bulletin-deploy 0.7.21 → 0.7.22-rc.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.
Files changed (56) hide show
  1. package/dist/bug-report.js +4 -4
  2. package/dist/chunk-74ETPOKH.js +284 -0
  3. package/dist/chunk-A5IQ5MKO.js +207 -0
  4. package/dist/{chunk-VTTN4BX7.js → chunk-CIXT75OF.js} +151 -2
  5. package/dist/chunk-EJ5TNGAY.js +24 -0
  6. package/dist/{chunk-RJAFD4LO.js → chunk-FSSKFXTZ.js} +1 -1
  7. package/dist/{chunk-ZY6QLNKQ.js → chunk-KFHGT4A2.js} +1 -1
  8. package/dist/{chunk-MJTQOXBC.js → chunk-LEYQOOWC.js} +3 -2
  9. package/dist/chunk-QHOZEY5X.js +231 -0
  10. package/dist/{chunk-BFXHVC23.js → chunk-SPWQNU3F.js} +21 -17
  11. package/dist/chunk-T7EEVWNU.js +32 -0
  12. package/dist/chunk-UPWEOGLQ.js +37 -0
  13. package/dist/{chunk-SA37SLYF.js → chunk-V5NUBOEX.js} +2 -2
  14. package/dist/{chunk-2VNGK2MU.js → chunk-WNUWAA6F.js} +26 -3
  15. package/dist/{chunk-4TS6R26J.js → chunk-WVCIU6WM.js} +22 -9
  16. package/dist/{chunk-G2P5UIPX.js → chunk-XWA3NPMX.js} +4 -3
  17. package/dist/chunk-ZYVGHDMU.js +117 -0
  18. package/dist/chunk-probe.js +3 -3
  19. package/dist/deploy.d.ts +4 -2
  20. package/dist/deploy.js +9 -9
  21. package/dist/dotns.d.ts +74 -1
  22. package/dist/dotns.js +8 -4
  23. package/dist/incremental-stats.d.ts +3 -1
  24. package/dist/incremental-stats.js +1 -1
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +9 -9
  27. package/dist/memory-report.js +2 -2
  28. package/dist/merkle.js +9 -9
  29. package/dist/personhood/bind-paid-alias.d.ts +43 -0
  30. package/dist/personhood/bind-paid-alias.js +10 -0
  31. package/dist/personhood/bind-personal-id.d.ts +55 -0
  32. package/dist/personhood/bind-personal-id.js +12 -0
  33. package/dist/personhood/bootstrap.d.ts +85 -0
  34. package/dist/personhood/bootstrap.js +245 -0
  35. package/dist/personhood/claim-pgas.d.ts +61 -0
  36. package/dist/personhood/claim-pgas.js +12 -0
  37. package/dist/personhood/constants.d.ts +23 -0
  38. package/dist/personhood/constants.js +22 -0
  39. package/dist/personhood/encoding.d.ts +49 -0
  40. package/dist/personhood/encoding.js +24 -0
  41. package/dist/personhood/hashing.d.ts +4 -0
  42. package/dist/personhood/hashing.js +8 -0
  43. package/dist/personhood/member-key.d.ts +12 -0
  44. package/dist/personhood/member-key.js +10 -0
  45. package/dist/personhood/people-client.d.ts +14 -0
  46. package/dist/personhood/people-client.js +48 -0
  47. package/dist/personhood/reprove.d.ts +43 -0
  48. package/dist/personhood/reprove.js +225 -0
  49. package/dist/pool.d.ts +7 -2
  50. package/dist/pool.js +3 -1
  51. package/dist/run-state.js +1 -1
  52. package/dist/telemetry.d.ts +7 -1
  53. package/dist/telemetry.js +8 -2
  54. package/dist/version-check.js +3 -3
  55. package/docs/e2e-bootstrap.md +36 -10
  56. package/package.json +4 -3
