@dcasegr/skein 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +522 -2
- package/bin/skein-host.js +22 -0
- package/bin/skein.js +8 -0
- package/dist/client/admin-cli.d.ts +10 -0
- package/dist/client/admin-cli.js +370 -0
- package/dist/client/admin.d.ts +139 -0
- package/dist/client/admin.js +256 -0
- package/dist/client/bundle.d.ts +9 -0
- package/dist/client/bundle.js +34 -0
- package/dist/client/cli.d.ts +44 -0
- package/dist/client/cli.js +306 -0
- package/dist/client/client.d.ts +161 -0
- package/dist/client/client.js +237 -0
- package/dist/client/config.d.ts +18 -0
- package/dist/client/config.js +31 -0
- package/dist/client/conversation.d.ts +62 -0
- package/dist/client/conversation.js +113 -0
- package/dist/client/raw.d.ts +94 -0
- package/dist/client/raw.js +154 -0
- package/dist/client/target.d.ts +34 -0
- package/dist/client/target.js +158 -0
- package/dist/dev/cli.d.ts +8 -0
- package/dist/dev/cli.js +248 -0
- package/dist/dev/scan.d.ts +15 -0
- package/dist/dev/scan.js +173 -0
- package/dist/envelope-cbor.d.ts +110 -0
- package/dist/envelope-cbor.js +160 -0
- package/dist/envelope.d.ts +38 -0
- package/dist/envelope.js +101 -0
- package/dist/host/arc.d.ts +131 -0
- package/dist/host/arc.js +425 -0
- package/dist/host/billing.d.ts +102 -0
- package/dist/host/billing.js +167 -0
- package/dist/host/boot.d.ts +246 -0
- package/dist/host/boot.js +643 -0
- package/dist/host/cli.d.ts +57 -0
- package/dist/host/cli.js +1253 -0
- package/dist/host/clock.d.ts +3 -0
- package/dist/host/clock.js +8 -0
- package/dist/host/control.d.ts +45 -0
- package/dist/host/control.js +170 -0
- package/dist/host/cron.d.ts +99 -0
- package/dist/host/cron.js +196 -0
- package/dist/host/deliver.d.ts +53 -0
- package/dist/host/deliver.js +251 -0
- package/dist/host/deploy.d.ts +29 -0
- package/dist/host/deploy.js +55 -0
- package/dist/host/door-answer.d.ts +24 -0
- package/dist/host/door-answer.js +21 -0
- package/dist/host/events.d.ts +89 -0
- package/dist/host/events.js +222 -0
- package/dist/host/fake-arcade.d.ts +40 -0
- package/dist/host/fake-arcade.js +149 -0
- package/dist/host/fake-discovery.d.ts +4 -0
- package/dist/host/fake-discovery.js +58 -0
- package/dist/host/feeds.d.ts +127 -0
- package/dist/host/feeds.js +422 -0
- package/dist/host/frontdoor.d.ts +92 -0
- package/dist/host/frontdoor.js +172 -0
- package/dist/host/genesis.d.ts +259 -0
- package/dist/host/genesis.js +353 -0
- package/dist/host/handles.d.ts +40 -0
- package/dist/host/handles.js +88 -0
- package/dist/host/hostenv.d.ts +30 -0
- package/dist/host/hostenv.js +83 -0
- package/dist/host/image-chain.d.ts +127 -0
- package/dist/host/image-chain.js +440 -0
- package/dist/host/install.d.ts +22 -0
- package/dist/host/install.js +139 -0
- package/dist/host/instances.d.ts +227 -0
- package/dist/host/instances.js +430 -0
- package/dist/host/kernel.d.ts +246 -0
- package/dist/host/kernel.js +603 -0
- package/dist/host/liveness.d.ts +65 -0
- package/dist/host/liveness.js +155 -0
- package/dist/host/manifest.d.ts +160 -0
- package/dist/host/manifest.js +597 -0
- package/dist/host/p2p.d.ts +337 -0
- package/dist/host/p2p.js +1002 -0
- package/dist/host/packet.d.ts +121 -0
- package/dist/host/packet.js +562 -0
- package/dist/host/plan.d.ts +154 -0
- package/dist/host/plan.js +418 -0
- package/dist/host/providers.d.ts +238 -0
- package/dist/host/providers.js +565 -0
- package/dist/host/roster.d.ts +72 -0
- package/dist/host/roster.js +172 -0
- package/dist/host/router.d.ts +773 -0
- package/dist/host/router.js +2389 -0
- package/dist/host/signer.d.ts +49 -0
- package/dist/host/signer.js +167 -0
- package/dist/host/store-sqlite.d.ts +39 -0
- package/dist/host/store-sqlite.js +170 -0
- package/dist/host/stores.d.ts +43 -0
- package/dist/host/stores.js +342 -0
- package/dist/host/sync.d.ts +121 -0
- package/dist/host/sync.js +467 -0
- package/dist/host/testbeef.d.ts +21 -0
- package/dist/host/testbeef.js +37 -0
- package/dist/host/testhost.d.ts +149 -0
- package/dist/host/testhost.js +211 -0
- package/dist/host/vcdiff.d.ts +9 -0
- package/dist/host/vcdiff.js +210 -0
- package/dist/host/wasm-kernel.d.ts +87 -0
- package/dist/host/wasm-kernel.js +296 -0
- package/dist/host/wasm-worker.d.ts +1 -0
- package/dist/host/wasm-worker.js +186 -0
- package/dist/peers/cron.d.ts +33 -0
- package/dist/peers/cron.js +75 -0
- package/dist/peers/infer-main.d.ts +2 -0
- package/dist/peers/infer-main.js +74 -0
- package/dist/peers/infer.d.ts +163 -0
- package/dist/peers/infer.js +367 -0
- package/dist/runtime/beef.d.ts +28 -0
- package/dist/runtime/beef.js +107 -0
- package/dist/runtime/bitcoin.d.ts +36 -0
- package/dist/runtime/bitcoin.js +141 -0
- package/dist/runtime/cid.d.ts +14 -0
- package/dist/runtime/cid.js +51 -0
- package/dist/runtime/dispatch.d.ts +92 -0
- package/dist/runtime/dispatch.js +142 -0
- package/dist/runtime/envelope.d.ts +60 -0
- package/dist/runtime/envelope.js +101 -0
- package/dist/runtime/heads.d.ts +25 -0
- package/dist/runtime/heads.js +37 -0
- package/dist/runtime/identity.d.ts +28 -0
- package/dist/runtime/identity.js +67 -0
- package/dist/runtime/index-store.d.ts +152 -0
- package/dist/runtime/index-store.js +715 -0
- package/dist/runtime/log.d.ts +62 -0
- package/dist/runtime/log.js +104 -0
- package/dist/runtime/programs.d.ts +30 -0
- package/dist/runtime/programs.js +61 -0
- package/dist/runtime/records.d.ts +135 -0
- package/dist/runtime/records.js +149 -0
- package/dist/runtime/sqlite.d.ts +33 -0
- package/dist/runtime/sqlite.js +604 -0
- package/dist/runtime/store.d.ts +141 -0
- package/dist/runtime/store.js +24 -0
- package/dist/runtime/syscalls.d.ts +9 -0
- package/dist/runtime/syscalls.js +41 -0
- package/dist/runtime/tree.d.ts +60 -0
- package/dist/runtime/tree.js +196 -0
- package/dist/runtime/types.d.ts +100 -0
- package/dist/runtime/types.js +7 -0
- package/dist/testapps.d.ts +101 -0
- package/dist/testapps.js +275 -0
- package/dist/testkit.d.ts +25 -0
- package/dist/testkit.js +48 -0
- package/dist/wallet.d.ts +35 -0
- package/dist/wallet.js +87 -0
- package/images/README.md +68 -0
- package/images/default/README.md +38 -0
- package/images/default/bin/frontdoor.cid +1 -0
- package/images/default/bin/frontdoor.json +5 -0
- package/images/default/bin/messagebox.cid +1 -0
- package/images/default/bin/messagebox.json +8 -0
- package/images/default/bin/wallet.cid +1 -0
- package/images/default/bin/wallet.json +14 -0
- package/images/default/etc/config.json +1 -0
- package/images/default/etc/dispatch.json +82 -0
- package/images/host/etc/apps.json +8 -0
- package/kernel-zig/README.md +1247 -0
- package/kernel-zig/web/client.js +65 -0
- package/kernel-zig/web/kernel.d.ts +59 -0
- package/kernel-zig/web/kernel.js +329 -0
- package/kernel-zig/web/store.js +67 -0
- package/kernel-zig/web/worker.js +79 -0
- package/kernel-zig/zig-out/web/skein-kernel.wasm +0 -0
- package/package.json +77 -4
- package/wasm/README.md +35 -0
- package/wasm/frontdoor.wasm +0 -0
- package/wasm/messagebox.wasm +0 -0
- package/wasm/resolve.wasm +0 -0
- package/wasm/wallet.wasm +0 -0
- package/wasm/wire-probe.wasm +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Billing (#130), the host's side. The kernel meters what is in its log and
|
|
2
|
+
// prepays the host block by block from the instance's own wallet
|
|
3
|
+
// (kernel-zig/src/billing.zig, scheduler.zig billingAfter); the host:
|
|
4
|
+
//
|
|
5
|
+
// terms its key (a child of the master secret: provider key `billing`) and what it supports
|
|
6
|
+
// — X, the rates, its free allowance per skein, its tick interval, its grace — published
|
|
7
|
+
// at /.well-known/skein-host (`billing`). The owner grants them as the host row, a kernel
|
|
8
|
+
// row of the skein's dispatch table (`skein host`): no row, nothing is billed, the
|
|
9
|
+
// skein is served as before; a row naming another key or lower rates (or X) than this
|
|
10
|
+
// host's: it stops serving (the gate).
|
|
11
|
+
// meter what never reaches the log: the fuel of the read calls it makes (the explorer's reads,
|
|
12
|
+
// frontdoor.ts) and the bytes it serves, per instance, since its last tick; each a line
|
|
13
|
+
// of its log for the period.
|
|
14
|
+
// tick every tickMs (and at once for a skein whose host row it has not ticked yet, and early
|
|
15
|
+
// when what it holds unreported would take the tally to the allocation): a message
|
|
16
|
+
// signed by its key, in the host row's box — {kind: "tick", at, allowance, fuel, served,
|
|
17
|
+
// log: <the CID of its log record for the period>} — the period's record kept in host.db.
|
|
18
|
+
// payment the wallet's `payment` event (the pay step's): kept in host.db and broadcast (its
|
|
19
|
+
// Arcade), the output checked against the BRC-29 key the remittance derives.
|
|
20
|
+
// the gate asleep (the kernel's billing state says so: consumed ≥ allocation and nothing paid) or
|
|
21
|
+
// the terms not this host's: nothing is forwarded to the instance — a request is 402,
|
|
22
|
+
// a libp2p message ignored, a provider's answer, a feed's event dropped — but its own
|
|
23
|
+
// messages to itself (the loopback: its wallet's ingest at the chain app). No tick is sent;
|
|
24
|
+
// the tally is frozen in the kernel.
|
|
25
|
+
// grace when it went asleep is in host.db; past the grace the host may reclaim it
|
|
26
|
+
// (`skein-host reclaim`): disabled, its row and store removed. Nothing does it on its own.
|
|
27
|
+
//
|
|
28
|
+
// Amounts: X, the allowance and payments in satoshis; the tally in nanosatoshis (a bigint here).
|
|
29
|
+
import { encode } from "../runtime/cid.js";
|
|
30
|
+
/** The kernel's head (billing.zig HEAD). */
|
|
31
|
+
export const BILLING_HEAD = "billing";
|
|
32
|
+
/** The host row's kernel operation. */
|
|
33
|
+
export const TICK_OP = "tick";
|
|
34
|
+
/** The host row's box by convention (the row's address is what a tick goes to). */
|
|
35
|
+
export const BILLING_BOX = "billing";
|
|
36
|
+
export const NSAT = 1000000000n;
|
|
37
|
+
export const RATE_NAMES = ["fuel", "storage", "served", "fetch", "authfetch", "publish"];
|
|
38
|
+
/** Small dev defaults (#130 decided, "Numbers": configuration; real numbers later). */
|
|
39
|
+
export const DEV_BILLING = {
|
|
40
|
+
x: 1_000,
|
|
41
|
+
rates: { fuel: 1, storage: 1, served: 1, fetch: 1, authfetch: 1, publish: 1 },
|
|
42
|
+
allowance: 10_000,
|
|
43
|
+
tickMs: 60_000,
|
|
44
|
+
graceMs: 7 * 86_400_000,
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The host's billing from its environment: SKEIN_BILLING=off for none; else DEV_BILLING with
|
|
48
|
+
* SKEIN_BILLING_X, SKEIN_BILLING_RATES (JSON {fuel, storage, served, fetch, authfetch, publish}),
|
|
49
|
+
* SKEIN_BILLING_ALLOWANCE, SKEIN_BILLING_TICK_MS, SKEIN_BILLING_GRACE_MS over it.
|
|
50
|
+
*/
|
|
51
|
+
export function billingConfig(v) {
|
|
52
|
+
if (v.SKEIN_BILLING === "off" || v.SKEIN_BILLING === "0")
|
|
53
|
+
return undefined;
|
|
54
|
+
const num = (name, d) => {
|
|
55
|
+
const s = v[name];
|
|
56
|
+
if (s === undefined || s === "")
|
|
57
|
+
return d;
|
|
58
|
+
const n = Number(s);
|
|
59
|
+
if (!Number.isSafeInteger(n) || n < 0)
|
|
60
|
+
throw new Error(`${name}: a whole number, not ${s}`);
|
|
61
|
+
return n;
|
|
62
|
+
};
|
|
63
|
+
let rates = DEV_BILLING.rates;
|
|
64
|
+
if (v.SKEIN_BILLING_RATES) {
|
|
65
|
+
const r = JSON.parse(v.SKEIN_BILLING_RATES);
|
|
66
|
+
rates = { ...rates };
|
|
67
|
+
for (const [k, x] of Object.entries(r)) {
|
|
68
|
+
if (!RATE_NAMES.includes(k) || typeof x !== "number" || !Number.isSafeInteger(x) || x < 0)
|
|
69
|
+
throw new Error(`SKEIN_BILLING_RATES: ${k}: a rate is one of ${RATE_NAMES.join(", ")}, a whole number of sats`);
|
|
70
|
+
rates[k] = x;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const x = num("SKEIN_BILLING_X", DEV_BILLING.x);
|
|
74
|
+
if (x < 1)
|
|
75
|
+
throw new Error("SKEIN_BILLING_X: at least 1 sat");
|
|
76
|
+
return { x, rates, allowance: num("SKEIN_BILLING_ALLOWANCE", DEV_BILLING.allowance), tickMs: Math.max(1, num("SKEIN_BILLING_TICK_MS", DEV_BILLING.tickMs)), graceMs: num("SKEIN_BILLING_GRACE_MS", DEV_BILLING.graceMs) };
|
|
77
|
+
}
|
|
78
|
+
const hexOf = (k) => k instanceof Uint8Array ? Buffer.from(k).toString("hex") : typeof k === "string" && /^0[23][0-9a-f]{64}$/.test(k) ? k : undefined;
|
|
79
|
+
const whole = (n) => typeof n === "number" && Number.isSafeInteger(n) && n >= 0 ? n : typeof n === "bigint" && n >= 0n && n <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(n) : undefined;
|
|
80
|
+
/** The host row (billing.zig termsOf): the first kernel route whose fn is `tick`, in table order; #143: the host's key its `host` setting. */
|
|
81
|
+
export function termsOf(rows) {
|
|
82
|
+
for (const r of rows) {
|
|
83
|
+
if (r.program !== "kernel" || r.fn !== TICK_OP)
|
|
84
|
+
continue;
|
|
85
|
+
const host = hexOf(r.host);
|
|
86
|
+
const x = whole(r.x);
|
|
87
|
+
if (!host || !x)
|
|
88
|
+
return undefined;
|
|
89
|
+
const rates = Object.fromEntries(RATE_NAMES.map((n) => [n, 0]));
|
|
90
|
+
const given = r.rates;
|
|
91
|
+
if (given && typeof given === "object")
|
|
92
|
+
for (const n of RATE_NAMES) {
|
|
93
|
+
const v = whole(given[n]);
|
|
94
|
+
if (v !== undefined)
|
|
95
|
+
rates[n] = v;
|
|
96
|
+
}
|
|
97
|
+
return { host, x, rates, address: r.address };
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
/** Why the terms are not what this host (key `host`) supports (undefined: they are): another key, X or a rate below its own. */
|
|
102
|
+
export function mismatch(cfg, host, t) {
|
|
103
|
+
if (t.host !== host)
|
|
104
|
+
return `the host row names ${t.host.slice(0, 8)}…, not this host's key ${host.slice(0, 8)}…`;
|
|
105
|
+
if (t.x < cfg.x)
|
|
106
|
+
return `x ${t.x} is below this host's ${cfg.x}`;
|
|
107
|
+
for (const n of RATE_NAMES)
|
|
108
|
+
if (t.rates[n] < cfg.rates[n])
|
|
109
|
+
return `the ${n} rate ${t.rates[n]} is below this host's ${cfg.rates[n]}`;
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const big = (n) => typeof n === "bigint" ? n : typeof n === "number" && Number.isSafeInteger(n) ? BigInt(n) : undefined;
|
|
113
|
+
export function stateOf(rec) {
|
|
114
|
+
const r = rec;
|
|
115
|
+
if (!r || r.kind !== "billing")
|
|
116
|
+
return undefined;
|
|
117
|
+
const host = hexOf(r.host);
|
|
118
|
+
const [allowance, paid, tally] = [big(r.allowance), big(r.paid), big(r.tally)];
|
|
119
|
+
if (!host || allowance === undefined || paid === undefined || tally === undefined || typeof r.asleep !== "boolean")
|
|
120
|
+
return undefined;
|
|
121
|
+
return { host, allowance, paid, tally, lastTick: Number(r.lastTick), ticks: Number(r.ticks), bytes: Number(r.bytes), payments: Number(r.payments), asleep: r.asleep };
|
|
122
|
+
}
|
|
123
|
+
/** What the instance may consume (nanosats). */
|
|
124
|
+
export const allocation = (s) => (s.allowance + s.paid) * NSAT;
|
|
125
|
+
/** The host's amounts at the rates (nanosats): billing.zig priceHost. */
|
|
126
|
+
export const priceHost = (r, fuel, served) => BigInt(fuel) * BigInt(r.fuel) + BigInt(served) * BigInt(r.served) * 1000n;
|
|
127
|
+
/** What the host has metered for an instance since its last tick. */
|
|
128
|
+
export class Period {
|
|
129
|
+
since;
|
|
130
|
+
fuel = 0;
|
|
131
|
+
served = 0;
|
|
132
|
+
lines = [];
|
|
133
|
+
constructor(since) { this.since = since; }
|
|
134
|
+
add(l) {
|
|
135
|
+
this.fuel += l.fuel;
|
|
136
|
+
this.served += l.bytes;
|
|
137
|
+
this.lines.push(l);
|
|
138
|
+
}
|
|
139
|
+
get empty() { return this.lines.length === 0; }
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The period's record — {kind: "host-log", instance: <its identity>, from, to, lines: [{at, op,
|
|
143
|
+
* caller?, fuel, bytes}]} — and its CID, which the tick commits to (`log`): the host keeps the
|
|
144
|
+
* record (host.db billing_ticks), so it can show what it charged.
|
|
145
|
+
*/
|
|
146
|
+
export function periodRecord(identity, p, to) {
|
|
147
|
+
const record = {
|
|
148
|
+
kind: "host-log", instance: Uint8Array.from(Buffer.from(identity, "hex")), from: p.since, to,
|
|
149
|
+
lines: p.lines.map((l) => ({ at: l.at, op: l.op, ...(l.caller ? { caller: Uint8Array.from(Buffer.from(l.caller, "hex")) } : {}), fuel: l.fuel, bytes: l.bytes })),
|
|
150
|
+
};
|
|
151
|
+
const b = encode(record);
|
|
152
|
+
return { record, bytes: b.bytes, cid: b.cid };
|
|
153
|
+
}
|
|
154
|
+
/** A tick's body (billing.zig tickOf). */
|
|
155
|
+
export function tickBody(at, cfg, p, log) {
|
|
156
|
+
return { kind: "tick", at, allowance: cfg.allowance, fuel: p.fuel, served: p.served, log };
|
|
157
|
+
}
|
|
158
|
+
/** Why the host forwards nothing to the instance (undefined: it forwards as usual). */
|
|
159
|
+
export function closedBy(v) {
|
|
160
|
+
if (!v?.terms)
|
|
161
|
+
return undefined;
|
|
162
|
+
if (v.mismatch)
|
|
163
|
+
return `this host does not serve these terms: ${v.mismatch}`;
|
|
164
|
+
if (v.state?.asleep && v.state.host === v.terms.host)
|
|
165
|
+
return `asleep: its allocation is consumed and its wallet paid nothing`;
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { CID } from "multiformats/cid";
|
|
2
|
+
import { programRecord, RAW, rawCid, wasmKind } from "../runtime/programs.ts";
|
|
3
|
+
import type { Stamp } from "../runtime/syscalls.ts";
|
|
4
|
+
import { type Entry, type TreeBlocks } from "../runtime/tree.ts";
|
|
5
|
+
import { type ScanOptions } from "../dev/scan.ts";
|
|
6
|
+
import type { DispatchRow } from "../runtime/dispatch.ts";
|
|
7
|
+
import { type ConfigSpec, type DispatchSpec, type Genesis2Config, type System } from "./genesis.ts";
|
|
8
|
+
import type { KernelSurface as Kernel } from "./kernel.ts";
|
|
9
|
+
export declare const DAG_CBOR = 113;
|
|
10
|
+
export { programRecord, RAW, rawCid, wasmKind };
|
|
11
|
+
export declare const BIN = "bin";
|
|
12
|
+
export declare const CONFIG = "etc/config.json";
|
|
13
|
+
export declare const DISPATCH = "etc/dispatch.json";
|
|
14
|
+
/** The forms before #77 and #115, refused (#143: they spoke of senders). */
|
|
15
|
+
export declare const GONE: string[];
|
|
16
|
+
/** #141, #152: the apps an image installs at birth, and root's own routes (ImageApps). */
|
|
17
|
+
export declare const APPS = "etc/apps.json";
|
|
18
|
+
/** Blocks by CID, from wherever a source keeps them. */
|
|
19
|
+
export interface Objects {
|
|
20
|
+
get(cid: CID): Promise<Uint8Array | undefined>;
|
|
21
|
+
}
|
|
22
|
+
/** Blocks in memory: what a scanned directory or a verified packet becomes. */
|
|
23
|
+
export declare class MemBlocks implements Objects, TreeBlocks {
|
|
24
|
+
readonly map: Map<string, {
|
|
25
|
+
cid: CID;
|
|
26
|
+
bytes: Uint8Array;
|
|
27
|
+
}>;
|
|
28
|
+
get(cid: CID): Promise<Uint8Array<ArrayBufferLike> | undefined>;
|
|
29
|
+
bytes(cid: CID): Promise<Uint8Array<ArrayBufferLike>>;
|
|
30
|
+
has(cid: CID): Promise<boolean>;
|
|
31
|
+
putBlock(cid: CID, bytes: Uint8Array): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/** A git object's body if it is a `<type>` object. */
|
|
34
|
+
export declare function gitBody(object: Uint8Array, type: "blob" | "tree"): Uint8Array | undefined;
|
|
35
|
+
/** Source A: a directory on disk, hashed into git objects in memory (scan.ts). */
|
|
36
|
+
export declare function dirSource(dir: string, o?: ScanOptions): Promise<{
|
|
37
|
+
root: CID;
|
|
38
|
+
objects: MemBlocks;
|
|
39
|
+
}>;
|
|
40
|
+
export interface ProgramSpec {
|
|
41
|
+
name: string;
|
|
42
|
+
module: CID;
|
|
43
|
+
record: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
export interface SystemTree {
|
|
46
|
+
root: CID;
|
|
47
|
+
/** Every git object under the root, in walk order. */
|
|
48
|
+
objects: Array<{
|
|
49
|
+
cid: CID;
|
|
50
|
+
bytes: Uint8Array;
|
|
51
|
+
}>;
|
|
52
|
+
programs: ProgramSpec[];
|
|
53
|
+
/** Modules named by bin/<name>.wasm (with their bytes) or bin/<name>.cid (bytes if the source has them). */
|
|
54
|
+
modules: Array<{
|
|
55
|
+
cid: CID;
|
|
56
|
+
bytes?: Uint8Array;
|
|
57
|
+
name: string;
|
|
58
|
+
}>;
|
|
59
|
+
config: ConfigSpec;
|
|
60
|
+
/** etc/dispatch.json (#77, #143): the routes. Required. */
|
|
61
|
+
dispatch: DispatchSpec[];
|
|
62
|
+
/** etc/apps.json (#141): the apps installed at birth, and the trees of those inside the image (appKey → tree CID). */
|
|
63
|
+
apps?: ImageApps;
|
|
64
|
+
appTrees?: Record<string, CID>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* etc/apps.json (#141, #143, #152): what an image installs at birth — `install`, in order, each app
|
|
68
|
+
* a directory (a path relative to the image: a directory of its tree, or one beside it, `..`, read
|
|
69
|
+
* when the image is read from its directory) or a release tarball `{url, hash}` (`hash`: the git id
|
|
70
|
+
* of the app's tree, 40 hex — the tag's tree, `git rev-parse <tag>^{tree}`), which the host fetches
|
|
71
|
+
* and checks; `routes`, root's own routes (no app: an app's upgrade or uninstall leaves them), as
|
|
72
|
+
* the kernel takes them. The genesis carries what installing them as messages would have written:
|
|
73
|
+
* the app's objects and records (pre-filled), the routes (with `app`) and the heads `<app>/app`
|
|
74
|
+
* (plan.ts planInstall, planRootRoute).
|
|
75
|
+
*/
|
|
76
|
+
export interface ImageApps {
|
|
77
|
+
install: ImageApp[];
|
|
78
|
+
routes?: DispatchSpec[];
|
|
79
|
+
}
|
|
80
|
+
export type ImageApp = string | {
|
|
81
|
+
url: string;
|
|
82
|
+
hash: string;
|
|
83
|
+
};
|
|
84
|
+
/** An entry's key: its path, or its tarball's tree id. */
|
|
85
|
+
export declare const appKey: (a: ImageApp) => string;
|
|
86
|
+
/** Every git object reachable from `root` (trees, blobs, gitlinked records), each checked against its id. */
|
|
87
|
+
export declare function treeObjects(objects: Objects, root: CID): Promise<Array<{
|
|
88
|
+
cid: CID;
|
|
89
|
+
bytes: Uint8Array;
|
|
90
|
+
entries?: Entry[];
|
|
91
|
+
}>>;
|
|
92
|
+
/** Read a system tree out of `objects` (docs/BOOTSTRAP.md): its objects, programs, modules, config and subscriptions. */
|
|
93
|
+
export declare function readSystemTree(objects: Objects, root: CID): Promise<SystemTree>;
|
|
94
|
+
/** etc/apps.json's shape (#141, #152), refused with what it wants. */
|
|
95
|
+
export declare function checkImageApps(apps: ImageApps | undefined): void;
|
|
96
|
+
export type BootSource =
|
|
97
|
+
/** No tree: the stock system in code (the live agents). */
|
|
98
|
+
{
|
|
99
|
+
kind: "code";
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A system tree whose objects are in `objects` (a scanned directory, a store, a verified packet). `apps` (#152):
|
|
103
|
+
* the trees of the apps its etc/apps.json names by a directory outside the image, by appKey, read with the image
|
|
104
|
+
* from its directory (their objects in `objects`).
|
|
105
|
+
*/
|
|
106
|
+
| {
|
|
107
|
+
kind: "tree";
|
|
108
|
+
root: CID;
|
|
109
|
+
objects: Objects;
|
|
110
|
+
apps?: Record<string, CID>;
|
|
111
|
+
}
|
|
112
|
+
/** A checkpoint (#30): the state record and every block it reaches, verified; restored, not replayed. */
|
|
113
|
+
| {
|
|
114
|
+
kind: "checkpoint";
|
|
115
|
+
state: CID;
|
|
116
|
+
blocks: Array<{
|
|
117
|
+
cid: CID;
|
|
118
|
+
bytes: Uint8Array;
|
|
119
|
+
}>;
|
|
120
|
+
};
|
|
121
|
+
export interface Booted {
|
|
122
|
+
entry?: CID;
|
|
123
|
+
tree?: CID;
|
|
124
|
+
state?: CID;
|
|
125
|
+
objects: number;
|
|
126
|
+
programs: string[]; /** #141: the apps the image installed at birth. */
|
|
127
|
+
apps?: Array<{
|
|
128
|
+
name: string;
|
|
129
|
+
version: string;
|
|
130
|
+
notes: string[];
|
|
131
|
+
}>;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Boot an empty store through its kernel: pre-fill and write the genesis (a
|
|
135
|
+
* tree, or the stock system), or restore a checkpoint. The kernel processes
|
|
136
|
+
* the genesis when it starts (the dispatch rows; `main` → the tree).
|
|
137
|
+
*/
|
|
138
|
+
export declare function boot(k: Kernel, src: BootSource, c: Genesis2Config, time?: Stamp): Promise<Booted>;
|
|
139
|
+
/**
|
|
140
|
+
* #141, #152: the apps an image installs at birth (etc/apps.json), each a directory install — the
|
|
141
|
+
* app's tree (in the image; a directory beside it, `resolved` by the source; a tarball fetched and
|
|
142
|
+
* checked, appTarball), its objects put — planned as an install by messages would be (plan.ts:
|
|
143
|
+
* readStoredApp over the app's tree, planInstall) against the instance as its genesis will stand —
|
|
144
|
+
* the same records, routes and heads — and root's own routes (planRootRoute). An app's config given
|
|
145
|
+
* at creation (`appConfig`) is merged over its manifest's, as an install's `--config` is. Their
|
|
146
|
+
* objects and records are put into the store; the routes and heads go into the genesis.
|
|
147
|
+
*/
|
|
148
|
+
export declare function installAtBirth(k: Pick<Kernel, "hasBlock" | "putBlock">, imageObjects: Objects, t: SystemTree, s: System, c: Genesis2Config, resolved?: Record<string, CID>): Promise<{
|
|
149
|
+
rows: DispatchRow[];
|
|
150
|
+
heads: Record<string, CID>;
|
|
151
|
+
put: number;
|
|
152
|
+
apps: Array<{
|
|
153
|
+
name: string;
|
|
154
|
+
version: string;
|
|
155
|
+
notes: string[];
|
|
156
|
+
}>;
|
|
157
|
+
}>;
|
|
158
|
+
/** The program records' CIDs a tree's bin/ yields (as `boot` puts them), without a kernel. */
|
|
159
|
+
export declare function programCid(record: Record<string, unknown>): CID;
|
|
160
|
+
/** The stock system as files (`skein-host system <dir>`): bin/*.cid + bin/*.json from the kernel's records, etc/. */
|
|
161
|
+
export declare function stockSystemFiles(k: Kernel): Promise<Record<string, string>>;
|
|
162
|
+
/**
|
|
163
|
+
* Boot a store file that no router holds yet (`skein-host add --boot/--packet`,
|
|
164
|
+
* tests): start its kernel, `boot`, stop it. The router then hydrates it as
|
|
165
|
+
* any other store; the kernel processes the genesis at that first start.
|
|
166
|
+
*/
|
|
167
|
+
export declare function bootStore(o: {
|
|
168
|
+
db: string;
|
|
169
|
+
handle: string;
|
|
170
|
+
domain: string;
|
|
171
|
+
command?: string;
|
|
172
|
+
env?: Record<string, string | undefined>;
|
|
173
|
+
log?(line: string): void;
|
|
174
|
+
}, src: BootSource, c: Genesis2Config, time?: Stamp): Promise<Booted>;
|
|
175
|
+
/** Blocks out of a store (a store file opened read-only, or anything with `bytes`). */
|
|
176
|
+
export declare function storeObjects(s: {
|
|
177
|
+
bytes(cid: CID): Promise<Uint8Array>;
|
|
178
|
+
}): Objects;
|
|
179
|
+
/** The first source that has the block. */
|
|
180
|
+
export declare function anyOf(...sources: Objects[]): Objects;
|
|
181
|
+
/** The modules in a wasm directory (the repo's wasm/: the pinned builds), by their raw CIDs; hashed on first use. */
|
|
182
|
+
export declare function wasmDirObjects(dir: string): Objects;
|
|
183
|
+
/** The repo's pinned modules (wasm/): what a system tree's `bin/*.cid` names. */
|
|
184
|
+
export declare const WASM_DIR: string;
|
|
185
|
+
/** The default image (#89): a user skein's — no root in it, a claim route. */
|
|
186
|
+
export declare const DEFAULT_IMAGE: string;
|
|
187
|
+
/** The host image's own part (#142): merged over the default image (mergeImages), the host skein's image. */
|
|
188
|
+
export declare const HOST_IMAGE: string;
|
|
189
|
+
/**
|
|
190
|
+
* Two image trees merged (#142: images are starting trees that merge): every path of `over` added to
|
|
191
|
+
* `base`. A directory in both is merged; a file in both must be the same blob — except `etc/apps.json`,
|
|
192
|
+
* whose `install` and `routes` lists are joined (an app in both, by appKey, is refused; a root route of
|
|
193
|
+
* `over` at the same transport, address and prefix as one of `base`'s replaces it, #147). Any other path in both is a
|
|
194
|
+
* collision, refused with its path. The installer's own checks (boxes, heads, paths) run when the merged
|
|
195
|
+
* image's apps are installed at birth (installAtBirth). The new trees and the merged apps.json go into
|
|
196
|
+
* `out`; every other object stays where it was.
|
|
197
|
+
*/
|
|
198
|
+
export declare function mergeImages(objects: Objects, base: CID, over: CID, out: MemBlocks): Promise<CID>;
|
|
199
|
+
/**
|
|
200
|
+
* #152: an image directory with no `bin/` is an overlay — it carries what it adds (an app repository's
|
|
201
|
+
* `image/`: `etc/apps.json` alone) and is merged over the default image before boot, as images/host is;
|
|
202
|
+
* one with `bin/` is a complete image of its own.
|
|
203
|
+
*/
|
|
204
|
+
export declare function isOverlayImage(dir: string): boolean;
|
|
205
|
+
/** An image's static part: its tree, its objects, the apps it names beside it (imageDir). */
|
|
206
|
+
export interface ImageStatic {
|
|
207
|
+
root: CID;
|
|
208
|
+
objects: Objects;
|
|
209
|
+
apps: Record<string, CID>;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* #142, #152: an overlay image directory (`dir`: images/host, an app repository's `image/`) merged over
|
|
213
|
+
* `base` (mergeImages: an app in both refused, a root route at the same place replaced, any other path in
|
|
214
|
+
* both refused unless it is the same blob). The apps each names beside it are kept, by appKey.
|
|
215
|
+
*/
|
|
216
|
+
export declare function overlayImage(base: ImageStatic, dir: string): Promise<ImageStatic>;
|
|
217
|
+
/**
|
|
218
|
+
* An image as a boot source (#89, #90): a directory (default: the default
|
|
219
|
+
* image), its objects with the repo's pinned modules beside them, and the
|
|
220
|
+
* apps it names by a directory outside it (imageDir).
|
|
221
|
+
*/
|
|
222
|
+
export declare function imageSource(dir?: string): Promise<BootSource & {
|
|
223
|
+
kind: "tree";
|
|
224
|
+
}>;
|
|
225
|
+
/**
|
|
226
|
+
* #152: an image directory scanned, and each app its etc/apps.json names by a directory outside it
|
|
227
|
+
* (`..`, `../<dir>`, an absolute path) scanned from there as `skein install <dir>` reads it
|
|
228
|
+
* (install.ts appIgnore): the trees by appKey (BootSource `apps`), their objects with the image's.
|
|
229
|
+
*/
|
|
230
|
+
export declare function imageDir(dir: string): Promise<{
|
|
231
|
+
root: CID;
|
|
232
|
+
objects: MemBlocks;
|
|
233
|
+
apps: Record<string, CID>;
|
|
234
|
+
}>;
|
|
235
|
+
/**
|
|
236
|
+
* #152: an app by release tarball, `hash` its tree's git id: the tree the image's objects hold
|
|
237
|
+
* already, else fetched from `url` (gzip or plain tar), unpacked (a tarball holding one directory,
|
|
238
|
+
* as a tag's archive does, is that directory), scanned into `into` as `skein install <dir>` reads
|
|
239
|
+
* a directory (install.ts appIgnore), and refused unless its tree is `hash`.
|
|
240
|
+
*/
|
|
241
|
+
export declare function appTarball(a: {
|
|
242
|
+
url: string;
|
|
243
|
+
hash: string;
|
|
244
|
+
}, have: Objects, into: MemBlocks, get?: typeof fetch): Promise<CID>;
|
|
245
|
+
/** Source B: a packet file, verified (packet.ts) — a system tree to boot, or a checkpoint to restore. */
|
|
246
|
+
export declare function packetSource(bytes: Uint8Array, o?: import("./packet.ts").ReadOptions): Promise<BootSource>;
|