on main help sign in
add base-desk
commitcfa67d5652d322fbec7769ed46b783fbfca369fa authorJohn Hyde <johnhydefour@gmail.com> dateThu 24 Mar 2022, 09:03 (5 years ago) parent971bd0b
91 files changed+14094
base-desk/lib/agentio.hoon+139 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+182 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+176 base-desk/lib/cram.hoon+61 base-desk/lib/dbug.hoon+155 base-desk/lib/default-agent.hoon+69 base-desk/lib/der.hoon+210 base-desk/lib/docket.hoon+223 base-desk/lib/ethereum.hoon+982 base-desk/lib/ethio.hoon+289 base-desk/lib/hark-store.hoon+233 base-desk/lib/jose.hoon+214 base-desk/lib/keygen.hoon+112 base-desk/lib/language-server/build.hoon+61 base-desk/lib/language-server/complete.hoon+386 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/ph/io.hoon+297 base-desk/lib/ph/util.hoon+112 base-desk/lib/pill.hoon+138 base-desk/lib/pkcs.hoon+378 base-desk/lib/primitive-rsa.hoon+84 base-desk/lib/ring.hoon+477 base-desk/lib/server.hoon+159 base-desk/lib/shoe.hoon+532 base-desk/lib/skeleton.hoon+51 base-desk/lib/sole.hoon+139 base-desk/lib/strand.hoon+188 base-desk/lib/strandio.hoon+761 base-desk/lib/test.hoon+50 base-desk/lib/verb.hoon+105 base-desk/mar/atom.hoon+18 base-desk/mar/belt.hoon+29 base-desk/mar/bill.hoon+34 base-desk/mar/blit.hoon+61 base-desk/mar/docket-0.hoon+25 base-desk/mar/hoon.hoon+49 base-desk/mar/htm.hoon+15 base-desk/mar/html.hoon+22 base-desk/mar/httr.hoon+25 base-desk/mar/hymn.hoon+17 base-desk/mar/js.hoon+22 base-desk/mar/json.hoon+26 base-desk/mar/json/rpc/response.hoon+43 base-desk/mar/kelvin.hoon+18 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+19 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+50 base-desk/mar/sole/effect.hoon+82 base-desk/mar/svg.hoon+12 base-desk/mar/tang.hoon+30 base-desk/mar/tape.hoon+12 base-desk/mar/txt-diff.hoon+16 base-desk/mar/txt.hoon+275 base-desk/mar/udon.hoon+32 base-desk/mar/umd.hoon+32 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/sur/aquarium.hoon+76 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+315 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+87 base-desk/sur/spider.hoon+14 base-desk/sur/verb.hoon+12
base-desk/lib/agentio.hoonnew file+139
@@ -0,0 +1,139 @@
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 %wait 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+ ++ connect
89+ |= [=binding:eyre app=term]
90+ (arvo %e %connect binding app)
91+ --
92+::
93+++ fact-curry
94+ |* [=mark =mold]
95+ |= [paths=(list path) fac=mold]
96+ (fact mark^!>(fac) paths)
97+::
98+++ fact-kick
99+ |= [=path =cage]
100+ ^- (list card)
101+ :~ (fact cage ~[path])
102+ (kick ~[path])
103+ ==
104+::
105+++ fact-init
106+ |= =cage
107+ ^- card
108+ [%give %fact ~ cage]
109+::
110+++ fact-init-kick
111+ |= =cage
112+ ^- (list card)
113+ :~ (fact cage ~)
114+ (kick ~)
115+ ==
116+::
117+++ fact
118+ |= [=cage paths=(list path)]
119+ ^- card
120+ [%give %fact paths cage]
121+::
122+++ fact-all
123+ |= =cage
124+ ^- (unit card)
125+ =/ paths=(set path)
126+ %- ~(gas in *(set path))
127+ %+ turn ~(tap by sup.bowl)
128+ |=([duct ship =path] path)
129+ ?: =(~ paths) ~
130+ `(fact cage ~(tap in paths))
131+::
132+++ kick
133+ |= paths=(list path)
134+ [%give %kick paths ~]
135+::
136+++ kick-only
137+ |= [=ship paths=(list path)]
138+ [%give %kick paths `ship]
139+--
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+ ++ ropsten-contracts
118+ |%
119+ ++ azimuth
120+ 0x308a.b6a6.024c.f198.b57e.008d.0ac9.ad02.1988.6579
121+ ::
122+ ++ ecliptic
123+ 0x8b9f.86a2.8921.d9c7.05b3.113a.755f.b979.e1bd.1bce
124+ ::
125+ ++ linear-star-release
126+ 0x1f8e.dd03.1ee4.1474.0aed.b39b.84fb.8f2f.66ca.422f
127+ ::
128+ ++ conditional-star-release
129+ 0x0
130+ ::
131+ ++ delegated-sending
132+ 0x3e8c.a510.354b.c2fd.bbd6.1502.52d9.3105.c9c2.7bbe
133+ ::
134+ ++ naive
135+ 0xe7cf.4b83.06d3.11ba.ca15.585f.e3f0.7cd0.441c.21d1
136+ ::
137+ ++ launch 4.601.630
138+ ++ public launch
139+ ++ chain-id 3
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-octt: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"] ~])
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+182
@@ -0,0 +1,182 @@
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+ ==
60+ :- (cat:byt ~[1^typ pubkey.h])
61+ %- cat:byt
62+ :~ fprint.h
63+ 1^`@ux`bipt.h 3^0x80
64+ coin-type 3^0x80
65+ 4^0x80
66+ 1^`@ux`chyg.h 3^0x0
67+ (flip:byt 4^idx.h)
68+ ==
69+ ::
70+ ++ keyval-byts
71+ |= kv=keyval:psbt
72+ ^- hexb
73+ %- cat:byt
74+ :~ 1^wid.key.kv
75+ key.kv
76+ 1^wid.val.kv
77+ val.kv
78+ ==
79+ ::
80+ ++ map-byts
81+ |= m=map:psbt
82+ ^- (unit hexb)
83+ ?~ m ~
84+ :- ~
85+ %- cat:byt
86+ (turn m keyval-byts)
87+ --
88+ ++ base64
89+ |= b=hexb
90+ ^- base64:psbt
91+ %- en:base64:mimes:html
92+ (flip:byt b)
93+:: +encode: make base64 cord of PSBT
94+:: - only-witness: don't include non-witness UTXO
95+::
96+++ encode
97+ |= $: only-witness=?
98+ rawtx=hexb
99+ txid=hexb
100+ inputs=(list in:psbt)
101+ outputs=(list out:psbt)
102+ ==
103+ ^- base64:psbt
104+ =/ sep=(unit hexb) `1^0x0
105+ =/ final=(list (unit hexb))
106+ %+ join sep
107+ %+ turn
108+ %- zing
109+ :~ ~[(globals:en rawtx)]
110+ (turn inputs (cury input:en only-witness))
111+ (turn outputs output:en)
112+ ==
113+ map-byts:en
114+ %- base64:en
115+ ^- byts
116+ %- cat:byt
117+ %+ weld ~[[5 0x70.7362.74ff]]
118+ (murn (snoc final sep) same)
119+::
120+++ parse
121+ |= psbt-base64=cord
122+ ^- (list map:psbt)
123+ =/ todo=hexb
124+ (drop:byt 5 (to-byts psbt-base64))
125+ =| acc=(list map:psbt)
126+ =| m=map:psbt
127+ |-
128+ ?: =(wid.todo 0)
129+ (snoc acc m)
130+ :: 0x0: map separator
131+ ::
132+ ?: =(1^0x0 (take:byt 1 todo))
133+ $(acc (snoc acc m), m *map:psbt, todo (drop:byt 1 todo))
134+ =^ kv todo (next-keyval todo)
135+ $(m (snoc m kv))
136+:: +get-txid: extract txid from a valid PSBT
137+::
138+++ get-txid
139+ |= psbt-base64=cord
140+ ^- hexb
141+ =/ tx=hexb
142+ %- raw-tx
143+ %+ drop:byt 5
144+ (to-byts psbt-base64)
145+ %- flip:byt
146+ (dsha256 tx)
147+:: +raw-tx: extract hex transaction
148+:: looks for key 0x0 in global map
149+:: crashes if tx not in hex
150+::
151+++ raw-tx
152+ |= b=hexb
153+ ^- hexb
154+ |-
155+ ?: =(wid.b 0) !!
156+ ?: =(1^0x0 (take:byt 1 b)) !!
157+ =/ nk (next-keyval b)
158+ ?: =(0x0 dat.key.kv.nk)
159+ val.kv.nk
160+ $(b rest.nk)
161+:: +next-keyval: returns next key-val in a PSBT map
162+:: input first byte must be a map key length
163+::
164+++ next-keyval
165+ |= b=hexb
166+ ^- [kv=keyval:psbt rest=hexb]
167+ =/ klen dat:(take:byt 1 b)
168+ =/ k (take:byt klen (drop:byt 1 b))
169+ =/ vlen dat:(take:byt 1 (drop:byt (add 1 klen) b))
170+ =/ v (take:byt vlen (drop:byt (add 2 klen) b))
171+ ?> ?&((gth wid.k 0) (gth wid.v 0))
172+ :- [k v]
173+ (drop:byt ;:(add 2 klen vlen) b)
174+::
175+++ to-byts
176+ |= psbt-base64=cord
177+ ^- hexb
178+ ~| "Invalid PSBT"
179+ =+ p=(de:base64:mimes:html psbt-base64)
180+ ?~ p !!
181+ (flip:byt u.p)
182+--
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+176
@@ -0,0 +1,176 @@
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 1) 1^a
147+ ?: =(l 2) (cat:byt ~[1^0xfd (flip:byt 2^a)])
148+ ?: (lte l 4) (cat:byt ~[1^0xfe (flip:byt 4^a)])
149+ ?: (lte l 8) (cat:byt ~[1^0xff (flip:byt 8^a)])
150+ ~|("Cannot encode CompactSize longer than 8 bytes" !!)
151+ ::
152+ ++ de
153+ ~/ %de
154+ |= h=hexb
155+ ^- [n=hexb rest=hexb]
156+ =/ s=@ux dat:(take:byt 1 h)
157+ ?: (lth s 0xfd) [1^s (drop:byt 1 h)]
158+ ~| "Invalid compact-size at start of {<h>}"
159+ =/ len=bloq
160+ ?+ s !!
161+ %0xfd 1
162+ %0xfe 2
163+ %0xff 3
164+ ==
165+ :_ (drop:byt (add 1 len) h)
166+ %- flip:byt
167+ (take:byt (bex len) (drop:byt 1 h))
168+ :: +dea: atom instead of hexb for parsed CompactSize
169+ ::
170+ ++ dea
171+ |= h=hexb
172+ ^- [a=@ rest=hexb]
173+ => (de h)
174+ [dat.n rest]
175+ --
176+--
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+155
@@ -0,0 +1,155 @@
1+:: dbug: agent wrapper for generic debugging tools
2+::
3+:: usage: %-(agent:dbug your-agent)
4+::
5+|%
6++$ poke
7+ $% [%bowl ~]
8+ [%state grab=cord]
9+ [%incoming =about]
10+ [%outgoing =about]
11+ ==
12+::
13++$ about
14+ $@ ~
15+ $% [%ship =ship]
16+ [%path =path]
17+ [%wire =wire]
18+ [%term =term]
19+ ==
20+::
21+++ agent
22+ |= =agent:gall
23+ ^- agent:gall
24+ !.
25+ |_ =bowl:gall
26+ +* this .
27+ ag ~(. agent bowl)
28+ ::
29+ ++ on-poke
30+ |= [=mark =vase]
31+ ^- (quip card:agent:gall agent:gall)
32+ ?. ?=(%dbug mark)
33+ =^ cards agent (on-poke:ag mark vase)
34+ [cards this]
35+ =/ dbug
36+ !<(poke vase)
37+ =; =tang
38+ ((%*(. slog pri 1) tang) [~ this])
39+ ?- -.dbug
40+ %bowl [(sell !>(bowl))]~
41+ ::
42+ %state
43+ =? grab.dbug =('' grab.dbug) '-'
44+ =; product=^vase
45+ [(sell product)]~
46+ =/ state=^vase
47+ :: if the underlying app has implemented a /dbug/state scry endpoint,
48+ :: use that vase in place of +on-save's.
49+ ::
50+ =/ result=(each ^vase tang)
51+ (mule |.(q:(need (need (on-peek:ag /x/dbug/state)))))
52+ ?:(?=(%& -.result) p.result on-save:ag)
53+ %+ slap
54+ (slop state !>([bowl=bowl ..zuse]))
55+ (ream grab.dbug)
56+ ::
57+ %incoming
58+ =; =tang
59+ ?^ tang tang
60+ [%leaf "no matching subscriptions"]~
61+ %+ murn
62+ %+ sort ~(tap by sup.bowl)
63+ |= [[* a=[=ship =path]] [* b=[=ship =path]]]
64+ (aor [path ship]:a [path ship]:b)
65+ |= [=duct [=ship =path]]
66+ ^- (unit tank)
67+ =; relevant=?
68+ ?. relevant ~
69+ `>[path=path from=ship duct=duct]<
70+ ?: ?=(~ about.dbug) &
71+ ?- -.about.dbug
72+ %ship =(ship ship.about.dbug)
73+ %path ?=(^ (find path.about.dbug path))
74+ %wire %+ lien duct
75+ |=(=wire ?=(^ (find wire.about.dbug wire)))
76+ %term !!
77+ ==
78+ ::
79+ %outgoing
80+ =; =tang
81+ ?^ tang tang
82+ [%leaf "no matching subscriptions"]~
83+ %+ murn
84+ %+ sort ~(tap by wex.bowl)
85+ |= [[[a=wire *] *] [[b=wire *] *]]
86+ (aor a b)
87+ |= [[=wire =ship =term] [acked=? =path]]
88+ ^- (unit tank)
89+ =; relevant=?
90+ ?. relevant ~
91+ `>[wire=wire agnt=[ship term] path=path ackd=acked]<
92+ ?: ?=(~ about.dbug) &
93+ ?- -.about.dbug
94+ %ship =(ship ship.about.dbug)
95+ %path ?=(^ (find path.about.dbug path))
96+ %wire ?=(^ (find wire.about.dbug wire))
97+ %term =(term term.about.dbug)
98+ ==
99+ ==
100+ ::
101+ ++ on-peek
102+ |= =path
103+ ^- (unit (unit cage))
104+ ?. ?=([@ %dbug *] path)
105+ (on-peek:ag path)
106+ ?+ path [~ ~]
107+ [%u %dbug ~] ``noun+!>(&)
108+ [%x %dbug %state ~] ``noun+!>(on-save:ag)
109+ [%x %dbug %subscriptions ~] ``noun+!>([wex sup]:bowl)
110+ ==
111+ ::
112+ ++ on-init
113+ ^- (quip card:agent:gall agent:gall)
114+ =^ cards agent on-init:ag
115+ [cards this]
116+ ::
117+ ++ on-save on-save:ag
118+ ::
119+ ++ on-load
120+ |= old-state=vase
121+ ^- (quip card:agent:gall agent:gall)
122+ =^ cards agent (on-load:ag old-state)
123+ [cards this]
124+ ::
125+ ++ on-watch
126+ |= =path
127+ ^- (quip card:agent:gall agent:gall)
128+ =^ cards agent (on-watch:ag path)
129+ [cards this]
130+ ::
131+ ++ on-leave
132+ |= =path
133+ ^- (quip card:agent:gall agent:gall)
134+ =^ cards agent (on-leave:ag path)
135+ [cards this]
136+ ::
137+ ++ on-agent
138+ |= [=wire =sign:agent:gall]
139+ ^- (quip card:agent:gall agent:gall)
140+ =^ cards agent (on-agent:ag wire sign)
141+ [cards this]
142+ ::
143+ ++ on-arvo
144+ |= [=wire =sign-arvo]
145+ ^- (quip card:agent:gall agent:gall)
146+ =^ cards agent (on-arvo:ag wire sign-arvo)
147+ [cards this]
148+ ::
149+ ++ on-fail
150+ |= [=term =tang]
151+ ^- (quip card:agent:gall agent:gall)
152+ =^ cards agent (on-fail:ag term tang)
153+ [cards this]
154+ --
155+--
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/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+982
@@ -0,0 +1,982 @@
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-octt (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-octt (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 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+++ address-to-hex
946+ |= a=address
947+ ^- tape
948+ %- prefix-hex
949+ (render-hex-bytes 20 `@`a)
950+::
951+++ transaction-to-hex
952+ |= h=@
953+ ^- tape
954+ %- prefix-hex
955+ (render-hex-bytes 32 h)
956+::
957+++ prefix-hex
958+ |= a=tape
959+ ^- tape
960+ ['0' 'x' a]
961+::
962+++ render-hex-bytes
963+ :: atom to string of hex bytes without 0x prefix and dots.
964+ |= a=octs
965+ ^- tape
966+ ((x-co:co (mul 2 p.a)) q.a)
967+::
968+++ pad-to-multiple
969+ |= [wat=tape mof=@ud wer=?(%left %right)]
970+ ^- tape
971+ =+ len=(lent wat)
972+ ?: =(0 len) (reap mof '0')
973+ =+ mad=(mod len mof)
974+ ?: =(0 mad) wat
975+ =+ tad=(reap (sub mof mad) '0')
976+ %- weld
977+ ?:(?=(%left wer) [tad wat] [wat tad])
978+::
979+++ hex-to-num
980+ |= a=@t
981+ (rash (rsh [3 2] a) hex)
982+--
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-octt: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+233
@@ -0,0 +1,233 @@
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+ :: TODO: fix +stab
175+ ::
176+ ++ pa
177+ |= j=json
178+ ^- path
179+ ?> ?=(%s -.j)
180+ ?: =('/' p.j) /
181+ (stab p.j)
182+ ::
183+ ++ place
184+ %- ot
185+ :~ desk+so
186+ path+pa
187+ ==
188+ ::
189+ ++ bin
190+ %- ot
191+ :~ path+pa
192+ place+place
193+ ==
194+ ::
195+ ++ read-each
196+ %- ot
197+ :~ place+place
198+ path+pa
199+ ==
200+ ::
201+ :: parse date as @ud
202+ :: TODO: move to zuse
203+ ++ sd
204+ |= jon=json
205+ ^- @da
206+ ?> ?=(%s -.jon)
207+ `@da`(rash p.jon dem:ag)
208+ ::
209+ ++ lid
210+ %- of
211+ :~ archive+sd
212+ unseen+ul
213+ seen+ul
214+ ==
215+ ::
216+ ++ archive
217+ %- ot
218+ :~ lid+lid
219+ bin+bin
220+ ==
221+ ::
222+ ++ action
223+ ^- $-(json ^action)
224+ %- of
225+ :~ archive-all+ul
226+ archive+archive
227+ opened+ul
228+ read-count+place
229+ read-each+read-each
230+ read-note+bin
231+ ==
232+ --
233+--
base-desk/lib/jose.hoonnew file+214
@@ -0,0 +1,214 @@
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+ =, en-json:html
37+ |= [val=json sor=$-(^ ?) rez=tape]
38+ ^- tape
39+ ?~ val (weld "null" rez)
40+ ?- -.val
41+ %a
42+ :- '['
43+ =. rez [']' rez]
44+ !.
45+ ?~ p.val rez
46+ |-
47+ ?~ t.p.val ^$(val i.p.val)
48+ ^$(val i.p.val, rez [',' $(p.val t.p.val)])
49+ ::
50+ %b (weld ?:(p.val "true" "false") rez)
51+ %n (weld (trip p.val) rez)
52+ %s
53+ :- '"'
54+ =. rez ['"' rez]
55+ =+ viz=(trip p.val)
56+ !.
57+ |- ^- tape
58+ ?~ viz rez
59+ =+ hed=(jesc i.viz)
60+ ?: ?=([@ ~] hed)
61+ [i.hed $(viz t.viz)]
62+ (weld hed $(viz t.viz))
63+ ::
64+ %o
65+ :- '{'
66+ =. rez ['}' rez]
67+ =/ viz
68+ %+ sort ~(tap by p.val)
69+ |=((pair) (sor (head p) (head q)))
70+ ?~ viz rez
71+ !.
72+ |- ^+ rez
73+ ?~ t.viz ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)])
74+ =. rez [',' $(viz t.viz)]
75+ ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)])
76+ ==
77+ --
78+:: %/lib/jose
79+::
80+:: |jwk: json representations of cryptographic keys (rfc7517)
81+::
82+:: Url-safe base64 encoding of key parameters in big-endian byte order.
83+:: RSA-only for now
84+::
85+++ jwk
86+ |%
87+ :: |en:jwk: encoding of json cryptographic keys
88+ ::
89+ ++ en
90+ => |%
91+ :: +numb:en:jwk: base64-url encode big-endian number
92+ ::
93+ ++ numb (corl en-base64url en:octn)
94+ --
95+ |%
96+ :: +pass:en:jwk: json encode public key
97+ ::
98+ ++ pass
99+ |= k=key:rsa
100+ ^- json
101+ [%o (my kty+s+'RSA' n+s+(numb n.pub.k) e+s+(numb e.pub.k) ~)]
102+ :: +ring:en:jwk: json encode private key
103+ ::
104+ ++ ring
105+ |= k=key:rsa
106+ ^- json
107+ ~| %rsa-need-ring
108+ ?> ?=(^ sek.k)
109+ :- %o %- my :~
110+ kty+s+'RSA'
111+ n+s+(numb n.pub.k)
112+ e+s+(numb e.pub.k)
113+ d+s+(numb d.u.sek.k)
114+ p+s+(numb p.u.sek.k)
115+ q+s+(numb q.u.sek.k)
116+ ==
117+ --
118+ :: |de:jwk: decoding of json cryptographic keys
119+ ::
120+ ++ de
121+ =, dejs-soft:format
122+ => |%
123+ :: +numb:de:jwk: parse base64-url big-endian number
124+ ::
125+ ++ numb (cu (cork de-base64url (lift de:octn)) so)
126+ --
127+ |%
128+ :: +pass:de:jwk: decode json public key
129+ ::
130+ ++ pass
131+ %+ ci
132+ =/ a (unit @ux)
133+ |= [kty=@t n=a e=a]
134+ ^- (unit key:rsa)
135+ =/ pub (both n e)
136+ ?~(pub ~ `[u.pub ~])
137+ (ot kty+(su (jest 'RSA')) n+numb e+numb ~)
138+ :: +ring:de:jwk: decode json private key
139+ ::
140+ ++ ring
141+ %+ ci
142+ =/ a (unit @ux)
143+ |= [kty=@t n=a e=a d=a p=a q=a]
144+ ^- (unit key:rsa)
145+ =/ pub (both n e)
146+ =/ sek :(both d p q)
147+ ?:(|(?=(~ pub) ?=(~ sek)) ~ `[u.pub sek])
148+ (ot kty+(su (jest 'RSA')) n+numb e+numb d+numb p+numb q+numb ~)
149+ --
150+ :: |thumb:jwk: "thumbprint" json-encoded key (rfc7638)
151+ ::
152+ ++ thumb
153+ |%
154+ :: +pass:thumb:jwk: thumbprint json-encoded public key
155+ ::
156+ ++ pass
157+ |= k=key:rsa
158+ (en-base64url 32 (shax (crip (en-json-sort aor (pass:en k)))))
159+ :: +ring:thumb:jwk: thumbprint json-encoded private key
160+ ::
161+ ++ ring !!
162+ --
163+ --
164+:: |jws: json web signatures (rfc7515)
165+::
166+:: Note: flattened signature form only.
167+::
168+++ jws
169+ |%
170+ :: +sign:jws: sign json value
171+ ::
172+ ++ sign
173+ |= [k=key:rsa pro=json lod=json]
174+ |^ ^- json
175+ =. pro header
176+ =/ protect=cord (encode pro)
177+ =/ payload=cord (encode lod)
178+ :- %o %- my :~
179+ protected+s+protect
180+ payload+s+payload
181+ signature+s+(sign protect payload)
182+ ==
183+ :: +header:sign:jws: set signature algorithm in header
184+ ::
185+ ++ header
186+ ?> ?=([%o *] pro)
187+ ^- json
188+ [%o (~(put by p.pro) %alg s+'RS256')]
189+ :: +encode:sign:jws: encode json for signing
190+ ::
191+ :: Alphabetically sort object keys, url-safe base64 encode
192+ :: the serialized json.
193+ ::
194+ ++ encode
195+ |= jon=json
196+ %- en-base64url
197+ %- as-octt:mimes:html
198+ (en-json-sort aor jon)
199+ :: +sign:sign:jws: compute signature
200+ ::
201+ :: Url-safe base64 encode in big-endian byte order.
202+ ::
203+ ++ sign
204+ |= [protect=cord payload=cord]
205+ =/ msg=@t (rap 3 ~[protect '.' payload])
206+ =/ sig=@ud (~(sign rs256 k) (met 3 msg) msg)
207+ =/ len=@ud (met 3 n.pub.k)
208+ (en-base64url len (rev 3 len sig))
209+ --
210+ :: +verify:jws: verify signature
211+ ::
212+ ++ verify !!
213+ --
214+--
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:crub:crypto 256 seed)
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+386
@@ -0,0 +1,386 @@
1+/+ language-server-parser
2+:: Autocomplete for hoon.
3+::
4+=/ debug |
5+|%
6++* option [item]
7+ [term=cord detail=item]
8+::
9+:: Like +rose except also produces line number
10+::
11+++ lily
12+ |* [los=tape sab=rule]
13+ =+ vex=(sab [[1 1] los])
14+ ?~ q.vex
15+ [%| p=p.vex(q (dec q.p.vex))]
16+ ?. =(~ q.q.u.q.vex)
17+ [%| p=p.vex(q (dec q.p.vex))]
18+ [%& p=p.u.q.vex]
19+::
20+:: Get all the identifiers accessible if this type is your subject.
21+::
22+++ get-identifiers
23+ |= ty=type
24+ %- flop
25+ |- ^- (list (option type))
26+ ?- ty
27+ %noun ~
28+ %void ~
29+ [%atom *] ~
30+ [%cell *]
31+ %+ weld
32+ $(ty p.ty)
33+ $(ty q.ty)
34+ ::
35+ [%core *]
36+ %- weld
37+ :_ ?. ?=(%gold r.p.q.ty)
38+ ~
39+ $(ty p.ty)
40+ ^- (list (option type))
41+ %- zing
42+ %+ turn ~(tap by q.r.q.ty)
43+ |= [term =tome]
44+ %+ turn
45+ ~(tap by q.tome)
46+ |= [name=term =hoon]
47+ ^- (pair term type)
48+ ~| term=term
49+ [name ~(play ~(et ut ty) ~[name] ~)]
50+ ::
51+ [%face *]
52+ ?^ p.ty
53+ ~
54+ [p.ty q.ty]~
55+ ::
56+ [%fork *]
57+ %= $
58+ ty
59+ =/ tines ~(tap in p.ty)
60+ ?~ tines
61+ %void
62+ |- ^- type
63+ ?~ t.tines
64+ i.tines
65+ (~(fuse ut $(tines t.tines)) i.tines)
66+ ==
67+ ::
68+ [%hint *] $(ty q.ty)
69+ [%hold *] $(ty ~(repo ut ty))
70+ ==
71+::
72+++ search-exact
73+ |* [sid=term options=(list (option))]
74+ =/ match
75+ %+ skim options
76+ |= [id=cord *]
77+ =(sid id)
78+ ?~ match
79+ ~
80+ [~ i.match]
81+::
82+:: Get all the identifiers that start with sid.
83+::
84+++ search-prefix
85+ |* [sid=cord ids=(list (option))]
86+ ^+ ids
87+ %+ skim ids
88+ |= [id=cord *]
89+ ^- ?(%.y %.n)
90+ =(sid (end [3 (met 3 sid)] id))
91+::
92+:: Get the longest prefix of a list of identifiers.
93+::
94+++ longest-match
95+ |= matches=(list (option))
96+ ^- cord
97+ ?~ matches
98+ ''
99+ =/ n 1
100+ =/ last (met 3 term.i.matches)
101+ |- ^- term
102+ ?: (gth n last)
103+ term.i.matches
104+ =/ prefix (end [3 n] term.i.matches)
105+ ?: |- ^- ?
106+ ?| ?=(~ t.matches)
107+ ?& =(prefix (end [3 n] term.i.t.matches))
108+ $(t.matches t.t.matches)
109+ == ==
110+ $(n +(n))
111+ (end [3 (dec n)] term.i.matches)
112+::
113+:: Run +find-type safely, printing the first line of the stack trace on
114+:: error.
115+::
116+++ find-type-mule
117+ |= [sut=type gen=hoon]
118+ ^- (unit [term type])
119+ =/ res (mule |.((find-type sut gen)))
120+ ?- -.res
121+ %& p.res
122+ %| ((slog (flop (scag 10 p.res))) ~)
123+ ==
124+::
125+:: Get the subject type of the wing where you've put the "magic-spoon".
126+::
127+++ find-type
128+ |= [sut=type gen=hoon]
129+ =* loop $
130+ |^
131+ ^- (unit [term type])
132+ ?- gen
133+ [%cnts [%magic-spoon ~] *] `['' sut]
134+ [%cnts [%magic-spoon @ ~] *] `[i.t.p.gen sut]
135+ [%cnts [%magic-spoon @ *] *]
136+ %= $
137+ sut (~(play ut sut) wing+t.t.p.gen)
138+ t.p.gen t.p.gen(t ~)
139+ ==
140+ ::
141+ [%cnts [%magic-fork @ ~] *]
142+ `['' (~(play ut sut) wing+t.p.gen)]
143+ ::
144+ [^ *] (both p.gen q.gen)
145+ [%brcn *] (grow q.gen)
146+ [%brpt *] (grow q.gen)
147+ [%cnts *]
148+ |- ^- (unit [term type])
149+ =* inner-loop $
150+ ?~ q.gen
151+ ~
152+ %+ replace
153+ loop(gen q.i.q.gen)
154+ |. inner-loop(q.gen t.q.gen)
155+ ::
156+ [%dtkt *] (spec-and-hoon p.gen q.gen)
157+ [%dtls *] loop(gen p.gen)
158+ [%rock *] ~
159+ [%sand *] ~
160+ [%tune *] ~
161+ [%dttr *] (both p.gen q.gen)
162+ [%dtts *] (both p.gen q.gen)
163+ [%dtwt *] loop(gen p.gen)
164+ [%hand *] ~
165+ [%ktbr *] loop(gen p.gen)
166+ [%ktls *] (both p.gen q.gen)
167+ [%ktpm *] loop(gen p.gen)
168+ [%ktsg *] loop(gen p.gen)
169+ [%ktwt *] loop(gen p.gen)
170+ [%note *] loop(gen q.gen)
171+ [%sgzp *] (both p.gen q.gen)
172+ [%sggr *] loop(gen q.gen) :: should check for hoon in p.gen
173+ [%tsgr *] (change p.gen q.gen)
174+ [%tscm *]
175+ %+ replace
176+ loop(gen p.gen)
177+ |.(loop(gen q.gen, sut (~(busk ut sut) p.gen)))
178+ ::
179+ [%wtcl *] (bell p.gen q.gen r.gen)
180+ [%fits *] (both p.gen wing+q.gen)
181+ [%wthx *] loop(gen wing+q.gen)
182+ [%dbug *] loop(gen q.gen)
183+ [%zpcm *] (both p.gen q.gen)
184+ [%lost *] loop(gen p.gen)
185+ [%zpmc *] (both p.gen q.gen)
186+ [%zpts *] loop(gen p.gen)
187+ [%zppt *] (both q.gen r.gen)
188+ [%zpgl *] (spec-and-hoon p.gen q.gen)
189+ [%zpzp *] ~
190+ *
191+ =+ doz=~(open ap gen)
192+ ?: =(doz gen)
193+ ~_ (show [%c 'hoon'] [%q gen])
194+ ~> %mean.'play-open'
195+ !!
196+ loop(gen doz)
197+ ==
198+ ::
199+ ++ replace
200+ |= [a=(unit [term type]) b=(trap (unit [term type]))]
201+ ^- (unit [term type])
202+ ?~(a $:b a)
203+ ::
204+ ++ both
205+ |= [a=hoon b=hoon]
206+ (replace loop(gen a) |.(loop(gen b)))
207+ ::
208+ ++ bell
209+ |= [a=hoon b=hoon c=hoon]
210+ %+ replace loop(gen a)
211+ |. %+ replace loop(gen b, sut (~(gain ut sut) a))
212+ |. loop(gen c, sut (~(lose ut sut) a))
213+ ::
214+ ++ spec-and-hoon
215+ |= [a=spec b=hoon]
216+ (replace (find-type-in-spec sut a) |.(loop(gen b)))
217+ ::
218+ ++ change
219+ |= [a=hoon b=hoon]
220+ (replace loop(gen a) |.(loop(gen b, sut (~(play ut sut) a))))
221+ ::
222+ ++ grow
223+ |= m=(map term tome)
224+ =/ tomes ~(tap by m)
225+ |- ^- (unit [term type])
226+ =* outer-loop $
227+ ?~ tomes
228+ ~
229+ =/ arms ~(tap by q.q.i.tomes)
230+ |- ^- (unit [term type])
231+ =* inner-loop $
232+ ?~ arms
233+ outer-loop(tomes t.tomes)
234+ %+ replace
235+ loop(gen q.i.arms, sut (~(play ut sut) gen))
236+ |. inner-loop(arms t.arms)
237+ --
238+::
239+:: Not implemented yet. I wonder whether we should modify types found
240+:: in spec mode such that if it's a mold that produces a type, it
241+:: should just display the type and not that it's technically a
242+:: function.
243+::
244+++ find-type-in-spec
245+ |= [sut=type pec=spec]
246+ ^- (unit [term type])
247+ ~
248+::
249+++ get-id-sym
250+ |= [pos=@ud =tape]
251+ %^ get-id pos tape
252+ ^- $-(nail (like (unit @t)))
253+ ;~(sfix (punt sym) (star ;~(pose prn (just `@`10))))
254+::
255+++ get-id-cord
256+ |= [pos=@ud =tape]
257+ %^ get-id pos tape
258+ ^- $-(nail (like (unit @t)))
259+ ;~(sfix (punt (cook crip (star prn))) (star ;~(pose prn (just `@`10))))
260+::
261+++ get-id
262+ |= [pos=@ud txt=tape seek=$-(nail (like (unit @t)))]
263+ ^- [forward=(unit @t) backward=(unit @t) id=(unit @t)]
264+ =/ forward=(unit @t)
265+ (scan (slag pos txt) seek)
266+ =/ backward=(unit @t)
267+ %- (lift |=(t=@t (swp 3 t)))
268+ (scan (flop (scag pos txt)) seek)
269+ =/ id=(unit @t)
270+ ?~ forward
271+ ?~ backward
272+ ~
273+ `u.backward
274+ ?~ backward
275+ `u.forward
276+ `(cat 3 u.backward u.forward)
277+ [forward backward id]
278+::
279+:: Insert magic marker in hoon source at the given position.
280+::
281+++ insert-magic
282+ |= [pos=@ud txt=tape]
283+ ^- [back-pos=@ud fore-pos=@ud txt=tape]
284+ :: Find beg-pos by searching backward to where the current term
285+ :: begins
286+ =+ (get-id-sym pos txt)
287+ =/ back-pos
288+ ?~ backward
289+ pos
290+ (sub pos (met 3 u.backward))
291+ =/ fore-pos
292+ ?~ forward
293+ pos
294+ (add pos (met 3 u.forward))
295+ :+ back-pos fore-pos
296+ :: Insert "magic-spoon" marker so +find-type can identify where to
297+ :: stop.
298+ ::
299+ ;: weld
300+ (scag back-pos txt)
301+ ?: &(?=(~ id) ?=([%'.' *] (slag pos txt)))
302+ "magic-fork"
303+ "magic-spoon"
304+ ?~ id
305+ ""
306+ "."
307+ (slag back-pos txt)
308+ "\0a"
309+ ==
310+::
311+:: Produce the longest possible advance without choosing between
312+:: matches.
313+::
314+:: Takes a +hoon which has already has a magic-spoon marker. Useful if
315+:: you want to handle your own parsing.
316+::
317+++ advance-hoon
318+ |= [sut=type gen=hoon]
319+ %+ bind (find-type-mule sut gen)
320+ |= [id=term typ=type]
321+ =/ matches=(list (option type))
322+ (search-prefix id (get-identifiers typ))
323+ (longest-match matches)
324+::
325+:: Same as +advance-hoon, but takes a position and text directly.
326+::
327+++ advance-tape
328+ |= [sut=type pos=@ud code=tape]
329+ (advance-hoon sut (scan txt:(insert-magic pos code) vest))
330+::
331+:: Produce a list of matches.
332+::
333+:: Takes a +hoon which has already has a magic-spoon marker. Useful if
334+:: you want to handle your own parsing.
335+::
336+++ tab-list-hoon
337+ |= [sut=type gen=hoon]
338+ ^- (unit (list (option type)))
339+ %+ bind (find-type-mule sut gen)
340+ |= [id=term typ=type]
341+ (search-prefix id (get-identifiers typ))
342+::
343+:: Same as +advance-hoon, but takes a position and text directly.
344+::
345+++ tab-list-tape
346+ |= [sut=type pos=@ud code=tape]
347+ ^- (each (unit (list (option type))) [row=@ col=@])
348+ ~? > debug %start-magick
349+ =/ magicked txt:(insert-magic pos code)
350+ ~? > debug %start-parsing
351+ =/ res (lily magicked (language-server-parser *path))
352+ ?: ?=(%| -.res)
353+ ~? > debug [%parsing-error p.res]
354+ [%| p.res]
355+ :- %&
356+ ~? > debug %parsed-good
357+ ((cury tab-list-hoon sut) hoon:`pile:clay`p.res)
358+::
359+:: Generators
360+++ tab-generators
361+ |= [pfix=path app=(unit term) gens=(list term)]
362+ ^- (list (option tank))
363+ %+ turn gens
364+ |= gen=term
365+ ^- (option tank)
366+ =/ pax=path
367+ (weld pfix ~[gen %hoon])
368+ =/ file
369+ .^(@t %cx pax)
370+ :_ (render-help file)
371+ ?~ app
372+ (cat 3 '+' gen)
373+ ?: =(%hood u.app)
374+ (cat 3 '|' gen)
375+ :((cury cat 3) ':' u.app '|' gen)
376+:: Stolen from +help
377+++ render-help
378+ |= a=@t
379+ ^- tank
380+ :- %leaf
381+ =/ c (to-wain:format a)
382+ ?~ c "~"
383+ ?. =(':: ' (end [3 4] i.c))
384+ "<undocumented>"
385+ (trip i.c)
386+--
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.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 q.+<))))
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-exists}
513+ $\{3:if-not-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/ph/io.hoonnew file+297
@@ -0,0 +1,297 @@
1+/- *aquarium, spider
2+/+ libstrand=strand, *strandio, util=ph-util
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+::
92+++ init
93+ =/ m (strand ,~)
94+ ^- form:m
95+ (send-azimuth-action %init-azimuth ~)
96+::
97+++ spawn
98+ |= =ship
99+ ~& > "spawning {<ship>}"
100+ =/ m (strand ,~)
101+ ^- form:m
102+ (send-azimuth-action %spawn ship)
103+::
104+++ breach
105+ |= =ship
106+ ~& > "breaching {<ship>}"
107+ =/ m (strand ,~)
108+ ^- form:m
109+ (send-azimuth-action %breach ship)
110+::
111+:: who: breachee
112+:: her: wait until hears about breach
113+::
114+++ breach-and-hear
115+ |= [who=ship her=ship]
116+ ~& > "breaching {<who>} for {<her>}"
117+ =/ m (strand ,~)
118+ ;< =bowl:spider bind:m get-bowl
119+ =/ aqua-pax
120+ :- %i
121+ /(scot %p her)/j/(scot %p her)/rift/(scot %da now.bowl)/(scot %p who)/noun
122+ =/ old-rut ;;((unit @) (scry-aqua:util noun our.bowl now.bowl aqua-pax))
123+ =/ new-rut
124+ ?~ old-rut
125+ 1
126+ +(+.old-rut)
127+ ;< ~ bind:m (send-azimuth-action %breach who)
128+ |- ^- form:m
129+ =* loop $
130+ ;< ~ bind:m (sleep ~s1)
131+ ;< =bowl:spider bind:m get-bowl
132+ =/ aqua-pax
133+ :- %i
134+ /(scot %p her)/j/(scot %p her)/rift/(scot %da now.bowl)/(scot %p who)/noun
135+ =/ rut (scry-aqua:util noun our.bowl now.bowl aqua-pax)
136+ ?: =([~ new-rut] rut)
137+ (pure:m ~)
138+ loop
139+::
140+++ init-ship
141+ |= [=ship fake=?]
142+ =/ m (strand ,~)
143+ ^- form:m
144+ ~& > "starting {<ship>}"
145+ ;< ~ bind:m (send-events (init:util ship fake))
146+ (check-ship-booted ship)
147+::
148+++ check-ship-booted
149+ |= =ship
150+ =/ m (strand ,~)
151+ ^- form:m
152+ =* loop $
153+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
154+ =/ f |=(=tape (is-dojo-output:util ship her unix-effect tape))
155+ :: This is a pretty bad heuristic, but in general galaxies will
156+ :: hit the first of these cases, and other ships will hit the
157+ :: second.
158+ ::
159+ ?: ?| (f ":dojo>")
160+ (f "is your neighbor")
161+ ==
162+ (pure:m ~)
163+ loop
164+::
165+++ dojo
166+ |= [=ship =tape]
167+ =/ m (strand ,~)
168+ ^- form:m
169+ ~& > "dojo: {tape}"
170+ (send-events (dojo:util ship tape))
171+::
172+++ wait-for-output
173+ |= [=ship =tape]
174+ =/ m (strand ,~)
175+ ^- form:m
176+ ~& > "waiting for output: {tape}"
177+ |- ^- form:m
178+ =* loop $
179+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
180+ ?: (is-dojo-output:util ship her unix-effect tape)
181+ (pure:m ~)
182+ loop
183+::
184+:: Send "|hi" from one ship to another
185+::
186+++ send-hi
187+ |= [from=@p to=@p]
188+ =/ m (strand ,~)
189+ ^- form:m
190+ ;< ~ bind:m (dojo from "|hi {(scow %p to)}")
191+ (wait-for-output from "hi {(scow %p to)} successful")
192+::
193+:: Send "|hi" and wait for "not responding" message
194+::
195+++ send-hi-not-responding
196+ |= [from=@p to=@p]
197+ ~& > 'sending hi not responding'
198+ =/ m (strand ,~)
199+ ;< ~ bind:m (dojo from "|hi {(scow %p to)}")
200+ (wait-for-output from "{(scow %p to)} not responding still trying")
201+::
202+:: Mount a desk.
203+::
204+++ mount
205+ |= [=ship =desk]
206+ =/ m (strand ,~)
207+ ^- form:m
208+ ;< ~ bind:m (dojo ship "|mount /={(trip desk)}=")
209+ |- ^- form:m
210+ =* loop $
211+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
212+ ?: (is-ergo:util ship her unix-effect)
213+ (pure:m ~)
214+ loop
215+::
216+:: Modify /sur/aquarium/hoon on the given ship
217+::
218+++ touch-file
219+ |= [her=ship =desk extra=@t]
220+ =/ m (strand ,@t)
221+ ^- form:m
222+ (touch her desk /sur/aquarium/hoon extra)
223+::
224+:: Modify path on the given ship
225+::
226+++ touch
227+ |= [her=ship =desk pax=path extra=@t]
228+ =/ m (strand ,@t)
229+ ^- form:m
230+ ~& > "touching file on {<her>}/{<desk>}"
231+ ;< ~ bind:m (mount her desk)
232+ ;< our=@p bind:m get-our
233+ ;< now=@da bind:m get-time
234+ =/ aqua-pax
235+ ;: weld
236+ /i/(scot %p her)/cx/(scot %p her)/[desk]/(scot %da now)
237+ pax
238+ /noun
239+ ==
240+ =/ warped
241+ %^ cat 3 '=> . '
242+ %^ cat 3 extra
243+ (need (scry-aqua:util (unit @) our now aqua-pax))
244+ ;< ~ bind:m (send-events (insert-files:util her desk [pax warped] ~))
245+ (pure:m warped)
246+::
247+:: Check /sur/aquarium/hoon on the given has the given contents.
248+::
249+++ check-file-touched
250+ |= [=ship =desk warped=@t]
251+ =/ m (strand ,~)
252+ (check-touched ship desk /sur/aquarium/hoon warped)
253+::
254+:: Check path on the given desk has the given contents.
255+::
256+++ check-touched
257+ |= [=ship =desk pax=path warped=@t]
258+ =/ m (strand ,~)
259+ ~& > "checking file touched on {<ship>}/{<desk>}"
260+ ;< ~ bind:m (mount ship desk)
261+ ^- form:m
262+ |- ^- form:m
263+ =* loop $
264+ ;< [her=^ship =unix-effect] bind:m take-unix-effect
265+ ;< our=@p bind:m get-our
266+ ;< now=@da bind:m get-time
267+ :: %ergo is no longer sufficient because .^ is pinned to beginning of
268+ :: the event. So we hope somebody sets a timer for something.
269+ ::
270+ ?. &(=(ship her) ?=(?(%init %ergo %doze) -.q.unix-effect))
271+ loop
272+ =/ aqua-pax
273+ ;: weld
274+ /i/(scot %p ship)/cx/(scot %p ship)/[desk]/(scot %da now)
275+ pax
276+ /noun
277+ ==
278+ ?: =(warped (need (scry-aqua:util (unit @) our now aqua-pax)))
279+ (pure:m ~)
280+ loop
281+::
282+:: Turns poke into a dojo command
283+::
284+++ poke-app
285+ |= [=ship app=term =mark data=*]
286+ =/ m (strand ,~)
287+ ^- form:m
288+ =/ command=tape ":{(trip app)} &{(trip mark)} {<data>}"
289+ (send-events (dojo:util ship command))
290+::
291+++ dojo-thread
292+ |= [=ship ted=term =mark data=*]
293+ =/ m (strand ,~)
294+ ^- form:m
295+ =/ command=tape "-{(trip ted)} &{(trip mark)} {<data>}"
296+ (send-events (dojo:util ship command))
297+--
base-desk/lib/ph/util.hoonnew file+112
@@ -0,0 +1,112 @@
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 fake=?]
20+ ^- (list aqua-event)
21+ [%init-ship who fake]~
22+::
23+:: Send dojo command
24+::
25+++ dojo
26+ |= [who=ship what=tape]
27+ ^- (list aqua-event)
28+ %+ send-events-to who
29+ ^- (list unix-event)
30+ :~
31+ [/d/term/1 %belt %ctl `@c`%e]
32+ [/d/term/1 %belt %ctl `@c`%u]
33+ [/d/term/1 %belt %txt ((list @c) what)]
34+ [/d/term/1 %belt %ret ~]
35+ ==
36+::
37+:: Control character
38+::
39+++ ctrl
40+ |= [who=ship what=term]
41+ ^- (list ph-event)
42+ %+ send-events-to who
43+ :~ [/d/term/1 %belt %ctl (,@c what)]
44+ ==
45+::
46+:: Inject a file into a ship
47+::
48+++ insert-files
49+ |= [who=ship des=desk files=(list [=path txt=@t])]
50+ ^- (list aqua-event)
51+ =/ input
52+ %+ turn files
53+ |= [=path txt=@t]
54+ [path ~ /text/plain (as-octs:mimes:html txt)]
55+ %+ send-events-to who
56+ :~
57+ [/c/sync/0v1n.2m9vh %into des | input]
58+ ==
59+::
60+:: Checks whether the given event is a dojo output blit containing the
61+:: given tape
62+::
63+++ is-dojo-output
64+ |= [who=ship her=ship uf=unix-effect what=tape]
65+ ?& =(who her)
66+ ?=(%blit -.q.uf)
67+ ::
68+ %+ lien p.q.uf
69+ |= =blit:dill
70+ ?. ?=(%lin -.blit)
71+ |
72+ !=(~ (find what p.blit))
73+ ==
74+::
75+:: Test is successful if +is-dojo-output
76+::
77+++ expect-dojo-output
78+ |= [who=ship her=ship uf=unix-effect what=tape]
79+ ^- (list ph-event)
80+ ?. (is-dojo-output who her uf what)
81+ ~
82+ [%test-done &]~
83+::
84+:: Check whether the given event is an ergo
85+::
86+++ is-ergo
87+ |= [who=ship her=ship uf=unix-effect]
88+ ?& =(who her)
89+ ?=(%ergo -.q.uf)
90+ ==
91+::
92+:: Check if given effect is an http request; extract
93+::
94+++ extract-request
95+ |= [uf=unix-effect dest=@t]
96+ ^- (unit [num=@ud =request:http])
97+ ?. ?=(%request -.q.uf) ~
98+ ?. =(dest url.request.q.uf) ~
99+ `[id.q.uf request.q.uf]
100+::
101+:: Scry into a running aqua ship
102+::
103+++ scry-aqua
104+ |* [a=mold our=@p now=@da pax=path]
105+ .^ a
106+ %gx
107+ (scot %p our)
108+ %aqua
109+ (scot %da now)
110+ pax
111+ ==
112+--
base-desk/lib/pill.hoonnew file+138
@@ -0,0 +1,138 @@
1+:: |pill: helper functions for making pills
2+::
3+/- dice
4+^?
5+|%
6+::
7++$ pill
8+ $% [%ivory p=(list)]
9+ $: %pill
10+ nam=term
11+ boot-ova=(list)
12+ kernel-ova=(list unix-event)
13+ userspace-ova=(list unix-event)
14+ == ==
15+::
16++$ unix-event
17+ %+ pair wire
18+ $% [%wack p=@]
19+ [%what p=(list (pair path (cask)))]
20+ [%whom p=ship]
21+ [%boot ? $%($>(%fake task:jael) $>(%dawn task:jael))]
22+ [%wyrd p=vere]
23+ [%verb p=(unit ?)]
24+ unix-task
25+ ==
26+:: +boot-ovum: boostrap kernel filesystem load
27+::
28+++ boot-ovum
29+ |= [hoon=cord arvo=cord]
30+ :~ //arvo
31+ %what
32+ [/sys/hoon hoon/hoon]
33+ [/sys/arvo hoon/arvo]
34+ ==
35+:: +file-ovum: userspace filesystem load
36+::
37+:: bas: full path to / directory
38+::
39+++ file-ovum
40+ =/ directories=(list path)
41+ :~ /app :: %gall applications
42+ /gen :: :dojo generators
43+ /lib :: libraries
44+ /mar :: mark definitions
45+ /sur :: structures
46+ /sys :: system files
47+ /ted :: :spider strands
48+ /web :: %eyre web content
49+ /desk :: desk manifest
50+ ==
51+ |= [des=desk bas=path]
52+ ^- unix-event
53+ %. directories
54+ |= :: sal: all spurs to load from
55+ ::
56+ sal=(list spur)
57+ ^- unix-event
58+ ::
59+ :: hav: all user files
60+ ::
61+ =; hav ~& user-files+(lent hav)
62+ =/ =yuki:clay
63+ :- *(list tako:clay)
64+ %- ~(gas by *(map path (each page:clay lobe:clay)))
65+ (turn hav |=([=path =page:clay] [path &+page]))
66+ [/c/sync [%park des &+yuki *rang:clay]]
67+ =| hav=(list [path page:clay])
68+ |- ^+ hav
69+ ?~ sal ~
70+ =. hav $(sal t.sal)
71+ ::
72+ :: tyl: spur
73+ ::
74+ =/ tyl i.sal
75+ |- ^+ hav
76+ ::
77+ :: pax: full path at `tyl`
78+ :: lon: directory at `tyl`
79+ ::
80+ =/ lyt (flop tyl)
81+ =/ pax (weld bas lyt)
82+ =/ lon .^(arch %cy pax)
83+ =? hav ?=(^ fil.lon)
84+ :_ hav
85+ :- lyt
86+ ?. ?=([%azimuth-snapshot *] tyl)
87+ [mark=;;(@tas (head tyl)) noun=.^(* %cx pax)]
88+ =; convert
89+ mime/(convert .^(snap-state:dice %cx pax))
90+ .^($-(snap-state:dice mime) %cf (weld bas /azimuth-snapshot/mime))
91+ =/ all ~(tap by dir.lon)
92+ |- ^+ hav
93+ ?~ all hav
94+ $(all t.all, hav ^$(tyl [p.i.all tyl]))
95+::
96+:: +file-ovum2: electric boogaloo
97+::
98+++ file-ovum2 |=(p=path `unix-event`[//arvo what/(user-files p)])
99+::
100+:: +user-files: all userspace hoon files
101+::
102+++ user-files
103+ |= bas=path
104+ %. directories:file-ovum
105+ |= sal=(list spur)
106+ ^- (list (pair path (cask)))
107+ ::
108+ :: hav: all user files
109+ ::
110+ =| hav=(list (pair path (cask)))
111+ |- ^+ hav
112+ ?~ sal ~
113+ =. hav $(sal t.sal)
114+ ::
115+ :: tyl: spur
116+ ::
117+ =/ tyl i.sal
118+ |- ^+ hav
119+ ::
120+ :: pax: full path at `tyl`
121+ :: lon: directory at `tyl`
122+ ::
123+ =/ pax (weld bas (flop tyl))
124+ =/ lon .^(arch %cy pax)
125+ =? hav ?=(^ fil.lon)
126+ ::
127+ :: install only hoon files for now
128+ ::
129+ ?. ?=([%hoon *] tyl)
130+ hav
131+ :_ hav
132+ [(flop `path`t.tyl) hoon/.^(@t %cx pax)]
133+ ::
134+ =/ all ~(tap by dir.lon)
135+ |- ^+ hav
136+ ?~ all hav
137+ $(all t.all, hav ^$(tyl [p.i.all tyl]))
138+--
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+477
@@ -0,0 +1,477 @@
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=@udpoint]
22+ ::
23+ =/ data=@ (mod link-scope l:ed:crypto)
24+ =/ h=@udpoint (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=@udpoint y=@udpoint])
34+ ::
35+ ?~ link-scope
36+ ~
37+ ::
38+ =+ [data=@ h=@udpoint]=(generate-public-linkage u.link-scope)
39+ =/ y=@udpoint (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=@udpoint
51+ :: high level universal state
52+ ::
53+ link-state=(unit [data=@ h=@udpoint y=@udpoint])
54+ :: point to include in challenge when link-state isn't ~
55+ ::
56+ h=(unit @udpoint)
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=@udpoint y=@udpoint])
78+ message=@
79+ public-keys=(list @udpoint)
80+ ss=(list @)
81+ ::
82+ prev-k=@u
83+ prev-s=@
84+ prev-ch=@
85+ challenges=(list @)
86+ ==
87+ ^- (list @)
88+ ::
89+ =/ gs=@udpoint
90+ %- add-scalarmult-scalarmult-base:ed:crypto :*
91+ prev-ch
92+ (snag prev-k public-keys)
93+ prev-s
94+ ==
95+ ::
96+ =/ hs=(unit @udpoint)
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=@udpoint y=@udpoint])]
129+ ^- (unit @udpoint)
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 @udpoint)
147+ my-public-key=@udpoint
148+ my-private-key=@udscalar
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=@udpoint y=@udpoint])
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 @udpoint)
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 @udpoint)
263+ ~(tap in anonymity-set)
264+ :: participants: length of :anonymity-list
265+ ::
266+ =/ participants=@u
267+ (lent anonymity-list)
268+ ::
269+ =/ z0p=@udpoint
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=@udpoint y=@udpoint])
279+ ?~ link-scope
280+ ~
281+ =+ [data=@ h=@udpoint]=(generate-public-linkage u.link-scope)
282+ :- ~
283+ [data h (need y.signature)]
284+ ::
285+ =/ z0pp=(unit @udpoint)
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 ^- @udscalar
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+ ^- @udpoint
351+ ::
352+ =/ d=[=^life =pass]
353+ =/ scry-path=path
354+ :~ %k
355+ (scot %p our)
356+ (scot %da now)
357+ (scot %p ship)
358+ (scot %ud life)
359+ ==
360+ .^([^life pass] scry-path)
361+ :: we have the deed which has pass, which is several numbers +cat-ed
362+ :: together; pull out the keys
363+ ::
364+ =/ x=[crypt=@ auth=@] (get-public-key-from-pass pass.d)
365+ ::
366+ `@udpoint`auth.x
367+ ::
368+ ++ build-signing-participants
369+ |= [our=@p now=@da invited=(list @p)]
370+ ^- [(set [@p life]) (set @udpoint)]
371+ ::
372+ =| participants=(set [@p life])
373+ =| keys=(set @udpoint)
374+ ::
375+ |-
376+ ?~ invited
377+ [participants keys]
378+ ::
379+ =/ =life
380+ .^(life k+/(scot %p our)/life/(scot %da now)/(scot %p i.invited))
381+ ::
382+ ?: =(life 0)
383+ $(invited t.invited)
384+ ::
385+ =/ pubkey=@udpoint (ship-life-to-pubid our now i.invited life)
386+ ::
387+ =. participants (~(put in participants) [i.invited life])
388+ =. keys (~(put in keys) pubkey)
389+ ::
390+ $(invited t.invited)
391+ ::
392+ ::
393+ ++ build-verifying-participants
394+ |= [our=@p now=@da invited=(list [ship=@p =life])]
395+ ^- (set @udpoint)
396+ ::
397+ =| keys=(set @udpoint)
398+ ::
399+ |-
400+ ?~ invited
401+ keys
402+ ::
403+ =/ pubkey=@udpoint
404+ (ship-life-to-pubid our now ship.i.invited life.i.invited)
405+ =. keys
406+ (~(put in keys) pubkey)
407+ ::
408+ $(invited t.invited)
409+ --
410+--
411+:: public interface
412+::
413+|%
414+:: +sign: ring-signs a message using the current ship
415+::
416+++ sign
417+ |= $: our=@p
418+ now=@da
419+ eny=@uvJ
420+ ::
421+ message=*
422+ link-scope=(unit *)
423+ anonymity-set=(set @p)
424+ ==
425+ ^- ring-signature
426+ :: if our is not in @p, we must be in @p.
427+ ::
428+ =. anonymity-set (~(put in anonymity-set) our)
429+ ::
430+ =/ msg-hash=@ (shaz (jam message))
431+ =/ link-hash=(unit @) (bind link-scope |=(a=* (shaz (jam a))))
432+ :: get everyone's public keys
433+ ::
434+ =/ p=[participants=(set [ship=@p =life]) keys=(set @udpoint)]
435+ (build-signing-participants:detail our now ~(tap in anonymity-set))
436+ :: get our ships' current life
437+ ::
438+ =/ our-life=life
439+ .^(life %k /(scot %p our)/life/(scot %da now)/(scot %p our))
440+ :: get our ships' secret keyfile ring
441+ ::
442+ =/ secret-ring=ring
443+ .^(ring %k /(scot %p our)/vein/(scot %da now)/(scot %ud our-life))
444+ :: fetch the encoded auth seed from the ring
445+ ::
446+ =/ secret-auth-seed=@
447+ +:(get-private-key-from-ring:detail secret-ring)
448+ :: get our ships' public key
449+ ::
450+ =/ public-key=@udpoint
451+ (ship-life-to-pubid:detail our now our our-life)
452+ ::
453+ :- participants.p
454+ :- link-scope
455+ %- sign:raw :*
456+ msg-hash
457+ link-hash
458+ keys.p
459+ public-key
460+ (seed-to-private-key-scalar:detail secret-auth-seed)
461+ eny
462+ ==
463+:: +verify: verifies a message against a ring signature
464+::
465+++ verify
466+ |= [our=@p now=@da message=* =ring-signature]
467+ ^- ?
468+ ::
469+ =/ keys=(set @udpoint)
470+ %^ build-verifying-participants:detail our now
471+ ~(tap in participants.ring-signature)
472+ ::
473+ =/ msg-hash=@ (shaz (jam message))
474+ =/ link-hash=(unit @) (bind link-scope.ring-signature |=(a=* (shaz (jam a))))
475+ ::
476+ (verify:raw msg-hash link-hash keys raw.ring-signature)
477+--
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-octt: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+532
@@ -0,0 +1,532 @@
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-0
17+ $: %0
18+ soles=(map @ta sole-share)
19+ ==
20+:: $card: standard gall cards plus shoe effects
21+::
22++$ card
23+ $% card:agent:gall
24+ [%shoe sole-ids=(list @ta) effect=shoe-effect] :: ~ sends to all soles
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=@ta
51+ |~(nail *(like [? command-type]))
52+ :: +tab-list: autocomplete options for the session (to match +command-parser)
53+ ::
54+ ++ tab-list
55+ |~ sole-id=@ta
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=@ta command=command-type]
62+ *(quip card _^|(..on-init))
63+ ::
64+ ++ can-connect
65+ |~ sole-id=@ta
66+ *?
67+ ::
68+ ++ on-connect
69+ |~ sole-id=@ta
70+ *(quip card _^|(..on-init))
71+ ::
72+ ++ on-disconnect
73+ |~ sole-id=@ta
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=@ta
123+ (easy *[? command-type])
124+ ::
125+ ++ tab-list
126+ |= sole-id=@ta
127+ ~
128+ ::
129+ ++ on-command
130+ |= [sole-id=@ta command=command-type]
131+ [~ shoe]
132+ ::
133+ ++ can-connect
134+ |= sole-id=@ta
135+ (team:title [our src]:bowl)
136+ ::
137+ ++ on-connect
138+ |= sole-id=@ta
139+ [~ shoe]
140+ ::
141+ ++ on-disconnect
142+ |= sole-id=@ta
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-0
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+ |= sole-id=@ta
168+ /sole/[sole-id]
169+ ::
170+ %table
171+ =; fez=(list sole-effect)
172+ $(effect.card [%sole %mor fez])
173+ =, +.effect.card
174+ :- (row:draw & wide head)
175+ %+ turn rows
176+ (cury (cury row:draw |) wide)
177+ ::
178+ %row
179+ $(effect.card [%sole (row:draw | +.effect.card)])
180+ ==
181+ --
182+ ::
183+ |_ =bowl:gall
184+ +* this .
185+ og ~(. shoe bowl)
186+ ::
187+ ++ on-init
188+ ^- (quip card:agent:gall agent:gall)
189+ =^ cards shoe on-init:og
190+ [(deal cards) this]
191+ ::
192+ ++ on-save !>([%shoe-app on-save:og state])
193+ ::
194+ ++ on-load
195+ |= old-state=vase
196+ ^- (quip card:agent:gall agent:gall)
197+ :: we could be upgrading from a shoe-less app, in which case the vase
198+ :: contains inner application state instead of our +on-save.
199+ :: to distinguish between the two, we check for the presence of our own
200+ :: +on-save tag in the vase.
201+ ::
202+ ?. ?=([%shoe-app ^] q.old-state)
203+ =^ cards shoe (on-load:og old-state)
204+ [(deal cards) this]
205+ =^ old-inner state +:!<([%shoe-app vase state-0] old-state)
206+ =^ cards shoe (on-load:og old-inner)
207+ [(deal cards) this]
208+ ::
209+ ++ on-poke
210+ |= [=mark =vase]
211+ ^- (quip card:agent:gall agent:gall)
212+ ?. ?=(%sole-action mark)
213+ =^ cards shoe (on-poke:og mark vase)
214+ [(deal cards) this]
215+ ::
216+ =/ act !<(sole-action vase)
217+ =* sole-id id.act
218+ =/ cli-state=sole-share
219+ (~(gut by soles) sole-id *sole-share)
220+ |^ =^ [cards=(list card) =_cli-state] shoe
221+ ?- -.dat.act
222+ %det (apply-edit +.dat.act)
223+ %clr [[~ cli-state] shoe]
224+ %ret try-command
225+ %tab [(tab +.dat.act) shoe]
226+ ==
227+ :- (deal cards)
228+ this(soles (~(put by soles) sole-id cli-state))
229+ ::
230+ ++ effect
231+ |= =sole-effect
232+ ^- card
233+ [%shoe [sole-id]~ %sole sole-effect]
234+ ::
235+ ++ apply-edit
236+ |= =sole-change
237+ ^+ [[*(list card) cli-state] shoe]
238+ =^ inverse cli-state
239+ (~(transceive sole cli-state) sole-change)
240+ :: res: & for fully parsed, | for parsing failure at location
241+ ::
242+ =/ res=(each (unit [run=? cmd=command-type]) @ud)
243+ %+ rose (tufa buf.cli-state)
244+ (command-parser:og sole-id)
245+ ?: ?=(%& -.res)
246+ :: only auto-run eligible commands if they were typed out
247+ :: (that is, not retrieved from command history)
248+ ::
249+ ?. &(?=(^ p.res) run.u.p.res !?=(%set -.ted.sole-change))
250+ [[~ cli-state] shoe]
251+ (run-command cmd.u.p.res)
252+ :_ shoe
253+ :: parsing failed
254+ ::
255+ ?. &(?=(%del -.inverse) =(+(p.inverse) (lent buf.cli-state)))
256+ :: if edit was somewhere in the middle, let it happen anyway
257+ ::
258+ [~ cli-state]
259+ :: if edit was insertion at buffer tail, revert it
260+ ::
261+ =^ undo cli-state
262+ (~(transmit sole cli-state) inverse)
263+ :_ cli-state
264+ :_ ~
265+ %+ effect %mor
266+ :~ [%det undo] :: undo edit
267+ [%err p.res] :: cursor to error location
268+ ==
269+ ::
270+ ++ try-command
271+ ^+ [[*(list card) cli-state] shoe]
272+ =/ res=(unit [? cmd=command-type])
273+ %+ rust (tufa buf.cli-state)
274+ (command-parser:og sole-id)
275+ ?^ res (run-command cmd.u.res)
276+ [[[(effect %bel ~)]~ cli-state] shoe]
277+ ::
278+ ++ run-command
279+ |= cmd=command-type
280+ ^+ [[*(list card) cli-state] shoe]
281+ =^ cards shoe (on-command:og sole-id cmd)
282+ :: clear buffer
283+ ::
284+ =^ clear cli-state (~(transmit sole cli-state) [%set ~])
285+ =- [[[- cards] cli-state] shoe]
286+ %+ effect %mor
287+ :~ [%nex ~]
288+ [%det clear]
289+ ==
290+ ::
291+ ++ tab
292+ |= pos=@ud
293+ ^- (quip card _cli-state)
294+ =+ (get-id-cord:auto pos (tufa buf.cli-state))
295+ =/ needle=term
296+ (fall id %$)
297+ :: autocomplete empty command iff user at start of command
298+ ::
299+ =/ options=(list (option:auto tank))
300+ (search-prefix:auto needle (tab-list:og sole-id))
301+ =/ advance=term
302+ (longest-match:auto options)
303+ =/ to-send=tape
304+ %- trip
305+ (rsh [3 (met 3 needle)] advance)
306+ =/ send-pos=@ud
307+ %+ add pos
308+ (met 3 (fall forward ''))
309+ =| cards=(list card)
310+ :: only render the option list if we couldn't complete anything
311+ ::
312+ =? cards &(?=(~ to-send) ?=(^ options))
313+ [(effect %tab options) cards]
314+ |- ^- (quip card _cli-state)
315+ ?~ to-send
316+ [(flop cards) cli-state]
317+ =^ char cli-state
318+ (~(transmit sole cli-state) [%ins send-pos `@c`i.to-send])
319+ %_ $
320+ cards [(effect %det char) cards]
321+ send-pos +(send-pos)
322+ to-send t.to-send
323+ ==
324+ --
325+ ::
326+ ++ on-watch
327+ |= =path
328+ ^- (quip card:agent:gall agent:gall)
329+ ?. ?=([%sole @ ~] path)
330+ =^ cards shoe
331+ (on-watch:og path)
332+ [(deal cards) this]
333+ =* sole-id i.t.path
334+ ?> (can-connect:og sole-id)
335+ =. soles (~(put by soles) sole-id *sole-share)
336+ =^ cards shoe
337+ (on-connect:og sole-id)
338+ :_ this
339+ %- deal
340+ :_ cards
341+ [%shoe [sole-id]~ %sole %pro & dap.bowl "> "]
342+ ::
343+ ++ on-leave
344+ |= =path
345+ ^- (quip card:agent:gall agent:gall)
346+ =^ cards shoe (on-leave:og path)
347+ [(deal cards) this]
348+ ::
349+ ++ on-peek
350+ |= =path
351+ ^- (unit (unit cage))
352+ ?. =(/x/dbug/state path) (on-peek:og path)
353+ ``noun+(slop on-save:og !>(shoe=state))
354+ ::
355+ ++ on-agent
356+ |= [=wire =sign:agent:gall]
357+ ^- (quip card:agent:gall agent:gall)
358+ =^ cards shoe (on-agent:og wire sign)
359+ [(deal cards) this]
360+ ::
361+ ++ on-arvo
362+ |= [=wire =sign-arvo]
363+ ^- (quip card:agent:gall agent:gall)
364+ =^ cards shoe (on-arvo:og wire sign-arvo)
365+ [(deal cards) this]
366+ ::
367+ ++ on-fail
368+ |= [=term =tang]
369+ ^- (quip card:agent:gall agent:gall)
370+ =^ cards shoe (on-fail:og term tang)
371+ [(deal cards) this]
372+ --
373+::
374+++ draw
375+ |%
376+ ++ row
377+ |= [bold=? wide=(list @ud) cols=(list dime)]
378+ ^- sole-effect
379+ :- %mor
380+ ^- (list sole-effect)
381+ =/ cows=(list [wid=@ud col=dime])
382+ %- head
383+ %^ spin cols wide
384+ |= [col=dime wiz=(list @ud)]
385+ ~| [%too-few-wide col]
386+ ?> ?=(^ wiz)
387+ [[i.wiz col] t.wiz]
388+ =/ cobs=(list [wid=@ud (list tape)])
389+ (turn cows col-as-lines)
390+ =+ [lin=0 any=|]
391+ =| fez=(list sole-effect)
392+ |- ^+ fez
393+ =; out=tape
394+ :: done when we're past the end of all columns
395+ ::
396+ ?: (levy out (cury test ' '))
397+ (flop fez)
398+ =; fec=sole-effect
399+ $(lin +(lin), fez [fec fez])
400+ ?. bold txt+out
401+ klr+[[`%br ~ ~]^[(crip out)]~]~
402+ %+ roll cobs
403+ |= [[wid=@ud lines=(list tape)] out=tape]
404+ %+ weld out
405+ %+ weld ?~(out "" " ")
406+ =+ l=(swag [lin 1] lines)
407+ ?^(l i.l (reap wid ' '))
408+ ::
409+ ++ col-as-lines
410+ |= [wid=@ud col=dime]
411+ ^- [@ud (list tape)]
412+ :- wid
413+ %+ turn
414+ (break wid (col-as-text col) (break-sets -.col))
415+ (cury (cury pad wid) (alignment -.col))
416+ ::
417+ ++ col-as-text
418+ |= col=dime
419+ ^- tape
420+ ?+ p.col (scow col)
421+ %t (trip q.col)
422+ %tas ['%' (scow col)]
423+ ==
424+ ::
425+ ++ alignment
426+ |= wut=@ta
427+ ^- ?(%left %right)
428+ ?: ?=(?(%t %ta %tas %da) wut)
429+ %left
430+ %right
431+ ::
432+ ++ break-sets
433+ |= wut=@ta
434+ :: for: may break directly before these characters
435+ :: aft: may break directly after these characters
436+ :: new: always break on these characters, consuming them
437+ ::
438+ ^- [for=(set @t) aft=(set @t) new=(set @t)]
439+ ?+ wut [(sy " ") (sy ".:-/") (sy "\0a")]
440+ ?(%p %q) [(sy "-") (sy "-") ~]
441+ %ux [(sy ".") ~ ~]
442+ ==
443+ ::
444+ ++ break
445+ |= [wid=@ud cot=tape brs=_*break-sets]
446+ ^- (list tape)
447+ ~| [wid cot]
448+ ?: =("" cot) ~
449+ =; [lin=tape rem=tape]
450+ [lin $(cot rem)]
451+ :: take snip of max width+1, search for breakpoint on that.
452+ :: we grab one char extra, to look-ahead for for.brs.
453+ :: later on, we always transfer _at least_ the extra char.
454+ ::
455+ =^ lin=tape cot
456+ [(scag +(wid) cot) (slag +(wid) cot)]
457+ =+ len=(lent lin)
458+ :: find the first newline character
459+ ::
460+ =/ new=(unit @ud)
461+ =+ new=~(tap in new.brs)
462+ =| las=(unit @ud)
463+ |-
464+ ?~ new las
465+ $(new t.new, las (hunt lth las (find [i.new]~ lin)))
466+ :: if we found a newline, break on it
467+ ::
468+ ?^ new
469+ :- (scag u.new lin)
470+ (weld (slag +(u.new) lin) cot)
471+ :: if it fits, we're done
472+ ::
473+ ?: (lte len wid)
474+ [lin cot]
475+ =+ nil=(flop lin)
476+ :: search for latest aft match
477+ ::
478+ =/ aft=(unit @ud)
479+ :: exclude the look-ahead character from search
480+ ::
481+ =. len (dec len)
482+ =. nil (slag 1 nil)
483+ =- ?~(- ~ `+(u.-))
484+ ^- (unit @ud)
485+ =+ aft=~(tap in aft.brs)
486+ =| las=(unit @ud)
487+ |-
488+ ?~ aft (bind las (cury sub (dec len)))
489+ $(aft t.aft, las (hunt lth las (find [i.aft]~ nil)))
490+ :: search for latest for match
491+ ::
492+ =/ for=(unit @ud)
493+ =+ for=~(tap in for.brs)
494+ =| las=(unit @ud)
495+ |-
496+ ?~ for (bind las (cury sub (dec len)))
497+ =- $(for t.for, las (hunt lth las -))
498+ =+ (find [i.for]~ nil)
499+ :: don't break before the first character
500+ ::
501+ ?:(=(`(dec len) -) ~ -)
502+ :: if any result, break as late as possible
503+ ::
504+ =+ brk=(hunt gth aft for)
505+ ?~ brk
506+ :: lin can't break, produce it in its entirety
507+ :: (after moving the look-ahead character back)
508+ ::
509+ :- (scag wid lin)
510+ (weld (slag wid lin) cot)
511+ :- (scag u.brk lin)
512+ =. cot (weld (slag u.brk lin) cot)
513+ :: eat any leading whitespace the next line might have, "clean break"
514+ ::
515+ |- ^+ cot
516+ ?~ cot ~
517+ ?. ?=(?(%' ' %'\09') i.cot)
518+ cot
519+ $(cot t.cot)
520+ ::
521+ ++ pad
522+ |= [wid=@ud lyn=?(%left %right) lin=tape]
523+ ^+ lin
524+ =+ l=(lent lin)
525+ ?: (gte l wid) lin
526+ =+ p=(reap (sub wid l) ' ')
527+ ?- lyn
528+ %left (weld lin p)
529+ %right (weld p lin)
530+ ==
531+ --
532+--
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+139
@@ -0,0 +1,139 @@
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+--
base-desk/lib/strand.hoonnew file+188
@@ -0,0 +1,188 @@
1+|%
2++$ card card:agent:gall
3++$ input
4+ $% [%poke =cage]
5+ [%sign =wire =sign-arvo]
6+ [%agent =wire =sign:agent:gall]
7+ [%watch =path]
8+ ==
9++$ strand-input [=bowl in=(unit input)]
10++$ tid @tatid
11++$ bowl
12+ $: our=ship
13+ src=ship
14+ tid=tid
15+ mom=(unit tid)
16+ wex=boat:gall
17+ sup=bitt:gall
18+ eny=@uvJ
19+ now=@da
20+ byk=beak
21+ ==
22+::
23+:: cards: cards to send immediately. These will go out even if a
24+:: later stage of the computation fails, so they shouldn't have
25+:: any semantic effect on the rest of the system.
26+:: Alternately, they may record an entry in contracts with
27+:: enough information to undo the effect if the computation
28+:: fails.
29+:: wait: don't move on, stay here. The next sign should come back
30+:: to this same callback.
31+:: skip: didn't expect this input; drop it down to be handled
32+:: elsewhere
33+:: cont: continue computation with new callback.
34+:: fail: abort computation; don't send effects
35+:: done: finish computation; send effects
36+::
37+++ strand-output-raw
38+ |* a=mold
39+ $~ [~ %done *a]
40+ $: cards=(list card)
41+ $= next
42+ $% [%wait ~]
43+ [%skip ~]
44+ [%cont self=(strand-form-raw a)]
45+ [%fail err=(pair term tang)]
46+ [%done value=a]
47+ ==
48+ ==
49+::
50+++ strand-form-raw
51+ |* a=mold
52+ $-(strand-input (strand-output-raw a))
53+::
54+:: Abort strand computation with error message
55+::
56+++ strand-fail
57+ |= err=(pair term tang)
58+ |= strand-input
59+ [~ %fail err]
60+::
61+:: Asynchronous transcaction monad.
62+::
63+:: Combo of four monads:
64+:: - Reader on input
65+:: - Writer on card
66+:: - Continuation
67+:: - Exception
68+::
69+++ strand
70+ |* a=mold
71+ |%
72+ ++ output (strand-output-raw a)
73+ ::
74+ :: Type of an strand computation.
75+ ::
76+ ++ form (strand-form-raw a)
77+ ::
78+ :: Monadic pure. Identity computation for bind.
79+ ::
80+ ++ pure
81+ |= arg=a
82+ ^- form
83+ |= strand-input
84+ [~ %done arg]
85+ ::
86+ :: Monadic bind. Combines two computations, associatively.
87+ ::
88+ ++ bind
89+ |* b=mold
90+ |= [m-b=(strand-form-raw b) fun=$-(b form)]
91+ ^- form
92+ |= input=strand-input
93+ =/ b-res=(strand-output-raw b)
94+ (m-b input)
95+ ^- output
96+ :- cards.b-res
97+ ?- -.next.b-res
98+ %wait [%wait ~]
99+ %skip [%skip ~]
100+ %cont [%cont ..$(m-b self.next.b-res)]
101+ %fail [%fail err.next.b-res]
102+ %done [%cont (fun value.next.b-res)]
103+ ==
104+ ::
105+ :: The strand monad must be evaluted in a particular way to maintain
106+ :: its monadic character. +take:eval implements this.
107+ ::
108+ ++ eval
109+ |%
110+ :: Indelible state of a strand
111+ ::
112+ +$ eval-form
113+ $: =form
114+ ==
115+ ::
116+ :: Convert initial form to eval-form
117+ ::
118+ ++ from-form
119+ |= =form
120+ ^- eval-form
121+ form
122+ ::
123+ :: The cases of results of +take
124+ ::
125+ +$ eval-result
126+ $% [%next ~]
127+ [%fail err=(pair term tang)]
128+ [%done value=a]
129+ ==
130+ ::
131+ ++ validate-mark
132+ |= [in=* =mark =bowl]
133+ ^- cage
134+ =+ .^ =dais:clay %cb
135+ /(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/[mark]
136+ ==
137+ =/ res (mule |.((vale.dais in)))
138+ ?: ?=(%| -.res)
139+ ~|(%spider-mark-fail (mean leaf+"spider: ames vale fail {<mark>}" p.res))
140+ [mark p.res]
141+ ::
142+ :: Take a new sign and run the strand against it
143+ ::
144+ ++ take
145+ :: cards: accumulate throughout recursion the cards to be
146+ :: produced now
147+ =| cards=(list card)
148+ |= [=eval-form =strand-input]
149+ ^- [[(list card) =eval-result] _eval-form]
150+ =* take-loop $
151+ =. in.strand-input
152+ ?~ in.strand-input ~
153+ =/ in u.in.strand-input
154+ ?. ?=(%agent -.in) `in
155+ ?. ?=(%fact -.sign.in) `in
156+ ::
157+ :- ~
158+ :+ %agent wire.in
159+ [%fact (validate-mark q.q.cage.sign.in p.cage.sign.in bowl.strand-input)]
160+ :: run the strand callback
161+ ::
162+ =/ =output (form.eval-form strand-input)
163+ :: add cards to cards
164+ ::
165+ =. cards
166+ %+ welp
167+ cards
168+ :: XX add tag to wires?
169+ cards.output
170+ :: case-wise handle next steps
171+ ::
172+ ?- -.next.output
173+ %wait [[cards %next ~] eval-form]
174+ %skip [[cards %next ~] eval-form]
175+ %fail [[cards %fail err.next.output] eval-form]
176+ %done [[cards %done value.next.output] eval-form]
177+ %cont
178+ :: recurse to run continuation with initialization input
179+ ::
180+ %_ take-loop
181+ form.eval-form self.next.output
182+ strand-input [bowl.strand-input ~]
183+ ==
184+ ==
185+ --
186+ --
187+--
188+::
base-desk/lib/strandio.hoonnew file+761
@@ -0,0 +1,761 @@
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+ ~ `[%wait ~]
77+ [~ %poke @ *]
78+ ?. =(mark p.cage.u.in.tin)
79+ `[%skip ~]
80+ `[%done q.cage.u.in.tin]
81+ ==
82+::
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+ ~ `[%wait ~]
91+ [~ %sign *]
92+ `[%done [wire sign-arvo]:u.in.tin]
93+ ==
94+::
95+:: Wait for a subscription update on a wire
96+::
97+++ take-fact-prefix
98+ |= =wire
99+ =/ m (strand ,[path cage])
100+ ^- form:m
101+ |= tin=strand-input:strand
102+ ?+ in.tin `[%skip ~]
103+ ~ `[%wait ~]
104+ [~ %agent * %fact *]
105+ ?. =(watch+wire (scag +((lent wire)) wire.u.in.tin))
106+ `[%skip ~]
107+ `[%done (slag (lent wire) wire.u.in.tin) cage.sign.u.in.tin]
108+ ==
109+::
110+:: Wait for a subscription update on a wire
111+::
112+++ take-fact
113+ |= =wire
114+ =/ m (strand ,cage)
115+ ^- form:m
116+ |= tin=strand-input:strand
117+ ?+ in.tin `[%skip ~]
118+ ~ `[%wait ~]
119+ [~ %agent * %fact *]
120+ ?. =(watch+wire wire.u.in.tin)
121+ `[%skip ~]
122+ `[%done cage.sign.u.in.tin]
123+ ==
124+::
125+:: Wait for a subscription close
126+::
127+++ take-kick
128+ |= =wire
129+ =/ m (strand ,~)
130+ ^- form:m
131+ |= tin=strand-input:strand
132+ ?+ in.tin `[%skip ~]
133+ ~ `[%wait ~]
134+ [~ %agent * %kick *]
135+ ?. =(watch+wire wire.u.in.tin)
136+ `[%skip ~]
137+ `[%done ~]
138+ ==
139+::
140+++ echo
141+ =/ m (strand ,~)
142+ ^- form:m
143+ %- (main-loop ,~)
144+ :~ |= ~
145+ ^- form:m
146+ ;< =vase bind:m ((handle ,vase) (take-poke %echo))
147+ =/ message=tape !<(tape vase)
148+ %- (slog leaf+"{message}..." ~)
149+ ;< ~ bind:m (sleep ~s2)
150+ %- (slog leaf+"{message}.." ~)
151+ (pure:m ~)
152+ ::
153+ |= ~
154+ ^- form:m
155+ ;< =vase bind:m ((handle ,vase) (take-poke %over))
156+ %- (slog leaf+"over..." ~)
157+ (pure:m ~)
158+ ==
159+::
160+++ take-watch
161+ =/ m (strand ,path)
162+ |= tin=strand-input:strand
163+ ?+ in.tin `[%skip ~]
164+ ~ `[%wait ~]
165+ [~ %watch *]
166+ `[%done path.u.in.tin]
167+ ==
168+::
169+++ take-wake
170+ |= until=(unit @da)
171+ =/ m (strand ,~)
172+ ^- form:m
173+ |= tin=strand-input:strand
174+ ?+ in.tin `[%skip ~]
175+ ~ `[%wait ~]
176+ [~ %sign [%wait @ ~] %behn %wake *]
177+ ?. |(?=(~ until) =(`u.until (slaw %da i.t.wire.u.in.tin)))
178+ `[%skip ~]
179+ ?~ error.sign-arvo.u.in.tin
180+ `[%done ~]
181+ `[%fail %timer-error u.error.sign-arvo.u.in.tin]
182+ ==
183+::
184+++ take-poke-ack
185+ |= =wire
186+ =/ m (strand ,~)
187+ ^- form:m
188+ |= tin=strand-input:strand
189+ ?+ in.tin `[%skip ~]
190+ ~ `[%wait ~]
191+ [~ %agent * %poke-ack *]
192+ ?. =(wire wire.u.in.tin)
193+ `[%skip ~]
194+ ?~ p.sign.u.in.tin
195+ `[%done ~]
196+ `[%fail %poke-fail u.p.sign.u.in.tin]
197+ ==
198+::
199+++ take-watch-ack
200+ |= =wire
201+ =/ m (strand ,~)
202+ ^- form:m
203+ |= tin=strand-input:strand
204+ ?+ in.tin `[%skip ~]
205+ ~ `[%wait ~]
206+ [~ %agent * %watch-ack *]
207+ ?. =(watch+wire wire.u.in.tin)
208+ `[%skip ~]
209+ ?~ p.sign.u.in.tin
210+ `[%done ~]
211+ `[%fail %watch-ack-fail u.p.sign.u.in.tin]
212+ ==
213+::
214+++ poke
215+ |= [=dock =cage]
216+ =/ m (strand ,~)
217+ ^- form:m
218+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
219+ ;< ~ bind:m (send-raw-card card)
220+ (take-poke-ack /poke)
221+::
222+++ raw-poke
223+ |= [=dock =cage]
224+ =/ m (strand ,~)
225+ ^- form:m
226+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
227+ ;< ~ bind:m (send-raw-card card)
228+ =/ m (strand ,~)
229+ ^- form:m
230+ |= tin=strand-input:strand
231+ ?+ in.tin `[%skip ~]
232+ ~
233+ `[%wait ~]
234+ ::
235+ [~ %agent * %poke-ack *]
236+ ?. =(/poke wire.u.in.tin)
237+ `[%skip ~]
238+ `[%done ~]
239+ ==
240+::
241+++ raw-poke-our
242+ |= [app=term =cage]
243+ =/ m (strand ,~)
244+ ^- form:m
245+ ;< =bowl:spider bind:m get-bowl
246+ (raw-poke [our.bowl app] cage)
247+::
248+++ poke-our
249+ |= [=term =cage]
250+ =/ m (strand ,~)
251+ ^- form:m
252+ ;< our=@p bind:m get-our
253+ (poke [our term] cage)
254+::
255+++ watch
256+ |= [=wire =dock =path]
257+ =/ m (strand ,~)
258+ ^- form:m
259+ =/ =card:agent:gall [%pass watch+wire %agent dock %watch path]
260+ ;< ~ bind:m (send-raw-card card)
261+ (take-watch-ack wire)
262+::
263+++ watch-one
264+ |= [=wire =dock =path]
265+ =/ m (strand ,cage)
266+ ^- form:m
267+ ;< ~ bind:m (watch wire dock path)
268+ ;< =cage bind:m (take-fact wire)
269+ ;< ~ bind:m (take-kick wire)
270+ (pure:m cage)
271+::
272+++ watch-our
273+ |= [=wire =term =path]
274+ =/ m (strand ,~)
275+ ^- form:m
276+ ;< our=@p bind:m get-our
277+ (watch wire [our term] path)
278+::
279+++ scry
280+ |* [=mold =path]
281+ =/ m (strand ,mold)
282+ ^- form:m
283+ ?> ?=(^ path)
284+ ?> ?=(^ t.path)
285+ ;< =bowl:spider bind:m get-bowl
286+ %- pure:m
287+ .^(mold i.path (scot %p our.bowl) i.t.path (scot %da now.bowl) t.t.path)
288+::
289+++ leave
290+ |= [=wire =dock]
291+ =/ m (strand ,~)
292+ ^- form:m
293+ =/ =card:agent:gall [%pass watch+wire %agent dock %leave ~]
294+ (send-raw-card card)
295+::
296+++ leave-our
297+ |= [=wire =term]
298+ =/ m (strand ,~)
299+ ^- form:m
300+ ;< our=@p bind:m get-our
301+ (leave wire [our term])
302+::
303+++ rewatch
304+ |= [=wire =dock =path]
305+ =/ m (strand ,~)
306+ ;< ~ bind:m ((handle ,~) (take-kick wire))
307+ ;< ~ bind:m (flog-text "rewatching {<dock>} {<path>}")
308+ ;< ~ bind:m (watch wire dock path)
309+ (pure:m ~)
310+::
311+++ wait
312+ |= until=@da
313+ =/ m (strand ,~)
314+ ^- form:m
315+ ;< ~ bind:m (send-wait until)
316+ (take-wake `until)
317+::
318+++ sleep
319+ |= for=@dr
320+ =/ m (strand ,~)
321+ ^- form:m
322+ ;< now=@da bind:m get-time
323+ (wait (add now for))
324+::
325+++ send-wait
326+ |= until=@da
327+ =/ m (strand ,~)
328+ ^- form:m
329+ =/ =card:agent:gall
330+ [%pass /wait/(scot %da until) %arvo %b %wait until]
331+ (send-raw-card card)
332+::
333+++ map-err
334+ |* computation-result=mold
335+ =/ m (strand ,computation-result)
336+ |= [f=$-([term tang] [term tang]) computation=form:m]
337+ ^- form:m
338+ |= tin=strand-input:strand
339+ =* loop $
340+ =/ c-res (computation tin)
341+ ?: ?=(%cont -.next.c-res)
342+ c-res(self.next ..loop(computation self.next.c-res))
343+ ?. ?=(%fail -.next.c-res)
344+ c-res
345+ c-res(err.next (f err.next.c-res))
346+::
347+++ set-timeout
348+ |* computation-result=mold
349+ =/ m (strand ,computation-result)
350+ |= [time=@dr computation=form:m]
351+ ^- form:m
352+ ;< now=@da bind:m get-time
353+ =/ when (add now time)
354+ =/ =card:agent:gall
355+ [%pass /timeout/(scot %da when) %arvo %b %wait when]
356+ ;< ~ bind:m (send-raw-card card)
357+ |= tin=strand-input:strand
358+ =* loop $
359+ ?: ?& ?=([~ %sign [%timeout @ ~] %behn %wake *] in.tin)
360+ =((scot %da when) i.t.wire.u.in.tin)
361+ ==
362+ `[%fail %timeout ~]
363+ =/ c-res (computation tin)
364+ ?: ?=(%cont -.next.c-res)
365+ c-res(self.next ..loop(computation self.next.c-res))
366+ ?: ?=(%done -.next.c-res)
367+ =/ =card:agent:gall
368+ [%pass /timeout/(scot %da when) %arvo %b %rest when]
369+ c-res(cards [card cards.c-res])
370+ c-res
371+::
372+++ send-request
373+ |= =request:http
374+ =/ m (strand ,~)
375+ ^- form:m
376+ (send-raw-card %pass /request %arvo %i %request request *outbound-config:iris)
377+::
378+++ send-cancel-request
379+ =/ m (strand ,~)
380+ ^- form:m
381+ (send-raw-card %pass /request %arvo %i %cancel-request ~)
382+::
383+++ take-client-response
384+ =/ m (strand ,client-response:iris)
385+ ^- form:m
386+ |= tin=strand-input:strand
387+ ?+ in.tin `[%skip ~]
388+ ~ `[%wait ~]
389+ ::
390+ [~ %sign [%request ~] %iris %http-response %cancel *]
391+ ::NOTE iris does not (yet?) retry after cancel, so it means failure
392+ :- ~
393+ :+ %fail
394+ %http-request-cancelled
395+ ['http request was cancelled by the runtime']~
396+ ::
397+ [~ %sign [%request ~] %iris %http-response %finished *]
398+ `[%done client-response.sign-arvo.u.in.tin]
399+ ==
400+::
401+:: Wait until we get an HTTP response or cancelation and unset contract
402+::
403+++ take-maybe-sigh
404+ =/ m (strand ,(unit httr:eyre))
405+ ^- form:m
406+ ;< rep=(unit client-response:iris) bind:m
407+ take-maybe-response
408+ ?~ rep
409+ (pure:m ~)
410+ :: XX s/b impossible
411+ ::
412+ ?. ?=(%finished -.u.rep)
413+ (pure:m ~)
414+ (pure:m (some (to-httr:iris +.u.rep)))
415+::
416+++ take-maybe-response
417+ =/ m (strand ,(unit client-response:iris))
418+ ^- form:m
419+ |= tin=strand-input:strand
420+ ?+ in.tin `[%skip ~]
421+ ~ `[%wait ~]
422+ [~ %sign [%request ~] %iris %http-response %cancel *]
423+ `[%done ~]
424+ [~ %sign [%request ~] %iris %http-response %finished *]
425+ `[%done `client-response.sign-arvo.u.in.tin]
426+ ==
427+::
428+++ extract-body
429+ |= =client-response:iris
430+ =/ m (strand ,cord)
431+ ^- form:m
432+ ?> ?=(%finished -.client-response)
433+ %- pure:m
434+ ?~ full-file.client-response ''
435+ q.data.u.full-file.client-response
436+
437+::
438+++ fetch-cord
439+ |= url=tape
440+ =/ m (strand ,cord)
441+ ^- form:m
442+ =/ =request:http [%'GET' (crip url) ~ ~]
443+ ;< ~ bind:m (send-request request)
444+ ;< =client-response:iris bind:m take-client-response
445+ (extract-body client-response)
446+::
447+++ fetch-json
448+ |= url=tape
449+ =/ m (strand ,json)
450+ ^- form:m
451+ ;< =cord bind:m (fetch-cord url)
452+ =/ json=(unit json) (de-json:html cord)
453+ ?~ json
454+ (strand-fail %json-parse-error ~)
455+ (pure:m u.json)
456+::
457+++ hiss-request
458+ |= =hiss:eyre
459+ =/ m (strand ,(unit httr:eyre))
460+ ^- form:m
461+ ;< ~ bind:m (send-request (hiss-to-request:html hiss))
462+ take-maybe-sigh
463+::
464+:: +build-file: build the source file at the specified $beam
465+::
466+++ build-file
467+ |= [[=ship =desk =case] =spur]
468+ =* arg +<
469+ =/ m (strand ,(unit vase))
470+ ^- form:m
471+ ;< =riot:clay bind:m
472+ (warp ship desk ~ %sing %a case spur)
473+ ?~ riot
474+ (pure:m ~)
475+ ?> =(%vase p.r.u.riot)
476+ (pure:m (some !<(vase q.r.u.riot)))
477+:: +build-mark: build a mark definition to a $dais
478+::
479+++ build-mark
480+ |= [[=ship =desk =case] mak=mark]
481+ =* arg +<
482+ =/ m (strand ,dais:clay)
483+ ^- form:m
484+ ;< =riot:clay bind:m
485+ (warp ship desk ~ %sing %b case /[mak])
486+ ?~ riot
487+ (strand-fail %build-mark >arg< ~)
488+ ?> =(%dais p.r.u.riot)
489+ (pure:m !<(dais:clay q.r.u.riot))
490+:: +build-tube: build a mark conversion gate ($tube)
491+::
492+++ build-tube
493+ |= [[=ship =desk =case] =mars:clay]
494+ =* arg +<
495+ =/ m (strand ,tube:clay)
496+ ^- form:m
497+ ;< =riot:clay bind:m
498+ (warp ship desk ~ %sing %c case /[a.mars]/[b.mars])
499+ ?~ riot
500+ (strand-fail %build-tube >arg< ~)
501+ ?> =(%tube p.r.u.riot)
502+ (pure:m !<(tube:clay q.r.u.riot))
503+::
504+:: +build-nave: build a mark definition to a $nave
505+::
506+++ build-nave
507+ |= [[=ship =desk =case] mak=mark]
508+ =* arg +<
509+ =/ m (strand ,vase)
510+ ^- form:m
511+ ;< =riot:clay bind:m
512+ (warp ship desk ~ %sing %e case /[mak])
513+ ?~ riot
514+ (strand-fail %build-nave >arg< ~)
515+ ?> =(%nave p.r.u.riot)
516+ (pure:m q.r.u.riot)
517+:: +build-cast: build a mark conversion gate (static)
518+::
519+++ build-cast
520+ |= [[=ship =desk =case] =mars:clay]
521+ =* arg +<
522+ =/ m (strand ,vase)
523+ ^- form:m
524+ ;< =riot:clay bind:m
525+ (warp ship desk ~ %sing %f case /[a.mars]/[b.mars])
526+ ?~ riot
527+ (strand-fail %build-cast >arg< ~)
528+ ?> =(%cast p.r.u.riot)
529+ (pure:m q.r.u.riot)
530+::
531+:: Read from Clay
532+::
533+++ warp
534+ |= [=ship =riff:clay]
535+ =/ m (strand ,riot:clay)
536+ ;< ~ bind:m (send-raw-card %pass /warp %arvo %c %warp ship riff)
537+ (take-writ /warp)
538+::
539+++ read-file
540+ |= [[=ship =desk =case:clay] =spur]
541+ =* arg +<
542+ =/ m (strand ,cage)
543+ ;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
544+ ?~ riot
545+ (strand-fail %read-file >arg< ~)
546+ (pure:m r.u.riot)
547+::
548+++ check-for-file
549+ |= [[=ship =desk =case:clay] =spur]
550+ =/ m (strand ,?)
551+ ;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
552+ (pure:m ?=(^ riot))
553+::
554+++ list-tree
555+ |= [[=ship =desk =case:clay] =spur]
556+ =* arg +<
557+ =/ m (strand ,(list path))
558+ ;< =riot:clay bind:m (warp ship desk ~ %sing %t case spur)
559+ ?~ riot
560+ (strand-fail %list-tree >arg< ~)
561+ (pure:m !<((list path) q.r.u.riot))
562+::
563+:: Take Clay read result
564+::
565+++ take-writ
566+ |= =wire
567+ =/ m (strand ,riot:clay)
568+ ^- form:m
569+ |= tin=strand-input:strand
570+ ?+ in.tin `[%skip ~]
571+ ~ `[%wait ~]
572+ [~ %sign * ?(%behn %clay) %writ *]
573+ ?. =(wire wire.u.in.tin)
574+ `[%skip ~]
575+ `[%done +>.sign-arvo.u.in.tin]
576+ ==
577+:: +check-online: require that peer respond before timeout
578+::
579+++ check-online
580+ |= [who=ship lag=@dr]
581+ =/ m (strand ,~)
582+ ^- form:m
583+ %+ (map-err ,~) |=(* [%offline *tang])
584+ %+ (set-timeout ,~) lag
585+ ;< ~ bind:m
586+ (poke [who %hood] %helm-hi !>(~))
587+ (pure:m ~)
588+::
589+:: Queue on skip, try next on fail %ignore
590+::
591+++ main-loop
592+ |* a=mold
593+ =/ m (strand ,~)
594+ =/ m-a (strand ,a)
595+ =| queue=(qeu (unit input:strand))
596+ =| active=(unit [in=(unit input:strand) =form:m-a forms=(list $-(a form:m-a))])
597+ =| state=a
598+ |= forms=(lest $-(a form:m-a))
599+ ^- form:m
600+ |= tin=strand-input:strand
601+ =* top `form:m`..$
602+ =. queue (~(put to queue) in.tin)
603+ |^ (continue bowl.tin)
604+ ::
605+ ++ continue
606+ |= =bowl:strand
607+ ^- output:m
608+ ?> =(~ active)
609+ ?: =(~ queue)
610+ `[%cont top]
611+ =^ in=(unit input:strand) queue ~(get to queue)
612+ ^- output:m
613+ =. active `[in (i.forms state) t.forms]
614+ ^- output:m
615+ (run bowl in)
616+ ::
617+ ++ run
618+ ^- form:m
619+ |= tin=strand-input:strand
620+ ^- output:m
621+ ?> ?=(^ active)
622+ =/ res (form.u.active tin)
623+ =/ =output:m
624+ ?- -.next.res
625+ %wait `[%wait ~]
626+ %skip `[%cont ..$(queue (~(put to queue) in.tin))]
627+ %cont `[%cont ..$(active `[in.u.active self.next.res forms.u.active])]
628+ %done (continue(active ~, state value.next.res) bowl.tin)
629+ %fail
630+ ?: &(?=(^ forms.u.active) ?=(%ignore p.err.next.res))
631+ %= $
632+ active `[in.u.active (i.forms.u.active state) t.forms.u.active]
633+ in.tin in.u.active
634+ ==
635+ `[%fail err.next.res]
636+ ==
637+ [(weld cards.res cards.output) next.output]
638+ --
639+::
640+++ retry
641+ |* result=mold
642+ |= [crash-after=(unit @ud) computation=_*form:(strand (unit result))]
643+ =/ m (strand ,result)
644+ =| try=@ud
645+ |- ^- form:m
646+ =* loop $
647+ ?: =(crash-after `try)
648+ (strand-fail %retry-too-many ~)
649+ ;< ~ bind:m (backoff try ~m1)
650+ ;< res=(unit result) bind:m computation
651+ ?^ res
652+ (pure:m u.res)
653+ loop(try +(try))
654+::
655+++ backoff
656+ |= [try=@ud limit=@dr]
657+ =/ m (strand ,~)
658+ ^- form:m
659+ ;< eny=@uvJ bind:m get-entropy
660+ %- sleep
661+ %+ min limit
662+ ?: =(0 try) ~s0
663+ %+ add
664+ (mul ~s1 (bex (dec try)))
665+ (mul ~s0..0001 (~(rad og eny) 1.000))
666+::
667+:: ----
668+::
669+:: Output
670+::
671+++ flog
672+ |= =flog:dill
673+ =/ m (strand ,~)
674+ ^- form:m
675+ (send-raw-card %pass / %arvo %d %flog flog)
676+::
677+++ flog-text
678+ |= =tape
679+ =/ m (strand ,~)
680+ ^- form:m
681+ (flog %text tape)
682+::
683+++ flog-tang
684+ |= =tang
685+ =/ m (strand ,~)
686+ ^- form:m
687+ =/ =wall
688+ (zing (turn (flop tang) (cury wash [0 80])))
689+ |- ^- form:m
690+ =* loop $
691+ ?~ wall
692+ (pure:m ~)
693+ ;< ~ bind:m (flog-text i.wall)
694+ loop(wall t.wall)
695+::
696+++ trace
697+ |= =tang
698+ =/ m (strand ,~)
699+ ^- form:m
700+ (pure:m ((slog tang) ~))
701+::
702+++ app-message
703+ |= [app=term =cord =tang]
704+ =/ m (strand ,~)
705+ ^- form:m
706+ =/ msg=tape :(weld (trip app) ": " (trip cord))
707+ ;< ~ bind:m (flog-text msg)
708+ (flog-tang tang)
709+::
710+:: ----
711+::
712+:: Handle domains
713+::
714+++ install-domain
715+ |= =turf
716+ =/ m (strand ,~)
717+ ^- form:m
718+ (send-raw-card %pass / %arvo %e %rule %turf %put turf)
719+::
720+:: ----
721+::
722+:: Threads
723+::
724+++ start-thread
725+ |= file=term
726+ =/ m (strand ,tid:spider)
727+ ;< =bowl:spider bind:m get-bowl
728+ (start-thread-with-args byk.bowl file *vase)
729+::
730+++ start-thread-with-args
731+ |= [=beak file=term args=vase]
732+ =/ m (strand ,tid:spider)
733+ ^- form:m
734+ ;< =bowl:spider bind:m get-bowl
735+ =/ tid
736+ (scot %ta (cat 3 (cat 3 'strand_' file) (scot %uv (sham file eny.bowl))))
737+ =/ poke-vase !>([`tid.bowl `tid beak file args])
738+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
739+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
740+ (pure:m tid)
741+::
742++$ thread-result
743+ (each vase [term tang])
744+::
745+++ await-thread
746+ |= [file=term args=vase]
747+ =/ m (strand ,thread-result)
748+ ^- form:m
749+ ;< =bowl:spider bind:m get-bowl
750+ =/ tid (scot %ta (cat 3 'strand_' (scot %uv (sham file eny.bowl))))
751+ =/ poke-vase !>([`tid.bowl `tid file args])
752+ ;< ~ bind:m (watch-our /awaiting/[tid] %spider /thread-result/[tid])
753+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
754+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
755+ ;< =cage bind:m (take-fact /awaiting/[tid])
756+ ;< ~ bind:m (take-kick /awaiting/[tid])
757+ ?+ p.cage ~|([%strange-thread-result p.cage file tid] !!)
758+ %thread-done (pure:m %& q.cage)
759+ %thread-fail (pure:m %| !<([term tang] q.cage))
760+ ==
761+--
base-desk/lib/test.hoonnew file+50
@@ -0,0 +1,50 @@
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+ %& [leaf+"expected failure - succeeded" ~]
42+ ==
43+:: +category: prepends a name to an error result; passes successes unchanged
44+::
45+++ category
46+ |= [a=tape b=tang] ^- tang
47+ ?: =(~ b) ~ :: test OK
48+ :- leaf+"in: '{a}'"
49+ (turn b |=(c=tank rose+[~ " " ~]^~[c]))
50+--
base-desk/lib/verb.hoonnew file+105
@@ -0,0 +1,105 @@
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+ [[(emit-event %on-init ~) cards] this]
18+::
19+++ on-save
20+ ^- vase
21+ %- (print bowl |.("{<dap.bowl>}: on-save"))
22+ on-save:ag
23+::
24+++ on-load
25+ |= old-state=vase
26+ ^- (quip card:agent:gall agent:gall)
27+ %- (print bowl |.("{<dap.bowl>}: on-load"))
28+ =^ cards agent (on-load:ag old-state)
29+ [[(emit-event %on-load ~) cards] this]
30+::
31+++ on-poke
32+ |= [=mark =vase]
33+ ^- (quip card:agent:gall agent:gall)
34+ %- (print bowl |.("{<dap.bowl>}: on-poke with mark {<mark>}"))
35+ ?: ?=(%verb mark)
36+ ?- !<(?(%loud %bowl) vase)
37+ %loud `this(loud !loud)
38+ %bowl `this(bowl-print !bowl-print)
39+ ==
40+ =^ cards agent (on-poke:ag mark vase)
41+ [[(emit-event %on-poke mark) cards] this]
42+::
43+++ on-watch
44+ |= =path
45+ ^- (quip card:agent:gall agent:gall)
46+ %- (print bowl |.("{<dap.bowl>}: on-watch on path {<path>}"))
47+ =^ cards agent
48+ ?: ?=([%verb %events ~] path)
49+ [~ agent]
50+ (on-watch:ag path)
51+ [[(emit-event %on-watch path) cards] this]
52+::
53+++ on-leave
54+ |= =path
55+ ^- (quip card:agent:gall agent:gall)
56+ %- (print bowl |.("{<dap.bowl>}: on-leave on path {<path>}"))
57+ ?: ?=([%verb %event ~] path)
58+ [~ this]
59+ =^ cards agent (on-leave:ag path)
60+ [[(emit-event %on-leave path) cards] this]
61+::
62+++ on-peek
63+ |= =path
64+ ^- (unit (unit cage))
65+ %- (print bowl |.("{<dap.bowl>}: on-peek on path {<path>}"))
66+ (on-peek:ag path)
67+::
68+++ on-agent
69+ |= [=wire =sign:agent:gall]
70+ ^- (quip card:agent:gall agent:gall)
71+ %- (print bowl |.("{<dap.bowl>}: on-agent on wire {<wire>}, {<-.sign>}"))
72+ =^ cards agent (on-agent:ag wire sign)
73+ [[(emit-event %on-agent wire -.sign) cards] this]
74+::
75+++ on-arvo
76+ |= [=wire =sign-arvo]
77+ ^- (quip card:agent:gall agent:gall)
78+ %- %+ print bowl |.
79+ "{<dap.bowl>}: on-arvo on wire {<wire>}, {<[- +<]:sign-arvo>}"
80+ =^ cards agent (on-arvo:ag wire sign-arvo)
81+ [[(emit-event %on-arvo wire [- +<]:sign-arvo) cards] this]
82+::
83+++ on-fail
84+ |= [=term =tang]
85+ ^- (quip card:agent:gall agent:gall)
86+ %- (print bowl |.("{<dap.bowl>}: on-fail with term {<term>}"))
87+ =^ cards agent (on-fail:ag term tang)
88+ [[(emit-event %on-fail term) cards] this]
89+--
90+::
91+++ print
92+ |= [=bowl:gall render=(trap tape)]
93+ ^+ same
94+ =? . bowl-print
95+ %- (slog >bowl< ~)
96+ .
97+ ?. loud same
98+ %- (slog [%leaf $:render] ~)
99+ same
100+::
101+++ emit-event
102+ |= =event:verb
103+ ^- card:agent:gall
104+ [%give %fact ~[/verb/events] %verb-event !>(event)]
105+--
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+29
@@ -0,0 +1,29 @@
1+:: belt: runtime belt structure
2+::
3+|_ =belt:dill
4+++ grad %noun
5+:: +grab: convert from
6+::
7+++ grab
8+ |%
9+ ++ noun belt:dill
10+ ++ json
11+ ^- $-(^json belt:dill)
12+ =, dejs:format
13+ %- of
14+ :~ aro+(su (perk %d %l %r %u ~))
15+ bac+ul
16+ ctl+(cu taft so)
17+ del+ul
18+ met+(cu taft so)
19+ ret+ul
20+ txt+(ar (cu taft so))
21+ ==
22+ --
23+:: +grow: convert to
24+::
25+++ grow
26+ |%
27+ ++ noun belt
28+ --
29+--
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+61
@@ -0,0 +1,61 @@
1+:: blit: runtime blit structure
2+::
3+|_ =blit:dill
4+++ grad %noun
5+:: +grab: convert from
6+::
7+++ grab
8+ |%
9+ ++ noun blit:dill
10+ --
11+:: +grow: convert to
12+::
13+++ grow
14+ |%
15+ ++ noun blit
16+ ++ json
17+ ^- ^json
18+ =, enjs:format
19+ %+ frond -.blit
20+ ?- -.blit
21+ %bel b+&
22+ %clr b+&
23+ %hop (numb p.blit)
24+ %lin a+(turn p.blit |=(c=@c s+(tuft c)))
25+ %mor b+&
26+ %url s+p.blit
27+ ::
28+ %sag
29+ %- pairs
30+ :~ 'path'^(path p.blit)
31+ 'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit)))
32+ ==
33+ ::
34+ %sav
35+ %- pairs
36+ :~ 'path'^(path p.blit)
37+ 'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit))
38+ ==
39+ ::
40+ %klr
41+ :- %a
42+ %+ turn p.blit
43+ |= [=stye text=(list @c)]
44+ %- pairs
45+ :~ 'text'^a+(turn text |=(c=@c s+(tuft c)))
46+ ::
47+ :- 'stye'
48+ %- pairs
49+ |^ :~ 'back'^(color p.q.stye)
50+ 'fore'^(color q.q.stye)
51+ 'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d)))
52+ ==
53+ ++ color
54+ |= =tint
55+ ?@ tint ?~(tint ~ s+tint)
56+ s+(crip ((x-co:co 6) (rep 3 ~[b g r]:tint)))
57+ --
58+ ==
59+ ==
60+ --
61+--
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+49
@@ -0,0 +1,49 @@
1+:::: /hoon/hoon/mar
2+ ::
3+/? 310
4+::
5+=, eyre
6+|_ own=@t
7+::
8+++ grow :: convert to
9+ |%
10+ ++ mime `^mime`[/text/x-hoon (as-octs:mimes:html own)] :: convert to %mime
11+ ++ elem :: convert to %html
12+ ;div:pre(urb_codemirror "", mode "hoon"):"{(trip own)}"
13+ :: =+ gen-id="src-{<`@ui`(mug own)>}"
14+ :: ;div
15+ :: ;textarea(id "{gen-id}"):"{(trip own)}"
16+ :: ;script:"""
17+ :: CodeMirror.fromTextArea(
18+ :: window[{<gen-id>}],
19+ :: \{lineNumbers:true, readOnly:true}
20+ :: )
21+ :: """
22+ :: ==
23+ ++ hymn
24+ :: ;html:(head:title:"Source" "+{elem}")
25+ ;html
26+ ;head
27+ ;title:"Source"
28+ ;script@"//cdnjs.cloudflare.com/ajax/libs/codemirror/4.3.0/codemirror.js";
29+ ;script@"/lib/syntax/hoon.js";
30+ ;link(rel "stylesheet", href "//cdnjs.cloudflare.com/ajax/libs/".
31+ "codemirror/4.3.0/codemirror.min.css");
32+ ;link/"/lib/syntax/codemirror.css"(rel "stylesheet");
33+ ==
34+ ;body
35+ ;textarea#src:"{(trip own)}"
36+ ;script:'CodeMirror.fromTextArea(src, {lineNumbers:true, readOnly:true})'
37+ ==
38+ ==
39+ ++ txt
40+ (to-wain:format own)
41+ --
42+++ grab
43+ |% :: convert from
44+ ++ mime |=([p=mite q=octs] q.q)
45+ ++ noun @t :: clam from %noun
46+ ++ txt of-wain:format
47+ --
48+++ grad %txt
49+--
base-desk/mar/htm.hoonnew file+15
@@ -0,0 +1,15 @@
1+::
2+:::: /hoon/htm/mar
3+ ::
4+/? 310
5+|_ own=manx
6+::
7+++ grad %noun
8+++ grow :: convert to
9+ |%
10+ ++ noun own
11+ ++ hymn own
12+ --
13+++ grab |% :: convert from
14+ ++ noun manx :: clam from %noun
15+-- --
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+25
@@ -0,0 +1,25 @@
1+::
2+:::: /hoon/httr/mar
3+ ::
4+/? 310
5+::
6+=, eyre
7+=, format
8+=, html
9+|_ hit=httr
10+++ grad %noun
11+++ grow |% ++ wall (turn wain trip)
12+ ++ wain (to-wain cord)
13+ ++ json (need (de-json cord))
14+ ++ cord q:octs
15+ ++ noun hit
16+ ++ octs
17+ ~| hit
18+ ?> =(2 (div p.hit 100))
19+ (need r.hit)
20+ --
21+++ grab :: convert from
22+ |%
23+ ++ noun httr :: clam from %noun
24+ --
25+--
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+22
@@ -0,0 +1,22 @@
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+ ++ elem ;script
12+ ;- (trip (@t mud))
13+ ==
14+ ++ hymn ;html:(head:"+{elem}" body)
15+ --
16+++ grab
17+ |% :: convert from
18+ ++ mime |=([p=mite q=octs] (@t q.q))
19+ ++ noun cord :: clam from %noun
20+ --
21+++ grad %mime
22+--
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 [(crip (en-json jon))]~
17+ --
18+++ grab
19+ |% :: convert from
20+ ++ mime |=([p=mite q=octs] (fall (rush (@t q.q) apex:de-json) *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+43
@@ -0,0 +1,43 @@
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+ =, html
20+ %- json
21+ ?~ r.hit
22+ a+~
23+ (need (de-json q:u.r.hit))
24+ fail+hit
25+ ++ json :: from json
26+ =, dejs-soft:format
27+ |= a=json
28+ ^- response
29+ =; dere
30+ =+ res=((ar dere) a)
31+ ?~ res (need (dere a))
32+ [%batch u.res]
33+ |= a=json
34+ ^- (unit response)
35+ =/ res=(unit [@t json])
36+ ::TODO breaks when no id present
37+ ((ot id+so result+some ~) a)
38+ ?^ res `[%result u.res]
39+ ~| a
40+ :+ ~ %error %- need
41+ ((ot id+so error+(ot code+no message+so ~) ~) a)
42+ --
43+--
base-desk/mar/kelvin.hoonnew file+18
@@ -0,0 +1,18 @@
1+=/ weft ,[lal=@tas num=@ud] :: TODO remove after merge
2+|_ kel=weft
3+++ grow
4+ |%
5+ ++ mime `^mime`[/text/x-kelvin (as-octs:mimes:html hoon)]
6+ ++ noun kel
7+ ++ hoon (crip "{<[lal num]:kel>}\0a")
8+ ++ txt (to-wain:format hoon)
9+ --
10+++ grab
11+ |%
12+ ++ noun weft
13+ ++ mime
14+ |= [=mite len=@ud tex=@]
15+ !<(weft (slap !>(~) (ream tex)))
16+ --
17+++ grad %noun
18+--
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+19
@@ -0,0 +1,19 @@
1+::
2+:::: /hoon/noun/mar
3+ ::
4+/? 310
5+!:
6+:::: A minimal noun mark
7+|_ non=*
8+++ grab |%
9+ ++ noun *
10+ --
11+++ grad
12+ |%
13+ ++ form %noun
14+ ++ diff |=(* +<)
15+ ++ pact |=(* +<)
16+ ++ join |=([* *] *(unit *))
17+ ++ mash |=([[ship desk *] [ship desk *]] `*`~|(%noun-mash !!))
18+ --
19+--
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+50
@@ -0,0 +1,50 @@
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+so dat+(fo %ret (of det+change tab+ni ~)) ~)
24+ ++ fo
25+ |* [a=term b=fist]
26+ |=(c=json ?.(=([%s a] c) (b c) (some [a ~])))
27+ ::
28+ ++ ra
29+ |* [a=[term fist] b=fist]
30+ |= c=json %. c
31+ ?.(=(%a -.c) b (pe -.a (ar +.a)))
32+ ::
33+ ++ ke :: callbacks
34+ |* [gar=* sef=(trap fist)]
35+ |= jon=json ^- (unit _gar)
36+ =- ~! gar ~! (need -) -
37+ ((sef) jon)
38+ ::
39+ ++ change (ot ler+(at ni ni ~) ted+(pe 0v0 edit) ~)
40+ ++ char (cu taft so)
41+ ++ edit
42+ %+ ke *sole-edit |. ~+
43+ %+ fo %nop
44+ %+ ra mor+edit
45+ (of del+ni set+(cu tuba sa) ins+(ot at+ni cha+char ~) ~)
46+ --
47+ ::
48+ ++ noun sole-action :: clam from %noun
49+ --
50+--
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/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+ ::
20+ ++ elem
21+ =- ;pre:code:"{(of-wall -)}"
22+ ^- wall %- zing ^- (list wall)
23+ (turn (flop tan) |=(a=tank (wash 0^160 a)))
24+ --
25+++ grab :: convert from
26+ |%
27+ ++ noun (list ^tank) :: clam from %noun
28+ ++ tank |=(a=^tank [a]~)
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/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+275
@@ -0,0 +1,275 @@
1+::
2+:::: /hoon/txt/mar
3+ ::
4+/? 310
5+::
6+=, clay
7+=, differ
8+=, format
9+=, mimes:html
10+|_ txt=wain
11+::
12+++ grab :: convert from
13+ |%
14+ ++ mime |=((pair mite octs) (to-wain q.q))
15+ ++ noun wain :: clam from %noun
16+ --
17+++ grow
18+ => v=.
19+ |%
20+ ++ mime => v [/text/plain (as-octs (of-wain txt))]
21+ ++ elem => v ;pre: {(trip (of-wain txt))}
22+ --
23+++ grad
24+ |%
25+ ++ form %txt-diff
26+ ++ diff
27+ |= tyt=wain
28+ ^- (urge cord)
29+ (lusk txt tyt (loss txt tyt))
30+ ::
31+ ++ pact
32+ |= dif=(urge cord)
33+ ~| [%pacting dif]
34+ ^- wain
35+ (lurk txt dif)
36+ ::
37+ ++ join
38+ |= [ali=(urge cord) bob=(urge cord)]
39+ ^- (unit (urge cord))
40+ |^
41+ =. ali (clean ali)
42+ =. bob (clean bob)
43+ |- ^- (unit (urge cord))
44+ ?~ ali `bob
45+ ?~ bob `ali
46+ ?- -.i.ali
47+ %&
48+ ?- -.i.bob
49+ %&
50+ ?: =(p.i.ali p.i.bob)
51+ %+ bind $(ali t.ali, bob t.bob)
52+ |=(cud=(urge cord) [i.ali cud])
53+ ?: (gth p.i.ali p.i.bob)
54+ %+ bind $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)
55+ |=(cud=(urge cord) [i.bob cud])
56+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))
57+ |=(cud=(urge cord) [i.ali cud])
58+ ::
59+ %|
60+ ?: =(p.i.ali (lent p.i.bob))
61+ %+ bind $(ali t.ali, bob t.bob)
62+ |=(cud=(urge cord) [i.bob cud])
63+ ?: (gth p.i.ali (lent p.i.bob))
64+ %+ bind $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)
65+ |=(cud=(urge cord) [i.bob cud])
66+ ~
67+ ==
68+ ::
69+ %|
70+ ?- -.i.bob
71+ %|
72+ ?. =(i.ali i.bob)
73+ ~
74+ %+ bind $(ali t.ali, bob t.bob)
75+ |=(cud=(urge cord) [i.ali cud])
76+ ::
77+ %&
78+ ?: =(p.i.bob (lent p.i.ali))
79+ %+ bind $(ali t.ali, bob t.bob)
80+ |=(cud=(urge cord) [i.ali cud])
81+ ?: (gth p.i.bob (lent p.i.ali))
82+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))
83+ |=(cud=(urge cord) [i.ali cud])
84+ ~
85+ ==
86+ ==
87+ ++ clean :: clean
88+ |= wig=(urge cord)
89+ ^- (urge cord)
90+ ?~ wig ~
91+ ?~ t.wig wig
92+ ?: ?=(%& -.i.wig)
93+ ?: ?=(%& -.i.t.wig)
94+ $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
95+ [i.wig $(wig t.wig)]
96+ ?: ?=(%| -.i.t.wig)
97+ $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
98+ [i.wig $(wig t.wig)]
99+ --
100+ ::
101+ ++ mash
102+ |= $: [als=ship ald=desk ali=(urge cord)]
103+ [bos=ship bod=desk bob=(urge cord)]
104+ ==
105+ ^- (urge cord)
106+ |^
107+ =. ali (clean ali)
108+ =. bob (clean bob)
109+ |- ^- (urge cord)
110+ ?~ ali bob
111+ ?~ bob ali
112+ ?- -.i.ali
113+ %&
114+ ?- -.i.bob
115+ %&
116+ ?: =(p.i.ali p.i.bob)
117+ [i.ali $(ali t.ali, bob t.bob)]
118+ ?: (gth p.i.ali p.i.bob)
119+ [i.bob $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)]
120+ [i.ali $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))]
121+ ::
122+ %|
123+ ?: =(p.i.ali (lent p.i.bob))
124+ [i.bob $(ali t.ali, bob t.bob)]
125+ ?: (gth p.i.ali (lent p.i.bob))
126+ [i.bob $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)]
127+ =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
128+ (resolve ali bob)
129+ [fic $(ali ali, bob bob)]
130+ :: ~ :: here, alice is good for a while, but not for the whole
131+ == :: length of bob's changes
132+ ::
133+ %|
134+ ?- -.i.bob
135+ %|
136+ =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
137+ (resolve ali bob)
138+ [fic $(ali ali, bob bob)]
139+ ::
140+ %&
141+ ?: =(p.i.bob (lent p.i.ali))
142+ [i.ali $(ali t.ali, bob t.bob)]
143+ ?: (gth p.i.bob (lent p.i.ali))
144+ [i.ali $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))]
145+ =/ [fic=(unce cord) ali=(urge cord) bob=(urge cord)]
146+ (resolve ali bob)
147+ [fic $(ali ali, bob bob)]
148+ ==
149+ ==
150+ ::
151+ ++ annotate :: annotate conflict
152+ |= $: ali=(list @t)
153+ bob=(list @t)
154+ bas=(list @t)
155+ ==
156+ ^- (list @t)
157+ %- zing
158+ ^- (list (list @t))
159+ %- flop
160+ ^- (list (list @t))
161+ :- :_ ~
162+ %^ cat 3 '<<<<<<<<<<<<'
163+ %^ cat 3 ' '
164+ %^ cat 3 `@t`(scot %p bos)
165+ %^ cat 3 '/'
166+ bod
167+
168+ :- bob
169+ :- ~['------------']
170+ :- bas
171+ :- ~['++++++++++++']
172+ :- ali
173+ :- :_ ~
174+ %^ cat 3 '>>>>>>>>>>>>'
175+ %^ cat 3 ' '
176+ %^ cat 3 `@t`(scot %p als)
177+ %^ cat 3 '/'
178+ ald
179+ ~
180+ ::
181+ ++ clean :: clean
182+ |= wig=(urge cord)
183+ ^- (urge cord)
184+ ?~ wig ~
185+ ?~ t.wig wig
186+ ?: ?=(%& -.i.wig)
187+ ?: ?=(%& -.i.t.wig)
188+ $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
189+ [i.wig $(wig t.wig)]
190+ ?: ?=(%| -.i.t.wig)
191+ $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
192+ [i.wig $(wig t.wig)]
193+ ::
194+ ++ resolve
195+ |= [ali=(urge cord) bob=(urge cord)]
196+ ^- [fic=[%| p=(list cord) q=(list cord)] ali=(urge cord) bob=(urge cord)]
197+ =- [[%| bac (annotate alc boc bac)] ali bob]
198+ |- ^- $: $: bac=(list cord)
199+ alc=(list cord)
200+ boc=(list cord)
201+ ==
202+ ali=(urge cord)
203+ bob=(urge cord)
204+ ==
205+ ?~ ali [[~ ~ ~] ali bob]
206+ ?~ bob [[~ ~ ~] ali bob]
207+ ?- -.i.ali
208+ %&
209+ ?- -.i.bob
210+ %& [[~ ~ ~] ali bob] :: no conflict
211+ %|
212+ =+ lob=(lent p.i.bob)
213+ ?: =(lob p.i.ali)
214+ [[p.i.bob p.i.bob q.i.bob] t.ali t.bob]
215+ ?: (lth lob p.i.ali)
216+ [[p.i.bob p.i.bob q.i.bob] [[%& (sub p.i.ali lob)] t.ali] t.bob]
217+ =+ wat=(scag (sub lob p.i.ali) p.i.bob)
218+ =+ ^= res
219+ %= $
220+ ali t.ali
221+ bob [[%| (scag (sub lob p.i.ali) p.i.bob) ~] t.bob]
222+ ==
223+ :* :* (welp bac.res wat)
224+ (welp alc.res wat)
225+ (welp boc.res q.i.bob)
226+ ==
227+ ali.res
228+ bob.res
229+ ==
230+ ==
231+ ::
232+ %|
233+ ?- -.i.bob
234+ %&
235+ =+ loa=(lent p.i.ali)
236+ ?: =(loa p.i.bob)
237+ [[p.i.ali q.i.ali p.i.ali] t.ali t.bob]
238+ ?: (lth loa p.i.bob)
239+ [[p.i.ali q.i.ali p.i.ali] t.ali [[%& (sub p.i.bob loa)] t.bob]]
240+ =+ wat=(slag (sub loa p.i.bob) p.i.ali)
241+ =+ ^= res
242+ %= $
243+ ali [[%| (scag (sub loa p.i.bob) p.i.ali) ~] t.ali]
244+ bob t.bob
245+ ==
246+ :* :* (welp bac.res wat)
247+ (welp alc.res q.i.ali)
248+ (welp boc.res wat)
249+ ==
250+ ali.res
251+ bob.res
252+ ==
253+ ::
254+ %|
255+ =+ loa=(lent p.i.ali)
256+ =+ lob=(lent p.i.bob)
257+ ?: =(loa lob)
258+ [[p.i.ali q.i.ali q.i.bob] t.ali t.bob]
259+ =+ ^= res
260+ ?: (gth loa lob)
261+ $(ali [[%| (scag (sub loa lob) p.i.ali) ~] t.ali], bob t.bob)
262+ ~& [%scagging loa=loa pibob=p.i.bob slag=(scag loa p.i.bob)]
263+ $(ali t.ali, bob [[%| (scag (sub lob loa) p.i.bob) ~] t.bob])
264+ :* :* (welp bac.res ?:((gth loa lob) p.i.bob p.i.ali))
265+ (welp alc.res q.i.ali)
266+ (welp boc.res q.i.bob)
267+ ==
268+ ali.res
269+ bob.res
270+ ==
271+ ==
272+ ==
273+ --
274+ --
275+--
base-desk/mar/udon.hoonnew file+32
@@ -0,0 +1,32 @@
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+ ++ elem
13+ ^- manx
14+ =, cram
15+ elm:(static (ream mud))
16+ ++ front :: XX performance, types
17+ ^- (map term knot)
18+ %- ~(run by inf:(static:cram (ream mud)))
19+ |= a=dime ^- cord
20+ ?+ (end 3 p.a) (scot a)
21+ %t q.a
22+ ==
23+ --
24+++ grab
25+ |%
26+ ++ mime |=((pair mite octs) q.q)
27+ ++ noun @t
28+ ++ txt of-wain:format
29+ --
30+++ grad %txt
31+++ garb /down
32+--
base-desk/mar/umd.hoonnew file+32
@@ -0,0 +1,32 @@
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+ ++ elem
13+ ^- manx
14+ =, cram
15+ elm:(static (ream mud))
16+ ++ front :: XX performance, types
17+ ^- (map term knot)
18+ %- ~(run by inf:(static:cram (ream mud)))
19+ |= a=dime ^- cord
20+ ?+ (end 3 p.a) (scot a)
21+ %t q.a
22+ ==
23+ --
24+++ grab
25+ |%
26+ ++ mime |=((pair mite octs) q.q)
27+ ++ noun @t
28+ ++ txt of-wain:format
29+ --
30+++ grad %txt
31+++ garb /down
32+--
base-desk/mar/urb.hoonnew file+18
@@ -0,0 +1,18 @@
1+::
2+:::: /hoon/elem/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/sur/aquarium.hoonnew file+76
@@ -0,0 +1,76 @@
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+/+ pill
14+=, pill-lib=pill
15+|%
16++$ az-log [topics=(lest @) data=@t]
17++$ az-state
18+ $: logs=(list az-log)
19+ lives=(map ship [lyfe=life rut=rift])
20+ tym=@da
21+ ==
22+++ ph-event
23+ $% [%test-done p=?]
24+ aqua-event
25+ ==
26+::
27++$ unix-event unix-event:pill-lib
28++$ pill pill:pill-lib
29+::
30++$ aqua-event
31+ $% [%init-ship who=ship fake=?]
32+ [%pause-events who=ship]
33+ [%snap-ships lab=term hers=(list ship)]
34+ [%restore-snap lab=term]
35+ [%event who=ship ue=unix-event]
36+ ==
37+::
38++$ azimuth-action
39+ $% [%init-azimuth ~]
40+ [%spawn who=ship]
41+ [%breach who=ship]
42+ ==
43+::
44++$ aqua-effects
45+ [who=ship ufs=(list unix-effect)]
46+::
47++$ aqua-effect
48+ [who=ship ufs=unix-effect]
49+::
50++$ aqua-events
51+ [who=ship utes=(list unix-timed-event)]
52+::
53++$ aqua-boths
54+ [who=ship ub=(list unix-both)]
55+::
56++$ unix-both
57+ $% [%event unix-timed-event]
58+ [%effect unix-effect]
59+ ==
60+::
61++$ unix-timed-event [tym=@da ue=unix-event]
62+::
63++$ unix-effect
64+ %+ pair wire
65+ $% [%blit p=(list blit:dill)]
66+ [%send p=lane:ames q=@]
67+ [%doze p=(unit @da)]
68+ [%thus p=@ud q=(unit hiss:eyre)]
69+ [%ergo p=@tas q=mode:clay]
70+ [%sleep ~]
71+ [%restore ~]
72+ [%kill ~]
73+ [%init ~]
74+ [%request id=@ud request=request:http]
75+ ==
76+--
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)
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+315
@@ -0,0 +1,315 @@
1+=, clay
2+=* dude dude:gall
3+|%
4+:: $snap: kiln snapshot
5+::
6++$ snap (map desk arak)
7+:: $diff: subscription update
8+::
9++$ diff
10+ $% [%block =desk =arak =weft blockers=(set desk)]
11+ [%reset =desk =arak]
12+ [%commit =desk =arak]
13+ [%merge-sunk =desk =arak =tang]
14+ [%merge-fail =desk =arak =tang]
15+ [%suspend =desk =arak]
16+ [%revive =desk =arak]
17+ ==
18+:: $arak: foreign vat tracker
19+::
20+:: .rail: upstream tracking state, if any
21+:: .rein: configuration for agents
22+::
23++$ arak
24+ $: rail=(unit rail)
25+ =rein
26+ ==
27+:: $rail: upstream tracking state
28+::
29+:: .publisher: Ship that originally published desk, if available
30+:: .paused: is tracking paused? or live
31+:: .ship: upstream ship (could be .our)
32+:: .desk: name of upstream desk
33+:: .aeon: next aeon to pull from upstream
34+:: .next: list of pending commits with future kelvins
35+::
36++$ rail
37+ $: publisher=(unit ship)
38+ paused=?
39+ =ship
40+ =desk
41+ =aeon
42+ next=(list rung)
43+ ==
44+:: $rung: reference to upstream commit
45+::
46++$ rung [=aeon =weft]
47+:: $rein: diff from desk manifest
48+::
49+:: .liv: suspended? if suspended, no agents should run
50+:: .add: agents not in manifest that should be running
51+:: .sub: agents in manifest that should not be running
52+::
53++$ rein
54+ $: liv=_&
55+ add=(set dude)
56+ sub=(set dude)
57+ ==
58+::
59++$ vat [=desk hash=@uv =cass =arak]
60+:: +report-vats: report on all desk installations
61+::
62+++ report-vats
63+ |= [our=@p now=@da]
64+ ^- tang
65+ =+ .^ raz=(list vat)
66+ %gx /(scot %p our)/hood/(scot %da now)/kiln/vats/noun
67+ ==
68+ :- (report-kids our now)
69+ (turn raz |=(v=vat (report-vat our now v)))
70+:: +report-vat: report on a single desk installation
71+::
72+++ report-vat
73+ |= [our=ship now=@da vat]
74+ ^- tank
75+ ?: =(ud.cass 0)
76+ leaf+"desk does not yet exist: {<desk>}"
77+ =/ kel-path
78+ /(scot %p our)/[desk]/(scot %da now)/sys/kelvin
79+ ?. .^(? %cu kel-path)
80+ leaf+"bad desk: {<desk>}"
81+ =+ .^(=weft %cx kel-path)
82+ :+ %rose ["" "{<desk>}" "::"]
83+ ^- tang
84+ =/ meb (mergebase-hashes our desk now arak)
85+ =/ poz
86+ ?~ rail.arak "local"
87+ ?:(paused.u.rail.arak "paused" "tracking")
88+ =/ sat ?:(liv.rein.arak "running" "suspended")
89+ =/ pen
90+ ?~ rail.arak "~"
91+ <(turn next.u.rail.arak |=([@ lal=@tas num=@] [lal num]))>
92+ :~ leaf/"/sys/kelvin: {<[lal num]:weft>}"
93+ leaf/"base hash: {?.(=(1 (lent meb)) <meb> <(head meb)>)}"
94+ leaf/"%cz hash: {<hash>}"
95+ ::
96+ leaf/"app status: {sat}"
97+ leaf/"force on: {?:(=(~ add.rein.arak) "~" <add.rein.arak>)}"
98+ leaf/"force off: {?:(=(~ sub.rein.arak) "~" <sub.rein.arak>)}"
99+ ::
100+ leaf/"publishing ship: {?~(rail.arak <~> <publisher.u.rail.arak>)}"
101+ leaf/"updates: {poz}"
102+ leaf/"source ship: {?~(rail.arak <~> <ship.u.rail.arak>)}"
103+ leaf/"source desk: {?~(rail.arak <~> <desk.u.rail.arak>)}"
104+ leaf/"source aeon: {?~(rail.arak <~> <aeon.u.rail.arak>)}"
105+ leaf/"pending updates: {pen}"
106+ ==
107+:: +report-kids: non-vat cz hash report for kids desk
108+::
109+++ report-kids
110+ |= [our=ship now=@da]
111+ ^- tank
112+ =/ dek %kids
113+ =/ ego (scot %p our)
114+ =/ wen (scot %da now)
115+ ?. (~(has in .^((set desk) %cd /[ego]//[wen])) dek)
116+ leaf/"no %kids desk"
117+ =+ .^(hash=@uv %cz /[ego]/[dek]/[wen])
118+ leaf/"%kids %cz hash: {<hash>}"
119+:: +read-kelvin-foreign: read /sys/kelvin from a foreign desk
120+::
121+++ read-kelvin-foreign
122+ |= [=ship =desk =aeon]
123+ ^- weft
124+ ~| read-foreign-kelvin/+<
125+ =/ her (scot %p ship)
126+ =/ syd (scot %tas desk)
127+ =/ yon (scot %ud aeon)
128+ ::
129+ =/ dom .^(dome cv/~[her syd yon])
130+ =/ tak (scot %uv (~(got by hit.dom) let.dom))
131+ =/ yak .^(yaki cs/~[her syd yon %yaki tak])
132+ =/ lob (scot %uv (~(got by q.yak) /sys/kelvin))
133+ =/ bob .^(blob cs/~[her syd yon %blob lob])
134+ ::
135+ ;; weft
136+ ?- -.bob
137+ %direct q.q.bob
138+ %delta q.r.bob
139+ ==
140+:: +read-kelvin-local: read /sys/kelvin from a local desk
141+::
142+++ read-kelvin-local
143+ |= [our=ship =desk now=@da]
144+ ^- (unit weft)
145+ ~| read-kelvin-local+desk
146+ =/ pax (en-beam [our desk da+now] /sys/kelvin)
147+ ?. .^(? cu/pax)
148+ ~
149+ [~ .^(weft cx/pax)]
150+:: +read-bill-foreign: read /desk/bill from a foreign desk
151+::
152+++ read-bill-foreign
153+ |= [=ship =desk =aeon]
154+ ^- (list dude)
155+ ~| +<
156+ =/ her (scot %p ship)
157+ =/ syd (scot %tas desk)
158+ =/ yon (scot %ud aeon)
159+ ::
160+ =/ dom .^(dome cv/~[her syd yon])
161+ =/ tak ~| aeons=~(key by hit.dom)
162+ (scot %uv (~(got by hit.dom) aeon))
163+ =/ yak .^(yaki cs/~[her syd yon %yaki tak])
164+ =/ fil (~(get by q.yak) /desk/bill)
165+ ?~ fil ~
166+ =/ lob (scot %uv u.fil)
167+ =/ bob .^(blob cs/~[her syd yon %blob lob])
168+ ::
169+ ;; (list dude)
170+ ?- -.bob
171+ %direct q.q.bob
172+ %delta q.r.bob
173+ ==
174+:: +read-bill: read contents of /desk/bill manifest
175+::
176+++ read-bill
177+ |= [our=ship =desk now=@da]
178+ =/ pax (en-beam [our desk da+now] /desk/bill)
179+ ?. .^(? cu/pax)
180+ *(list dude)
181+ .^((list dude) cx/pax)
182+:: +adjust-dudes: which agents should be started and stopped
183+::
184+:: Will ask Gall to start agents that it's already running
185+:: but that should be ok, and might be safer in case other
186+:: unprocessed moves would have turned them off.
187+::
188+++ adjust-dudes
189+ |= $: local=[our=ship =desk now=@da]
190+ =rein
191+ ==
192+ ^- [jolt=(list dude) idle=(list dude)]
193+ =/ all=(list dude) (read-bill local)
194+ =/ want (get-apps-want local all rein)
195+ =/ have (get-apps-live local)
196+ [want (skip have ~(has in (sy want)))]
197+::
198+++ get-remote-diff
199+ |= [our=ship here=desk now=@da her=ship there=desk when=aeon]
200+ =+ .^(our-hash=@uv cz/[(scot %p our) here (scot %da now) ~])
201+ =+ .^(her-hash=@uv cz/[(scot %p her) there (scot %ud when) ~])
202+ !=(our-hash her-hash)
203+::
204+++ get-publisher
205+ |= [our=ship =desk now=@da]
206+ ^- (unit ship)
207+ =/ pax /(scot %p our)/[desk]/(scot %da now)/desk/ship
208+ ?. .^(? %cu pax) ~
209+ `.^(ship %cx pax)
210+::
211+++ get-apps-live
212+ |= [our=ship =desk now=@da]
213+ ^- (list dude)
214+ %+ murn (get-apps-have our desk now)
215+ |=([=dude live=?] ?.(live ~ `dude))
216+:: +get-apps-have: find which apps Gall is running on a desk
217+::
218+++ get-apps-have
219+ |= [our=ship =desk now=@da]
220+ ^- (list [=dude live=?])
221+ %~ tap in
222+ .^((set [=dude live=?]) ge+/(scot %p our)/[desk]/(scot %da now))
223+:: +get-apps-want: find which apps should be running on a desk
224+::
225+++ get-apps-want
226+ |= [local=[our=ship =desk now=@da] duz=(list dude) =rein]
227+ ^- (list dude)
228+ ?. liv.rein ~
229+ ?. |(=(`zuse+zuse (read-kelvin-local local)) =(%base desk.local)) ~
230+ =. duz (skip duz ~(has in sub.rein))
231+ =. duz (weld duz (skip ~(tap in add.rein) ~(has in (sy duz))))
232+ duz
233+::
234+++ mergebase-hashes
235+ |= [our=@p =desk now=@da =arak]
236+ ?~ rail.arak
237+ ~
238+ =/ her (scot %p ship.u.rail.arak)
239+ =/ ego (scot %p our)
240+ =/ wen (scot %da now)
241+ %+ turn .^((list tako) %cs ~[ego desk wen %base her desk.u.rail.arak])
242+ |=(=tako .^(@uv %cs ~[ego desk wen %hash (scot %uv tako)]))
243+::
244+++ enjs
245+ =, enjs:format
246+ |%
247+ ++ vats
248+ |= v=(list ^vat)
249+ ^- json
250+ %- pairs
251+ %+ turn v
252+ |= va=^vat
253+ [desk.va (vat va)]
254+ ::
255+ ++ tim
256+ |= t=@
257+ ^- json
258+ (numb (fall (mole |.((unm:chrono:userlib t))) 0))
259+ ::
260+ ++ cass
261+ |= c=^cass
262+ %- pairs
263+ :~ ud+(numb ud.c)
264+ da+(tim da.c)
265+ ==
266+ ::
267+ ++ vat
268+ |= v=^vat
269+ %- pairs
270+ :~ desk+s+desk.v
271+ hash+s+(scot %uv hash.v)
272+ cass+(cass cass.v)
273+ arak+(arak arak.v)
274+ ==
275+ ::
276+ ++ weft
277+ |= w=^weft
278+ %- pairs
279+ :~ name+s+lal.w
280+ kelvin+(numb num.w)
281+ ==
282+ ::
283+ ++ rung
284+ |= r=^rung
285+ %- pairs
286+ :~ aeon+(numb aeon.r)
287+ weft+(weft weft.r)
288+ ==
289+ ::
290+ ++ rein
291+ |= r=^rein
292+ %- pairs
293+ :~ add+a+(turn ~(tap in add.r) (lead %s))
294+ sub+a+(turn ~(tap in sub.r) (lead %s))
295+ ==
296+ ::
297+ ++ arak
298+ |= a=^arak
299+ %- pairs
300+ :~ rail+?~(rail.a ~ (rail u.rail.a))
301+ rein+(rein rein.a)
302+ ==
303+ ::
304+ ++ rail
305+ |= r=^rail
306+ %- pairs
307+ :~ ship+s+(scot %p ship.r)
308+ publisher+?~(publisher.r ~ s+(scot %p u.publisher.r))
309+ desk+s+desk.r
310+ paused+b+paused.r
311+ aeon+(numb aeon.r)
312+ next+a+(turn next.r rung)
313+ ==
314+ --
315+--
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 @udpoint)
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+87
@@ -0,0 +1,87 @@
1+::
2+:::: /hoon/sole/sur
3+ ::
4+^?
5+|%
6++$ sole-action :: sole to app
7+ $: id=@ta :: duct id
8+ $= dat
9+ $% :: [%abo ~] :: reset interaction
10+ [%det sole-change] :: command line edit
11+ [%ret ~] :: submit and clear
12+ [%clr ~] :: exit context
13+ [%tab pos=@ud] :: tab complete
14+ == ::
15+ ==
16++$ sole-buffer (list @c) :: command state
17++$ sole-change :: network change
18+ $: ler=sole-clock :: destination clock
19+ haw=@uvH :: source hash
20+ ted=sole-edit :: state change
21+ == ::
22++$ sole-clock [own=@ud his=@ud] :: vector clock
23++$ sole-edit :: shared state change
24+ $% [%del p=@ud] :: delete one at
25+ [%ins p=@ud q=@c] :: insert at
26+ [%mor p=(list sole-edit)] :: combination
27+ [%nop ~] :: no-op
28+ [%set p=sole-buffer] :: discontinuity
29+ == ::
30++$ sole-effect :: app to sole
31+ $% [%bel ~] :: beep
32+ [%blk p=@ud q=@c] :: blink+match char at
33+ [%bye ~] :: close session
34+ [%clr ~] :: clear screen
35+ [%det sole-change] :: edit command
36+ [%err p=@ud] :: error point
37+ [%klr p=styx] :: styled text line
38+ [%mor p=(list sole-effect)] :: multiple effects
39+ [%nex ~] :: save clear command
40+ [%pro sole-prompt] :: set prompt
41+ [%sag p=path q=*] :: save to jamfile
42+ [%sav p=path q=@] :: save to file
43+ [%tab p=(list [=cord =tank])] :: tab-complete list
44+ [%tan p=(list tank)] :: classic tank
45+ :: [%taq p=tanq] :: modern tank
46+ [%txt p=tape] :: text line
47+ [%url p=@t] :: activate url
48+ == ::
49++$ sole-command :: command state
50+ $: pos=@ud :: cursor position
51+ say=sole-share :: cursor
52+ == ::
53++$ sole-prompt :: prompt definition
54+ $: vis=? :: command visible
55+ tag=term :: history mode
56+ cad=styx :: caption
57+ == ::
58++$ sole-share :: symmetric state
59+ $: ven=sole-clock :: our vector clock
60+ leg=(list sole-edit) :: unmerged edits
61+ buf=sole-buffer :: sole state
62+ == ::
63+:: ::
64+:: ::
65+++ sole-dialog :: standard dialog
66+ |* out=$-(* *) :: output structure
67+ $-(sole-input (sole-result out)) :: output function
68+:: ::
69++$ sole-input tape :: prompt input
70+++ sole-result :: conditional result
71+ |* out=$-(* *) :: output structure
72+ $@(@ud (sole-product out)) :: error position
73+:: ::
74+++ sole-product :: success result
75+ |* out=$-(* *) ::
76+ %+ pair (list tank) ::
77+ %+ each (unit out) :: ~ is abort
78+ (pair sole-prompt (sole-dialog out)) :: ask and continue
79+:: ::
80++$ sole-gen :: XX virtual type
81+ $% [%say $-((sole-args) (cask))] :: direct noun
82+ [%ask $-((sole-args) (sole-product (cask)))] :: dialog
83+ == ::
84+++ sole-args :: generator arguments
85+ |* _[* *] ::
86+ ,[[now=@da eny=@uvJ bek=beak] [,+<- ,+<+]] ::
87+--
base-desk/sur/spider.hoonnew file+14
@@ -0,0 +1,14 @@
1+/+ libstrand=strand
2+=, strand=strand:libstrand
3+|%
4++$ thread $-(vase _*form:(strand ,vase))
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+--
base-desk/sur/verb.hoonnew file+12
@@ -0,0 +1,12 @@
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+--