@@ -9,10 +9,10 @@ import {
9
9
  offerBugReport,
10
10
  scrubSecrets,
11
11
  setDeployContext
12
- } from "./chunk-SA37SLYF.js";
13
- import "./chunk-RJAFD4LO.js";
14
- import "./chunk-2VNGK2MU.js";
15
- import "./chunk-G2P5UIPX.js";
12
+ } from "./chunk-V5NUBOEX.js";
13
+ import "./chunk-FSSKFXTZ.js";
14
+ import "./chunk-WNUWAA6F.js";
15
+ import "./chunk-XWA3NPMX.js";
16
16
  export {
17
17
  buildCliFlagsSummary,
18
18
  buildLabels,
@@ -0,0 +1,284 @@
1
+ import {
2
+ buildImplicationMessage,
3
+ buildV5GeneralExtrinsic,
4
+ bytesToHex,
5
+ encodeMembers,
6
+ hexToBytes,
7
+ readExtensionOrder,
8
+ toHex
9
+ } from "./chunk-ZYVGHDMU.js";
10
+ import {
11
+ PEOPLE_MEMBER_IDENTIFIER_HEX,
12
+ PGAS_ASSET_ID,
13
+ PROOF_BYTES
14
+ } from "./chunk-T7EEVWNU.js";
15
+
16
+ // src/personhood/claim-pgas.ts
17
+ import { Enum } from "polkadot-api";
18
+ var PgasClaimError = class extends Error {
19
+ kind;
20
+ dispatchError;
21
+ constructor(message, options = {}) {
22
+ super(message, options);
23
+ this.name = "PgasClaimError";
24
+ this.kind = options.kind ?? "Unknown";
25
+ this.dispatchError = options.dispatchError;
26
+ }
27
+ };
28
+ var SECS_PER_DAY = 86400n;
29
+ var IMPLICATION_EXCLUDE = /* @__PURE__ */ new Set([
30
+ "AuthorizeCall",
31
+ "AsPgas",
32
+ "StorageWeightReclaim"
33
+ ]);
34
+ var PGAS_CONTEXT_PREFIX = new TextEncoder().encode("pop:gas:");
35
+ function buildGasContext(day, slotIndex) {
36
+ const out = new Uint8Array(32);
37
+ out.set(PGAS_CONTEXT_PREFIX, 0);
38
+ const dv = new DataView(out.buffer);
39
+ dv.setUint32(8, day, true);
40
+ dv.setUint32(12, slotIndex, true);
41
+ return out;
42
+ }
43
+ function buildAsPgasClaimExtensionValue(proof, ringIndex, revision, day) {
44
+ return Enum("Claim", {
45
+ proof: bytesToHex(proof),
46
+ ring_index: ringIndex,
47
+ revision,
48
+ collection: Enum("People"),
49
+ day
50
+ });
51
+ }
52
+ var claimPgas = async ({
53
+ peopleUnsafeApi,
54
+ ahUnsafeApi,
55
+ ahClient,
56
+ target,
57
+ memberKey,
58
+ buildRingProof,
59
+ slotIndex = 0,
60
+ progress
61
+ }) => {
62
+ const people = peopleUnsafeApi;
63
+ const ah = ahUnsafeApi;
64
+ if (memberKey.length !== 32) {
65
+ throw new PgasClaimError("memberKey must be 32 bytes", { kind: "ClientError" });
66
+ }
67
+ const asset = await ah.query.Assets.Asset.getValue(PGAS_ASSET_ID, { at: "best" });
68
+ if (!asset) {
69
+ throw new PgasClaimError(
70
+ "PGAS asset (id 2_000_000_000) does not exist on AH",
71
+ { kind: "PgasAssetNotCreated" }
72
+ );
73
+ }
74
+ const position = await people.query.Members.Members.getValue(
75
+ PEOPLE_MEMBER_IDENTIFIER_HEX,
76
+ bytesToHex(memberKey),
77
+ { at: "best" }
78
+ );
79
+ if (!position) {
80
+ throw new PgasClaimError(
81
+ "member key not present on People \u2014 recognize first",
82
+ { kind: "NotARecognizedPerson" }
83
+ );
84
+ }
85
+ if (position.type !== "Included") {
86
+ throw new PgasClaimError(
87
+ `member position is '${position.type}', expected 'Included'`,
88
+ { kind: "NotARecognizedPerson" }
89
+ );
90
+ }
91
+ const ringIndex = position.value.ring_index;
92
+ const allEntries = await people.query.Members.RingKeys.getEntries({ at: "best" });
93
+ const pages = [];
94
+ const identHex = PEOPLE_MEMBER_IDENTIFIER_HEX.toLowerCase();
95
+ for (const entry of allEntries) {
96
+ if (entry.keyArgs[0].toLowerCase() !== identHex) continue;
97
+ if (Number(entry.keyArgs[1]) !== ringIndex) continue;
98
+ pages.push([Number(entry.keyArgs[2]), [...entry.value]]);
99
+ }
100
+ pages.sort((a, b) => a[0] - b[0]);
101
+ const ringKeys = pages.flatMap(([, ks]) => ks);
102
+ if (ringKeys.length === 0) {
103
+ throw new PgasClaimError("ring has no members on People", {
104
+ kind: "ClientError"
105
+ });
106
+ }
107
+ const membersBytes = encodeMembers(ringKeys.map((k) => hexToBytes(k)));
108
+ const collectionId = await ah.constants.AliasAccounts.PeopleCollectionIdentifier();
109
+ const ringExp = await ah.constants.AliasAccounts.PeopleRingExponent();
110
+ const ringExponent = ringExp.type === "R2e9" ? 9 : ringExp.type === "R2e10" ? 10 : 14;
111
+ const ringRoots = await ah.query.MembersSubscriber.RingRoots.getValue(
112
+ collectionId,
113
+ ringIndex,
114
+ { at: "best" }
115
+ );
116
+ if (!ringRoots || ringRoots.length === 0) {
117
+ throw new PgasClaimError(
118
+ "AH has no RingRoots for this (collection, ring_index)",
119
+ { kind: "RingRootNotFound" }
120
+ );
121
+ }
122
+ const latest = ringRoots[ringRoots.length - 1];
123
+ const revision = latest.revision;
124
+ const nowRaw = await ah.query.Timestamp.Now.getValue({ at: "best" });
125
+ const nowSec = nowRaw > 10000000000n ? nowRaw / 1000n : nowRaw;
126
+ const day = Number(nowSec / SECS_PER_DAY);
127
+ const contextBytes = buildGasContext(day, slotIndex);
128
+ const innerTx = ah.tx.Pgas.claim_pgas({ slot_index: slotIndex, target });
129
+ const callBytes = await innerTx.getEncodedData();
130
+ const passEmpty = await capturePass(innerTx, void 0);
131
+ const msg = buildImplicationMessage(
132
+ callBytes,
133
+ passEmpty.extensions,
134
+ IMPLICATION_EXCLUDE
135
+ );
136
+ const { proof, alias } = await buildRingProof({
137
+ ringExponent,
138
+ members: membersBytes,
139
+ context: contextBytes,
140
+ msg
141
+ });
142
+ if (proof.length !== PROOF_BYTES) {
143
+ throw new PgasClaimError(
144
+ `ring proof must be ${PROOF_BYTES} bytes, got ${proof.length}`,
145
+ { kind: "ClientError" }
146
+ );
147
+ }
148
+ const asPgasValue = Enum("Claim", {
149
+ proof: bytesToHex(proof),
150
+ ring_index: ringIndex,
151
+ revision,
152
+ collection: Enum("People"),
153
+ day
154
+ });
155
+ const passProof = await capturePass(innerTx, asPgasValue);
156
+ const extrinsicBytes = buildV5GeneralExtrinsic(callBytes, passProof.extensions);
157
+ const extrinsicHex = toHex(extrinsicBytes);
158
+ const blockHash = await submitExtrinsic(ahClient, extrinsicHex, progress);
159
+ const amount = await ah.constants.Pgas.PgasClaimAmount();
160
+ return { blockHash, amount, alias };
161
+ };
162
+ var capturePass = async (innerTx, asPgasValue) => {
163
+ let captured = null;
164
+ const sentinel = new Error("__pgas_capture_sentinel__");
165
+ const signer = {
166
+ publicKey: new Uint8Array(32),
167
+ signTx: async (callData, signedExtensions, metadata) => {
168
+ const order = await readExtensionOrder(metadata);
169
+ const byIdentifier = {};
170
+ for (const id of order) {
171
+ const ext = signedExtensions[id];
172
+ byIdentifier[id] = {
173
+ value: ext.value,
174
+ additionalSigned: ext.additionalSigned
175
+ };
176
+ }
177
+ captured = { callData, extensions: { order, byIdentifier } };
178
+ throw sentinel;
179
+ },
180
+ signBytes: async () => new Uint8Array(64)
181
+ };
182
+ try {
183
+ await innerTx.sign(signer, {
184
+ mortality: { mortal: false },
185
+ customSignedExtensions: {
186
+ AsPgas: {
187
+ value: asPgasValue,
188
+ additionalSigned: new Uint8Array()
189
+ }
190
+ }
191
+ });
192
+ } catch (err) {
193
+ if (err !== sentinel) throw err;
194
+ }
195
+ if (captured === null) {
196
+ throw new PgasClaimError("extension capture failed", { kind: "ClientError" });
197
+ }
198
+ return captured;
199
+ };
200
+ var narrowDispatchError = (dispatchError) => {
201
+ if (typeof dispatchError === "object" && dispatchError !== null && "type" in dispatchError) {
202
+ const d = dispatchError;
203
+ if (d.type === "Invalid" && typeof d.value === "object" && d.value !== null) {
204
+ const v = d.value;
205
+ if (v.type === "BadProof") return "BadProof";
206
+ if (v.type === "Custom") {
207
+ switch (v.value) {
208
+ case 230:
209
+ return "InvalidClaimSlot";
210
+ case 231:
211
+ return "InvalidClaimDay";
212
+ case 232:
213
+ return "AlreadyClaimedToday";
214
+ case 233:
215
+ return "PgasAssetNotCreated";
216
+ }
217
+ }
218
+ }
219
+ }
220
+ return "DispatchError";
221
+ };
222
+ var submitExtrinsic = (client, extrinsicHex, progress) => {
223
+ return new Promise((resolve, reject) => {
224
+ let settled = false;
225
+ const fail = (err) => {
226
+ if (settled) return;
227
+ settled = true;
228
+ reject(err);
229
+ };
230
+ const succeed = (h) => {
231
+ if (settled) return;
232
+ settled = true;
233
+ resolve(h);
234
+ };
235
+ client.submitAndWatch(hexToBytes(extrinsicHex)).subscribe({
236
+ next: (event) => {
237
+ if (settled) return;
238
+ if (event.type === "broadcasted") {
239
+ progress?.onBroadcasted?.();
240
+ return;
241
+ }
242
+ if (event.type === "txBestBlocksState" && event.found) {
243
+ if (event.ok === false) {
244
+ fail(
245
+ new PgasClaimError("claim_pgas dispatched but failed in-block", {
246
+ kind: narrowDispatchError(event.dispatchError),
247
+ dispatchError: event.dispatchError
248
+ })
249
+ );
250
+ return;
251
+ }
252
+ progress?.onBestBlock?.(event.block.hash);
253
+ return;
254
+ }
255
+ if (event.type === "finalized") {
256
+ if (event.ok === false) {
257
+ fail(
258
+ new PgasClaimError("claim_pgas failed at finalization", {
259
+ kind: narrowDispatchError(event.dispatchError),
260
+ dispatchError: event.dispatchError
261
+ })
262
+ );
263
+ return;
264
+ }
265
+ succeed(event.block.hash);
266
+ }
267
+ },
268
+ error: (err) => {
269
+ fail(
270
+ err instanceof PgasClaimError ? err : new PgasClaimError(
271
+ err instanceof Error ? `RPC rejected extrinsic: ${err.message}` : "RPC error during submitAndWatch",
272
+ { cause: err, kind: "RpcError" }
273
+ )
274
+ );
275
+ }
276
+ });
277
+ });
278
+ };
279
+
280
+ export {
281
+ PgasClaimError,
282
+ buildAsPgasClaimExtensionValue,
283
+ claimPgas
284
+ };
@@ -0,0 +1,207 @@
1
+ import {
2
+ buildImplicationMessage,
3
+ buildV5GeneralExtrinsic,
4
+ bytesToHex,
5
+ hexToBytes,
6
+ readExtensionOrder,
7
+ toHex
8
+ } from "./chunk-ZYVGHDMU.js";
9
+ import {
10
+ BANDERSNATCH_SIGNATURE_BYTES
11
+ } from "./chunk-T7EEVWNU.js";
12
+
13
+ // src/personhood/bind-personal-id.ts
14
+ import { Enum } from "polkadot-api";
15
+ var AS_PERSON_IDENTIFIER = "AsPerson";
16
+ var VERIFY_MULTI_SIGNATURE_IDENTIFIER = "VerifyMultiSignature";
17
+ var IMPLICATION_EXCLUDE = /* @__PURE__ */ new Set([
18
+ "VerifyMultiSignature",
19
+ AS_PERSON_IDENTIFIER,
20
+ "AuthorizeCall",
21
+ "StorageWeightReclaim"
22
+ ]);
23
+ var PersonalIdBindingError = class extends Error {
24
+ dispatchError;
25
+ kind;
26
+ constructor(message, options = {}) {
27
+ super(message, options);
28
+ this.name = "PersonalIdBindingError";
29
+ this.kind = options.kind ?? "unknown";
30
+ this.dispatchError = options.dispatchError;
31
+ }
32
+ };
33
+ function buildAsPersonExtensionValue(signature, personalId) {
34
+ return Enum("AsPersonalIdentityWithProof", [bytesToHex(signature), personalId]);
35
+ }
36
+ var bindPersonalIdToAccount = async ({
37
+ typedApi,
38
+ client,
39
+ personalId,
40
+ account,
41
+ signMember,
42
+ callValidAt,
43
+ progress
44
+ }) => {
45
+ const api = typedApi;
46
+ if (typeof api.tx?.People?.set_personal_id_account !== "function") {
47
+ throw new PersonalIdBindingError(
48
+ "typedApi does not expose People.set_personal_id_account \u2014 wrong chain or stale descriptors",
49
+ { kind: "client_error" }
50
+ );
51
+ }
52
+ const block = callValidAt ?? await api.query.System.Number.getValue();
53
+ const innerTx = api.tx.People.set_personal_id_account({
54
+ account,
55
+ call_valid_at: block
56
+ });
57
+ const callBytes = await innerTx.getEncodedData();
58
+ const passEmpty = await capturePass({
59
+ innerTx,
60
+ asPersonValue: new Uint8Array()
61
+ });
62
+ const msgHash = buildImplicationMessage(
63
+ callBytes,
64
+ passEmpty.extensions,
65
+ IMPLICATION_EXCLUDE
66
+ );
67
+ const signature = await Promise.resolve(signMember(msgHash));
68
+ if (signature.length !== BANDERSNATCH_SIGNATURE_BYTES) {
69
+ throw new PersonalIdBindingError(
70
+ `Bandersnatch signature must be ${BANDERSNATCH_SIGNATURE_BYTES} bytes, got ${signature.length}`,
71
+ { kind: "client_error" }
72
+ );
73
+ }
74
+ const asPersonProof = Enum("AsPersonalIdentityWithProof", [bytesToHex(signature), personalId]);
75
+ const passProof = await capturePass({
76
+ innerTx,
77
+ asPersonValue: asPersonProof
78
+ });
79
+ const extrinsicBytes = buildV5GeneralExtrinsic(callBytes, passProof.extensions);
80
+ const extrinsicHex = toHex(extrinsicBytes);
81
+ const blockHash = await submitExtrinsic(client, extrinsicHex, progress);
82
+ return { extrinsicHex, blockHash };
83
+ };
84
+ var capturePass = async ({
85
+ innerTx,
86
+ asPersonValue
87
+ }) => {
88
+ let captured = null;
89
+ const sentinel = new Error("__personhood_capture_sentinel__");
90
+ const signer = {
91
+ publicKey: new Uint8Array(32),
92
+ signTx: async (callData, signedExtensions, metadata) => {
93
+ const order = await readExtensionOrder(metadata);
94
+ const byIdentifier = {};
95
+ for (const id of order) {
96
+ const ext = signedExtensions[id];
97
+ if (!ext) {
98
+ throw new PersonalIdBindingError(
99
+ `papi did not produce signed extension '${id}'`
100
+ );
101
+ }
102
+ byIdentifier[id] = {
103
+ value: ext.value,
104
+ additionalSigned: ext.additionalSigned
105
+ };
106
+ }
107
+ captured = { callData, extensions: { order, byIdentifier } };
108
+ throw sentinel;
109
+ },
110
+ signBytes: async () => new Uint8Array(64)
111
+ };
112
+ try {
113
+ await innerTx.sign(signer, {
114
+ customSignedExtensions: {
115
+ [AS_PERSON_IDENTIFIER]: {
116
+ value: asPersonValue,
117
+ additionalSigned: new Uint8Array()
118
+ },
119
+ [VERIFY_MULTI_SIGNATURE_IDENTIFIER]: {
120
+ value: Enum("Disabled")
121
+ },
122
+ RestrictOrigins: {
123
+ value: new Uint8Array([1]),
124
+ additionalSigned: new Uint8Array()
125
+ }
126
+ }
127
+ });
128
+ } catch (err) {
129
+ if (err !== sentinel) throw err;
130
+ }
131
+ if (!captured) {
132
+ throw new PersonalIdBindingError(
133
+ "extension capture failed \u2014 papi never invoked signTx",
134
+ { kind: "client_error" }
135
+ );
136
+ }
137
+ return captured;
138
+ };
139
+ var submitExtrinsic = (client, extrinsicHex, progress) => {
140
+ return new Promise((resolve, reject) => {
141
+ let settled = false;
142
+ const fail = (err) => {
143
+ if (settled) return;
144
+ settled = true;
145
+ reject(err);
146
+ };
147
+ const succeed = (blockHash) => {
148
+ if (settled) return;
149
+ settled = true;
150
+ resolve(blockHash);
151
+ };
152
+ client.submitAndWatch(hexToBytes(extrinsicHex)).subscribe({
153
+ next: (event) => {
154
+ if (settled) return;
155
+ if (event.type === "broadcasted") {
156
+ progress?.onBroadcasted?.();
157
+ return;
158
+ }
159
+ if (event.type === "txBestBlocksState" && event.found) {
160
+ if (event.ok === false) {
161
+ fail(
162
+ new PersonalIdBindingError(
163
+ "set_personal_id_account dispatched but failed in-block",
164
+ {
165
+ kind: "dispatch_error",
166
+ dispatchError: event.dispatchError
167
+ }
168
+ )
169
+ );
170
+ return;
171
+ }
172
+ progress?.onBestBlock?.(event.block.hash);
173
+ return;
174
+ }
175
+ if (event.type === "finalized") {
176
+ if (event.ok === false) {
177
+ fail(
178
+ new PersonalIdBindingError(
179
+ "set_personal_id_account dispatch failed at finalization",
180
+ {
181
+ kind: "dispatch_error",
182
+ dispatchError: event.dispatchError
183
+ }
184
+ )
185
+ );
186
+ return;
187
+ }
188
+ succeed(event.block.hash);
189
+ }
190
+ },
191
+ error: (err) => {
192
+ fail(
193
+ err instanceof PersonalIdBindingError ? err : new PersonalIdBindingError(
194
+ err instanceof Error ? `RPC rejected extrinsic: ${err.message}` : "RPC error during submitAndWatch",
195
+ { cause: err, kind: "rpc_error" }
196
+ )
197
+ );
198
+ }
199
+ });
200
+ });
201
+ };
202
+
203
+ export {
204
+ PersonalIdBindingError,
205
+ buildAsPersonExtensionValue,
206
+ bindPersonalIdToAccount
207
+ };