BGW Params
Room encryption (BGW broadcast encryption over BLS12-381) needs a public parameters artifact: a static set of curve points generated once per capacity and reused by every room. Every client — admin and reader — loads the same artifact; rooms pin its identity on-chain at creation.
The artifact
A directory (or HTTP location) with:
manifest.json // capacity, paramsId, paramsRoot, chunk index + hashes
chunks/0.bin
chunks/1.bin
...
| Manifest field | Meaning |
|---|---|
capacity | Universe size N — valid member slots are 1..N (default 1,048,576) |
paramsId / paramsRoot | Artifact identity / integrity root — pinned by every room created against it |
chunks[] | Per-chunk byte length and sha256 — every chunk is verified on load |
The artifact is public — it contains no secrets and can be served from a CDN. It is also room-agnostic: one artifact serves any number of rooms (the room's own secret is the admin seed, which is independent of the artifact). Size scales with capacity; at the default capacity the chunks total roughly 200 MB, at capacity 4,096 under 1 MB.
Clients never load the whole artifact: BgwParamsClient fetches only the chunks needed for an operation and caches them, so steady-state usage touches a small fraction of the data.
Pointing the SDK at params
The default source
The SDK resolves params from a configurable default source, so room APIs work without per-call wiring. With nothing configured it uses the built-in default — a public, capacity-1,048,576 artifact hosted on Arweave:
https://arweave.net/erEnI-MC4igmd9SpXuWmoVRiz6zfK-tVqyz5yGjmF8M
It is served as an Arweave path manifest: the base URL returns manifest.json, and chunk i resolves at ${base}/${i}. This is what makes "just create a room" work out of the box — most apps need no params configuration at all.
To use your own artifact (e.g. a different capacity or your own host), pin a base URL or a local directory at startup — see below. You host the artifact once; it is public and serves every room (see Generating an artifact).
Process-wide default (recommended)
Call once at startup; everything resolves lazily from it:
import { configureDefaultBgwParams } from "xpkt-sdk";
configureDefaultBgwParams({ baseUrl: "https://arweave.net/<txid>" }); // Arweave-style: manifest.json at the base, chunk i at `${base}/${i}`
configureDefaultBgwParams({ dir: "/path/to/params" }); // local files (Node)
configureDefaultBgwParams({ manifestUrl: "https://host/params/manifest.json" }); // explicit manifest URL
configureDefaultBgwParams({ loader: async () => myParamsClient }); // fully custom
Per-room override
Every room entry point accepts an explicit BgwParamsClient, which always wins over the default — use this when one process serves rooms with differing params:
import { BgwParamsClient } from "xpkt-sdk";
const engine = await client.loadBgwEngine(); // room-agnostic WASM engine, cached on the client
const params = BgwParamsClient.InitLocal(engine, "/path/to/params");
// or: BgwParamsClient.InitArweave(engine, "https://arweave.net/<txid>")
const room = await client.room({ id: roomId, bgwParams: params });
const adminRoom = await client.roomAdmin({ roomId, seed, bgwParams: params });
Advanced: resolveBgwParams(engine, override?) is the resolution function the SDK uses internally — explicit override first, else the lazily-built cached default; it throws a descriptive error when neither exists.
Capacity and matching
A room created against capacity-N params can hold at most N member slots, and must always be used with the exact artifact it was created with. RoomAdminClient.Load verifies the resolved params root against the room's pinned paramsRoot and rejects mismatches; readers with wrong params fail during key recovery. See Troubleshooting.
Generating an artifact
Generation is a one-time, per-capacity operation. Most applications never generate an artifact — they use the built-in default or point at an operator-provided URL. Larger-capacity artifacts are produced offline and hosted; the SDK's in-process generator below is intended for development capacities and tests.
In TypeScript (development capacities, tests)
BgwParamsGenerator runs through the WASM engine — single-threaded, fine for dev capacities (e.g. 256 generates in seconds):
import { BgwParamsGenerator } from "xpkt-sdk";
import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
const dir = "./params-dev";
await mkdir(join(dir, "chunks"), { recursive: true });
const generator = new BgwParamsGenerator({
capacity: 256,
setupSeed: crypto.getRandomValues(new Uint8Array(32)),
saveCb: async (chunkIndex, chunkData) => {
await writeFile(join(dir, "chunks", `${chunkIndex}.bin`), chunkData);
},
});
const manifest = await generator.generateAndSave();
await writeFile(join(dir, "manifest.json"), JSON.stringify(manifest, null, 2));
The resulting directory plugs straight into configureDefaultBgwParams({ dir }) or BgwParamsClient.InitLocal.
BgwParamsClient reference
| Member | Description |
|---|---|
InitLocal(engine, dir, manifestFileName?) | Load from a local directory (manifest.json + chunks/*.bin) |
InitHttp(engine, manifestUrl, resolveChunkUrl?) | Load over HTTP; chunks default to chunks/${index}.bin next to the manifest |
getManifest() | The parsed manifest (cached) |
getCapacity() | Capacity N as BN |
getParamsId() / getParamsRoot() | Artifact identity bytes |
Chunk integrity (byte length + sha256) is verified on every load, for both local and HTTP sources.