@novasamatech/host-papp 0.9.1 → 0.9.3
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/.papi/descriptors/dist/common-types.d.ts +1483 -1359
- package/.papi/descriptors/dist/descriptors-BLqmZ_vS.js +25 -0
- package/.papi/descriptors/dist/index.d.ts +1 -1
- package/.papi/descriptors/dist/index.js +8 -6
- package/.papi/descriptors/dist/metadataTypes-wXgvb64i.js +3 -0
- package/.papi/descriptors/dist/metadataTypes.d.ts +1 -1
- package/.papi/descriptors/dist/people_lite.d.ts +1175 -1001
- package/.papi/descriptors/dist/people_lite_metadata-CwU9OBGy.js +3 -0
- package/.papi/descriptors/generated.json +1 -1
- package/.papi/descriptors/package.json +1 -1
- package/.papi/metadata/people_lite.scale +0 -0
- package/.papi/polkadot-api.json +3 -3
- package/README.md +140 -87
- package/dist/identity/identifierKey.d.ts +19 -0
- package/dist/identity/identifierKey.js +17 -0
- package/dist/identity/impl.js +12 -17
- package/dist/identity/index.d.ts +2 -0
- package/dist/identity/index.js +1 -0
- package/dist/identity/rpcAdapter.d.ts +5 -1
- package/dist/identity/rpcAdapter.js +9 -3
- package/dist/identity/types.d.ts +9 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +2 -0
- package/dist/sso/sessionManager/scale/remoteMessage.d.ts +102 -2
- package/dist/sso/sessionManager/scale/remoteMessage.js +11 -1
- package/dist/sso/sessionManager/scale/resourceAllocation.d.ts +3 -0
- package/dist/sso/sessionManager/scale/resourceAllocation.js +11 -0
- package/dist/sso/sessionManager/scale/ringVrf.d.ts +43 -2
- package/dist/sso/sessionManager/scale/ringVrf.js +12 -1
- package/dist/sso/sessionManager/scale/ringVrfKeys.d.ts +85 -0
- package/dist/sso/sessionManager/scale/ringVrfKeys.js +22 -0
- package/dist/sso/sessionManager/userSession.d.ts +22 -3
- package/dist/sso/sessionManager/userSession.js +59 -3
- package/package.json +9 -5
- package/.papi/descriptors/dist/descriptors-D5oN4i7I.js +0 -25
- package/.papi/descriptors/dist/metadataTypes-BaUy_4gO.js +0 -3
- package/.papi/descriptors/dist/people_lite_metadata-Cj1JLFI2.js +0 -3
|
@@ -67,6 +67,13 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
67
67
|
tag: "RingVrfAliasRequest";
|
|
68
68
|
value: {
|
|
69
69
|
callingProductId: string;
|
|
70
|
+
keyHandle: [string, {
|
|
71
|
+
tag: "Index";
|
|
72
|
+
value: number;
|
|
73
|
+
} | {
|
|
74
|
+
tag: "Raw";
|
|
75
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
76
|
+
}];
|
|
70
77
|
context: [string, {
|
|
71
78
|
tag: "Index";
|
|
72
79
|
value: number;
|
|
@@ -94,7 +101,7 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
94
101
|
alias: Uint8Array<ArrayBufferLike>;
|
|
95
102
|
}, import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
96
103
|
reason: string;
|
|
97
|
-
}, "GetAliasErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::NotMember">>;
|
|
104
|
+
}, "GetAliasErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::NotMember"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::KeyNotRegistered"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::KeyNotInRing">>;
|
|
98
105
|
};
|
|
99
106
|
} | {
|
|
100
107
|
tag: "ResourceAllocationRequest";
|
|
@@ -142,6 +149,7 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
142
149
|
tag: "AutoSigning";
|
|
143
150
|
value: {
|
|
144
151
|
productRootPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
152
|
+
ringVrfDomainEntropy: Uint8Array<ArrayBufferLike>;
|
|
145
153
|
};
|
|
146
154
|
} | {
|
|
147
155
|
tag: "BulletInAllowance";
|
|
@@ -224,6 +232,13 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
224
232
|
tag: "RingVrfProofRequest";
|
|
225
233
|
value: {
|
|
226
234
|
callingProductId: string;
|
|
235
|
+
keyHandle: [string, {
|
|
236
|
+
tag: "Index";
|
|
237
|
+
value: number;
|
|
238
|
+
} | {
|
|
239
|
+
tag: "Raw";
|
|
240
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
241
|
+
}];
|
|
227
242
|
context: [string, {
|
|
228
243
|
tag: "Index";
|
|
229
244
|
value: number;
|
|
@@ -257,7 +272,7 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
257
272
|
ringRevision: number;
|
|
258
273
|
}, import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
259
274
|
reason: string;
|
|
260
|
-
}, "CreateProofErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::NotMember">>;
|
|
275
|
+
}, "CreateProofErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::NotMember"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::KeyNotRegistered"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::KeyNotInRing"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::NotAllowlisted">>;
|
|
261
276
|
};
|
|
262
277
|
} | {
|
|
263
278
|
tag: "SignVrfRequest";
|
|
@@ -300,6 +315,91 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
300
315
|
productPublicKey: Uint8Array<ArrayBufferLike>;
|
|
301
316
|
}, string>;
|
|
302
317
|
};
|
|
318
|
+
} | {
|
|
319
|
+
tag: "RegisterRingVrfKeyRequest";
|
|
320
|
+
value: {
|
|
321
|
+
callingProductId: string;
|
|
322
|
+
index: {
|
|
323
|
+
tag: "Index";
|
|
324
|
+
value: number;
|
|
325
|
+
} | {
|
|
326
|
+
tag: "Raw";
|
|
327
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
328
|
+
};
|
|
329
|
+
ring: {
|
|
330
|
+
chainId: `0x${string}`;
|
|
331
|
+
junctions: ({
|
|
332
|
+
tag: "PalletInstance";
|
|
333
|
+
value: number;
|
|
334
|
+
} | {
|
|
335
|
+
tag: "CollectionId";
|
|
336
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
337
|
+
})[];
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
} | {
|
|
341
|
+
tag: "RegisterRingVrfKeyResponse";
|
|
342
|
+
value: {
|
|
343
|
+
respondingTo: string;
|
|
344
|
+
payload: import("scale-ts").ResultPayload<Uint8Array<ArrayBufferLike>, import("@novasamatech/scale").CodecError<undefined, "RegisterRingVrfKeyErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RegisterRingVrfKeyErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
345
|
+
reason: string;
|
|
346
|
+
}, "RegisterRingVrfKeyErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "RegisterRingVrfKeyErr::RingNotFound">>;
|
|
347
|
+
};
|
|
348
|
+
} | {
|
|
349
|
+
tag: "ListRingVrfKeysRequest";
|
|
350
|
+
value: {
|
|
351
|
+
callingProductId: string;
|
|
352
|
+
owner: string;
|
|
353
|
+
disclosure: "Anonymized" | "PublicKey";
|
|
354
|
+
};
|
|
355
|
+
} | {
|
|
356
|
+
tag: "ListRingVrfKeysResponse";
|
|
357
|
+
value: {
|
|
358
|
+
respondingTo: string;
|
|
359
|
+
payload: import("scale-ts").ResultPayload<{
|
|
360
|
+
handle: [string, {
|
|
361
|
+
tag: "Index";
|
|
362
|
+
value: number;
|
|
363
|
+
} | {
|
|
364
|
+
tag: "Raw";
|
|
365
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
366
|
+
}];
|
|
367
|
+
rings: {
|
|
368
|
+
chainId: `0x${string}`;
|
|
369
|
+
junctions: ({
|
|
370
|
+
tag: "PalletInstance";
|
|
371
|
+
value: number;
|
|
372
|
+
} | {
|
|
373
|
+
tag: "CollectionId";
|
|
374
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
375
|
+
})[];
|
|
376
|
+
}[];
|
|
377
|
+
publicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
378
|
+
}[], import("@novasamatech/scale").CodecError<undefined, "ListRingVrfKeysErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "ListRingVrfKeysErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
379
|
+
reason: string;
|
|
380
|
+
}, "ListRingVrfKeysErr::Unknown">>;
|
|
381
|
+
};
|
|
382
|
+
} | {
|
|
383
|
+
tag: "RingVrfSignRequest";
|
|
384
|
+
value: {
|
|
385
|
+
callingProductId: string;
|
|
386
|
+
keyHandle: [string, {
|
|
387
|
+
tag: "Index";
|
|
388
|
+
value: number;
|
|
389
|
+
} | {
|
|
390
|
+
tag: "Raw";
|
|
391
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
392
|
+
}];
|
|
393
|
+
message: Uint8Array<ArrayBufferLike>;
|
|
394
|
+
};
|
|
395
|
+
} | {
|
|
396
|
+
tag: "RingVrfSignResponse";
|
|
397
|
+
value: {
|
|
398
|
+
respondingTo: string;
|
|
399
|
+
payload: import("scale-ts").ResultPayload<Uint8Array<ArrayBufferLike>, import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
400
|
+
reason: string;
|
|
401
|
+
}, "RingVrfSignErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::KeyNotRegistered"> | import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::NotAllowlisted">>;
|
|
402
|
+
};
|
|
303
403
|
};
|
|
304
404
|
};
|
|
305
405
|
}>;
|
|
@@ -3,7 +3,8 @@ import { Struct, _void, str } from 'scale-ts';
|
|
|
3
3
|
import { CreateTransactionLegacyRequestCodec, CreateTransactionRequestCodec, CreateTransactionResponseCodec, } from './createTransaction.js';
|
|
4
4
|
import { ProductSubtreeRequestCodec, ProductSubtreeResponseCodec } from './productSubtree.js';
|
|
5
5
|
import { ResourceAllocationRequestCodec, ResourceAllocationResponseCodec } from './resourceAllocation.js';
|
|
6
|
-
import { RingVrfAliasRequestCodec, RingVrfAliasResponseCodec, RingVrfProofRequestCodec, RingVrfProofResponseCodec, } from './ringVrf.js';
|
|
6
|
+
import { RingVrfAliasRequestCodec, RingVrfAliasResponseCodec, RingVrfProofRequestCodec, RingVrfProofResponseCodec, RingVrfSignRequestCodec, RingVrfSignResponseCodec, } from './ringVrf.js';
|
|
7
|
+
import { ListRingVrfKeysRequestCodec, ListRingVrfKeysResponseCodec, RegisterRingVrfKeyRequestCodec, RegisterRingVrfKeyResponseCodec, } from './ringVrfKeys.js';
|
|
7
8
|
import { SignVrfRequestCodec, SignVrfResponseCodec } from './signVrf.js';
|
|
8
9
|
import { SignRawLegacyRequestCodec, SignRawLegacyResponseCodec, SigningRequestCodec, SigningResponseCodec, } from './signing.js';
|
|
9
10
|
export const RemoteMessageCodec = Struct({
|
|
@@ -31,6 +32,15 @@ export const RemoteMessageCodec = Struct({
|
|
|
31
32
|
// RFC-0022 additions — appended so existing variant indexes stay stable.
|
|
32
33
|
ProductSubtreeRequest: ProductSubtreeRequestCodec,
|
|
33
34
|
ProductSubtreeResponse: ProductSubtreeResponseCodec,
|
|
35
|
+
// RFC-0024 additions — likewise appended. `RingVrfAliasRequest` and
|
|
36
|
+
// `RingVrfProofRequest` above gained a `keyHandle` field in place rather
|
|
37
|
+
// than being re-added here, since a handle is now mandatory on both.
|
|
38
|
+
RegisterRingVrfKeyRequest: RegisterRingVrfKeyRequestCodec,
|
|
39
|
+
RegisterRingVrfKeyResponse: RegisterRingVrfKeyResponseCodec,
|
|
40
|
+
ListRingVrfKeysRequest: ListRingVrfKeysRequestCodec,
|
|
41
|
+
ListRingVrfKeysResponse: ListRingVrfKeysResponseCodec,
|
|
42
|
+
RingVrfSignRequest: RingVrfSignRequestCodec,
|
|
43
|
+
RingVrfSignResponse: RingVrfSignResponseCodec,
|
|
34
44
|
}),
|
|
35
45
|
}),
|
|
36
46
|
});
|
|
@@ -32,6 +32,7 @@ export declare const ApAllocatedResourceCodec: import("scale-ts").Codec<{
|
|
|
32
32
|
tag: "AutoSigning";
|
|
33
33
|
value: {
|
|
34
34
|
productRootPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
35
|
+
ringVrfDomainEntropy: Uint8Array<ArrayBufferLike>;
|
|
35
36
|
};
|
|
36
37
|
} | {
|
|
37
38
|
tag: "BulletInAllowance";
|
|
@@ -57,6 +58,7 @@ export declare const ApAllocationOutcomeCodec: import("scale-ts").Codec<{
|
|
|
57
58
|
tag: "AutoSigning";
|
|
58
59
|
value: {
|
|
59
60
|
productRootPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
61
|
+
ringVrfDomainEntropy: Uint8Array<ArrayBufferLike>;
|
|
60
62
|
};
|
|
61
63
|
} | {
|
|
62
64
|
tag: "BulletInAllowance";
|
|
@@ -113,6 +115,7 @@ export declare const ResourceAllocationResponseCodec: import("scale-ts").Codec<{
|
|
|
113
115
|
tag: "AutoSigning";
|
|
114
116
|
value: {
|
|
115
117
|
productRootPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
118
|
+
ringVrfDomainEntropy: Uint8Array<ArrayBufferLike>;
|
|
116
119
|
};
|
|
117
120
|
} | {
|
|
118
121
|
tag: "BulletInAllowance";
|
|
@@ -23,6 +23,17 @@ export const ApAllocatedResourceCodec = Enum({
|
|
|
23
23
|
// `Sr25519PrivateKey ++ Sr25519Nonce` (64 bytes): the full expanded secret
|
|
24
24
|
// needed to sign and soft-derive `/{index}` below the product root.
|
|
25
25
|
productRootPrivateKey: Bytes(),
|
|
26
|
+
// RFC-0024: entropy of the `//{productId}` node of the ring VRF tree, which
|
|
27
|
+
// is disjoint from the sr25519 product-account tree above. It lets the Host
|
|
28
|
+
// derive the member secret of a *registered* key locally — the second
|
|
29
|
+
// motivation being that a headless Account Holder execution context may not
|
|
30
|
+
// fit a ring VRF proof inside its ~30 s / ~24 MB budget.
|
|
31
|
+
//
|
|
32
|
+
// Derivation from this entropy is unconditional arithmetic: nothing about
|
|
33
|
+
// holding it distinguishes a meaningful index from a meaningless one, so the
|
|
34
|
+
// registry supplies that distinction. A Host MUST NOT derive a member secret
|
|
35
|
+
// for a `(product, index)` pair absent from its registry.
|
|
36
|
+
ringVrfDomainEntropy: Bytes(),
|
|
26
37
|
}),
|
|
27
38
|
});
|
|
28
39
|
export const ApAllocationOutcomeCodec = Enum({
|
|
@@ -2,6 +2,13 @@ import type { CodecType } from 'scale-ts';
|
|
|
2
2
|
export type RingVrfAliasRequest = CodecType<typeof RingVrfAliasRequestCodec>;
|
|
3
3
|
export declare const RingVrfAliasRequestCodec: import("scale-ts").Codec<{
|
|
4
4
|
callingProductId: string;
|
|
5
|
+
keyHandle: [string, {
|
|
6
|
+
tag: "Index";
|
|
7
|
+
value: number;
|
|
8
|
+
} | {
|
|
9
|
+
tag: "Raw";
|
|
10
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
11
|
+
}];
|
|
5
12
|
context: [string, {
|
|
6
13
|
tag: "Index";
|
|
7
14
|
value: number;
|
|
@@ -28,11 +35,18 @@ export declare const RingVrfAliasResponseCodec: import("scale-ts").Codec<{
|
|
|
28
35
|
alias: Uint8Array<ArrayBufferLike>;
|
|
29
36
|
}, import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
30
37
|
reason: string;
|
|
31
|
-
}, "GetAliasErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::NotMember">>;
|
|
38
|
+
}, "GetAliasErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::NotMember"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::KeyNotRegistered"> | import("@novasamatech/scale").CodecError<undefined, "GetAliasErr::KeyNotInRing">>;
|
|
32
39
|
}>;
|
|
33
40
|
export type RingVrfProofRequest = CodecType<typeof RingVrfProofRequestCodec>;
|
|
34
41
|
export declare const RingVrfProofRequestCodec: import("scale-ts").Codec<{
|
|
35
42
|
callingProductId: string;
|
|
43
|
+
keyHandle: [string, {
|
|
44
|
+
tag: "Index";
|
|
45
|
+
value: number;
|
|
46
|
+
} | {
|
|
47
|
+
tag: "Raw";
|
|
48
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
49
|
+
}];
|
|
36
50
|
context: [string, {
|
|
37
51
|
tag: "Index";
|
|
38
52
|
value: number;
|
|
@@ -65,5 +79,32 @@ export declare const RingVrfProofResponseCodec: import("scale-ts").Codec<{
|
|
|
65
79
|
ringRevision: number;
|
|
66
80
|
}, import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
67
81
|
reason: string;
|
|
68
|
-
}, "CreateProofErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::NotMember">>;
|
|
82
|
+
}, "CreateProofErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::RingNotFound"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::NotMember"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::KeyNotRegistered"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::KeyNotInRing"> | import("@novasamatech/scale").CodecError<undefined, "CreateProofErr::NotAllowlisted">>;
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Host → Account Holder request for a plain signature by the ring VRF member key
|
|
86
|
+
* itself (RFC-0024 `ring_vrf_sign`), rather than an anonymous ring proof.
|
|
87
|
+
*
|
|
88
|
+
* Carries no context and no ring: the signature derives no alias and proves no
|
|
89
|
+
* membership, so there is nothing for either to scope. It is verified against
|
|
90
|
+
* the member public key and is therefore linkable to every other use of the key.
|
|
91
|
+
*/
|
|
92
|
+
export type RingVrfSignRequest = CodecType<typeof RingVrfSignRequestCodec>;
|
|
93
|
+
export declare const RingVrfSignRequestCodec: import("scale-ts").Codec<{
|
|
94
|
+
callingProductId: string;
|
|
95
|
+
keyHandle: [string, {
|
|
96
|
+
tag: "Index";
|
|
97
|
+
value: number;
|
|
98
|
+
} | {
|
|
99
|
+
tag: "Raw";
|
|
100
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
101
|
+
}];
|
|
102
|
+
message: Uint8Array<ArrayBufferLike>;
|
|
103
|
+
}>;
|
|
104
|
+
export type RingVrfSignResponse = CodecType<typeof RingVrfSignResponseCodec>;
|
|
105
|
+
export declare const RingVrfSignResponseCodec: import("scale-ts").Codec<{
|
|
106
|
+
respondingTo: string;
|
|
107
|
+
payload: import("scale-ts").ResultPayload<Uint8Array<ArrayBufferLike>, import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
108
|
+
reason: string;
|
|
109
|
+
}, "RingVrfSignErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::KeyNotRegistered"> | import("@novasamatech/scale").CodecError<undefined, "RingVrfSignErr::NotAllowlisted">>;
|
|
69
110
|
}>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ContextualAlias, CreateProofErr, DotNsIdentifier, GetAliasErr, ProductProofContext, RingLocation, RingVrfProof, } from '@novasamatech/host-api';
|
|
1
|
+
import { ContextualAlias, CreateProofErr, DotNsIdentifier, GetAliasErr, ProductProofContext, RingLocation, RingVrfKeyHandle, RingVrfProof, RingVrfSignErr, } from '@novasamatech/host-api';
|
|
2
2
|
import { Bytes } from '@novasamatech/scale';
|
|
3
3
|
import { Result, Struct, str } from 'scale-ts';
|
|
4
4
|
export const RingVrfAliasRequestCodec = Struct({
|
|
5
5
|
callingProductId: DotNsIdentifier,
|
|
6
|
+
keyHandle: RingVrfKeyHandle,
|
|
6
7
|
context: ProductProofContext,
|
|
7
8
|
ring: RingLocation,
|
|
8
9
|
});
|
|
@@ -12,6 +13,7 @@ export const RingVrfAliasResponseCodec = Struct({
|
|
|
12
13
|
});
|
|
13
14
|
export const RingVrfProofRequestCodec = Struct({
|
|
14
15
|
callingProductId: DotNsIdentifier,
|
|
16
|
+
keyHandle: RingVrfKeyHandle,
|
|
15
17
|
context: ProductProofContext,
|
|
16
18
|
ring: RingLocation,
|
|
17
19
|
message: Bytes(),
|
|
@@ -20,3 +22,12 @@ export const RingVrfProofResponseCodec = Struct({
|
|
|
20
22
|
respondingTo: str,
|
|
21
23
|
payload: Result(RingVrfProof, CreateProofErr),
|
|
22
24
|
});
|
|
25
|
+
export const RingVrfSignRequestCodec = Struct({
|
|
26
|
+
callingProductId: DotNsIdentifier,
|
|
27
|
+
keyHandle: RingVrfKeyHandle,
|
|
28
|
+
message: Bytes(),
|
|
29
|
+
});
|
|
30
|
+
export const RingVrfSignResponseCodec = Struct({
|
|
31
|
+
respondingTo: str,
|
|
32
|
+
payload: Result(Bytes(), RingVrfSignErr),
|
|
33
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { CodecType } from 'scale-ts';
|
|
2
|
+
/**
|
|
3
|
+
* Host → Account Holder registration of a key the calling product owns.
|
|
4
|
+
*
|
|
5
|
+
* Ownership is `callingProductId` and is never chosen by the caller, so this is
|
|
6
|
+
* consent-free. Registration is idempotent: re-registering an `index` for an
|
|
7
|
+
* additional `ring` extends the existing entry rather than creating a second
|
|
8
|
+
* one, so re-notifying the phone about an entry it already has costs nothing.
|
|
9
|
+
*
|
|
10
|
+
* A Host holding the product's ring VRF domain entropy (see `AutoSigning` in
|
|
11
|
+
* `resourceAllocation.ts`) answers immediately and mirrors this fire-and-forget;
|
|
12
|
+
* without the entropy it issues the request and waits.
|
|
13
|
+
*
|
|
14
|
+
* > A Host MUST NOT derive a member secret for a `(product, index)` pair absent
|
|
15
|
+
* > from its registry. Domain entropy makes derivation unconditional — only
|
|
16
|
+
* > registration, which always reaches the phone, brings a key into existence.
|
|
17
|
+
*/
|
|
18
|
+
export type RegisterRingVrfKeyRequest = CodecType<typeof RegisterRingVrfKeyRequestCodec>;
|
|
19
|
+
export declare const RegisterRingVrfKeyRequestCodec: import("scale-ts").Codec<{
|
|
20
|
+
callingProductId: string;
|
|
21
|
+
index: {
|
|
22
|
+
tag: "Index";
|
|
23
|
+
value: number;
|
|
24
|
+
} | {
|
|
25
|
+
tag: "Raw";
|
|
26
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
27
|
+
};
|
|
28
|
+
ring: {
|
|
29
|
+
chainId: `0x${string}`;
|
|
30
|
+
junctions: ({
|
|
31
|
+
tag: "PalletInstance";
|
|
32
|
+
value: number;
|
|
33
|
+
} | {
|
|
34
|
+
tag: "CollectionId";
|
|
35
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
36
|
+
})[];
|
|
37
|
+
};
|
|
38
|
+
}>;
|
|
39
|
+
export type RegisterRingVrfKeyResponse = CodecType<typeof RegisterRingVrfKeyResponseCodec>;
|
|
40
|
+
export declare const RegisterRingVrfKeyResponseCodec: import("scale-ts").Codec<{
|
|
41
|
+
respondingTo: string;
|
|
42
|
+
payload: import("scale-ts").ResultPayload<Uint8Array<ArrayBufferLike>, import("@novasamatech/scale").CodecError<undefined, "RegisterRingVrfKeyErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "RegisterRingVrfKeyErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
43
|
+
reason: string;
|
|
44
|
+
}, "RegisterRingVrfKeyErr::Unknown"> | import("@novasamatech/scale").CodecError<undefined, "RegisterRingVrfKeyErr::RingNotFound">>;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Host → Account Holder listing of the registry entries owned by `owner`.
|
|
48
|
+
*
|
|
49
|
+
* `owner` may be `callingProductId` — permissionless — or another product, in
|
|
50
|
+
* which case the caller needs a grant. `PublicKey` disclosure additionally
|
|
51
|
+
* returns the member public key, which is linkable across every ring it appears
|
|
52
|
+
* in and so is permissioned cross-product even though the handle is not.
|
|
53
|
+
*/
|
|
54
|
+
export type ListRingVrfKeysRequest = CodecType<typeof ListRingVrfKeysRequestCodec>;
|
|
55
|
+
export declare const ListRingVrfKeysRequestCodec: import("scale-ts").Codec<{
|
|
56
|
+
callingProductId: string;
|
|
57
|
+
owner: string;
|
|
58
|
+
disclosure: "Anonymized" | "PublicKey";
|
|
59
|
+
}>;
|
|
60
|
+
export type ListRingVrfKeysResponse = CodecType<typeof ListRingVrfKeysResponseCodec>;
|
|
61
|
+
export declare const ListRingVrfKeysResponseCodec: import("scale-ts").Codec<{
|
|
62
|
+
respondingTo: string;
|
|
63
|
+
payload: import("scale-ts").ResultPayload<{
|
|
64
|
+
handle: [string, {
|
|
65
|
+
tag: "Index";
|
|
66
|
+
value: number;
|
|
67
|
+
} | {
|
|
68
|
+
tag: "Raw";
|
|
69
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
70
|
+
}];
|
|
71
|
+
rings: {
|
|
72
|
+
chainId: `0x${string}`;
|
|
73
|
+
junctions: ({
|
|
74
|
+
tag: "PalletInstance";
|
|
75
|
+
value: number;
|
|
76
|
+
} | {
|
|
77
|
+
tag: "CollectionId";
|
|
78
|
+
value: Uint8Array<ArrayBufferLike>;
|
|
79
|
+
})[];
|
|
80
|
+
}[];
|
|
81
|
+
publicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
82
|
+
}[], import("@novasamatech/scale").CodecError<undefined, "ListRingVrfKeysErr::NotConnected"> | import("@novasamatech/scale").CodecError<undefined, "ListRingVrfKeysErr::Rejected"> | import("@novasamatech/scale").CodecError<{
|
|
83
|
+
reason: string;
|
|
84
|
+
}, "ListRingVrfKeysErr::Unknown">>;
|
|
85
|
+
}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DerivationIndex, DotNsIdentifier, ListRingVrfKeysErr, RegisterRingVrfKeyErr, RegisteredRingVrfKey, RingLocation, RingVrfKeyDisclosure, RingVrfPublicKey, } from '@novasamatech/host-api';
|
|
2
|
+
import { Result, Struct, Vector, str } from 'scale-ts';
|
|
3
|
+
export const RegisterRingVrfKeyRequestCodec = Struct({
|
|
4
|
+
callingProductId: DotNsIdentifier,
|
|
5
|
+
index: DerivationIndex,
|
|
6
|
+
ring: RingLocation,
|
|
7
|
+
});
|
|
8
|
+
export const RegisterRingVrfKeyResponseCodec = Struct({
|
|
9
|
+
// referencing to RemoteMessage.messageId
|
|
10
|
+
respondingTo: str,
|
|
11
|
+
payload: Result(RingVrfPublicKey, RegisterRingVrfKeyErr),
|
|
12
|
+
});
|
|
13
|
+
export const ListRingVrfKeysRequestCodec = Struct({
|
|
14
|
+
callingProductId: DotNsIdentifier,
|
|
15
|
+
owner: DotNsIdentifier,
|
|
16
|
+
disclosure: RingVrfKeyDisclosure,
|
|
17
|
+
});
|
|
18
|
+
export const ListRingVrfKeysResponseCodec = Struct({
|
|
19
|
+
// referencing to RemoteMessage.messageId
|
|
20
|
+
respondingTo: str,
|
|
21
|
+
payload: Result(Vector(RegisteredRingVrfKey), ListRingVrfKeysErr),
|
|
22
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContextualAlias, ProductProofContext, RingLocation, RingVrfProof, VrfSignature } from '@novasamatech/host-api';
|
|
1
|
+
import { ContextualAlias, DerivationIndex, ProductProofContext, RegisteredRingVrfKey, RingLocation, RingVrfKeyDisclosure, RingVrfKeyHandle, RingVrfProof, VrfSignature } from '@novasamatech/host-api';
|
|
2
2
|
import type { Encryption, StatementProver, StatementStoreAdapter } from '@novasamatech/statement-store';
|
|
3
3
|
import type { StorageAdapter } from '@novasamatech/storage-adapter';
|
|
4
4
|
import { ResultAsync } from 'neverthrow';
|
|
@@ -24,8 +24,27 @@ export type UserSession = StoredUserSession & {
|
|
|
24
24
|
signRawLegacy(payload: SignRawLegacyRequest): ResultAsync<Uint8Array, Error>;
|
|
25
25
|
createTransaction(payload: CreateTransactionRequest): ResultAsync<Uint8Array, Error>;
|
|
26
26
|
createTransactionLegacy(payload: CreateTransactionLegacyRequest): ResultAsync<Uint8Array, Error>;
|
|
27
|
-
getRingVrfAlias(callingProductId: string, context: CodecType<typeof ProductProofContext>, ring: CodecType<typeof RingLocation>): ResultAsync<CodecType<typeof ContextualAlias>, Error>;
|
|
28
|
-
createRingVrfProof(callingProductId: string, context: CodecType<typeof ProductProofContext>, ring: CodecType<typeof RingLocation>, message: Uint8Array): ResultAsync<CodecType<typeof RingVrfProof>, Error>;
|
|
27
|
+
getRingVrfAlias(callingProductId: string, keyHandle: CodecType<typeof RingVrfKeyHandle>, context: CodecType<typeof ProductProofContext>, ring: CodecType<typeof RingLocation>): ResultAsync<CodecType<typeof ContextualAlias>, Error>;
|
|
28
|
+
createRingVrfProof(callingProductId: string, keyHandle: CodecType<typeof RingVrfKeyHandle>, context: CodecType<typeof ProductProofContext>, ring: CodecType<typeof RingLocation>, message: Uint8Array): ResultAsync<CodecType<typeof RingVrfProof>, Error>;
|
|
29
|
+
/**
|
|
30
|
+
* Signs `message` with the ring VRF member key itself (RFC-0024).
|
|
31
|
+
*
|
|
32
|
+
* Unlike {@link createRingVrfProof} this is not anonymous: the result is
|
|
33
|
+
* verified against the member public key and is linkable to every other use
|
|
34
|
+
* of that key.
|
|
35
|
+
*/
|
|
36
|
+
ringVrfSign(callingProductId: string, keyHandle: CodecType<typeof RingVrfKeyHandle>, message: Uint8Array): ResultAsync<Uint8Array, Error>;
|
|
37
|
+
/**
|
|
38
|
+
* Registers a ring VRF key owned by `callingProductId` against `ring`,
|
|
39
|
+
* returning the member public key (RFC-0024).
|
|
40
|
+
*
|
|
41
|
+
* The Account Holder is the authoritative registry, so registration always
|
|
42
|
+
* reaches it. Idempotent — re-registering an index for an additional ring
|
|
43
|
+
* extends the existing entry.
|
|
44
|
+
*/
|
|
45
|
+
registerRingVrfKey(callingProductId: string, index: CodecType<typeof DerivationIndex>, ring: CodecType<typeof RingLocation>): ResultAsync<Uint8Array, Error>;
|
|
46
|
+
/** Lists the ring VRF registry entries owned by `owner` (RFC-0024). */
|
|
47
|
+
listRingVrfKeys(callingProductId: string, owner: string, disclosure: CodecType<typeof RingVrfKeyDisclosure>): ResultAsync<CodecType<typeof RegisteredRingVrfKey>[], Error>;
|
|
29
48
|
/**
|
|
30
49
|
* Fetches the sr25519 public key of `//product//{productId}` (RFC-0022).
|
|
31
50
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContextualAlias, ProductProofContext, RingLocation, RingVrfProof, VrfSignature } from '@novasamatech/host-api';
|
|
1
|
+
import { ContextualAlias, DerivationIndex, ProductProofContext, RegisteredRingVrfKey, RingLocation, RingVrfKeyDisclosure, RingVrfKeyHandle, RingVrfProof, VrfSignature, } from '@novasamatech/host-api';
|
|
2
2
|
import { enumValue } from '@novasamatech/scale';
|
|
3
3
|
import { createSession } from '@novasamatech/statement-store';
|
|
4
4
|
import { fieldListView } from '@novasamatech/storage-adapter';
|
|
@@ -244,11 +244,12 @@ export function createUserSession({ userSession, statementStore, encryption, sto
|
|
|
244
244
|
return withHostActionTrace(withQueueTimeout(inner, 'createTransactionLegacy'), messageId, userSession.id);
|
|
245
245
|
});
|
|
246
246
|
},
|
|
247
|
-
getRingVrfAlias(callingProductId, context, ring) {
|
|
247
|
+
getRingVrfAlias(callingProductId, keyHandle, context, ring) {
|
|
248
248
|
return enqueue(() => {
|
|
249
249
|
const messageId = nanoid();
|
|
250
250
|
const data = enumValue('v1', enumValue('RingVrfAliasRequest', {
|
|
251
251
|
callingProductId,
|
|
252
|
+
keyHandle,
|
|
252
253
|
context,
|
|
253
254
|
ring,
|
|
254
255
|
}));
|
|
@@ -265,11 +266,12 @@ export function createUserSession({ userSession, statementStore, encryption, sto
|
|
|
265
266
|
return withHostActionTrace(awaitReplyOrAckFailure(request, reply).andThen(result => result.success ? ok(result.value) : err(result.value)), messageId, userSession.id);
|
|
266
267
|
});
|
|
267
268
|
},
|
|
268
|
-
createRingVrfProof(callingProductId, context, ring, message) {
|
|
269
|
+
createRingVrfProof(callingProductId, keyHandle, context, ring, message) {
|
|
269
270
|
return enqueue(() => {
|
|
270
271
|
const messageId = nanoid();
|
|
271
272
|
const data = enumValue('v1', enumValue('RingVrfProofRequest', {
|
|
272
273
|
callingProductId,
|
|
274
|
+
keyHandle,
|
|
273
275
|
context,
|
|
274
276
|
ring,
|
|
275
277
|
message,
|
|
@@ -287,6 +289,60 @@ export function createUserSession({ userSession, statementStore, encryption, sto
|
|
|
287
289
|
return withHostActionTrace(awaitReplyOrAckFailure(request, reply).andThen(result => result.success ? ok(result.value) : err(result.value)), messageId, userSession.id);
|
|
288
290
|
});
|
|
289
291
|
},
|
|
292
|
+
ringVrfSign(callingProductId, keyHandle, message) {
|
|
293
|
+
return enqueue(() => {
|
|
294
|
+
const messageId = nanoid();
|
|
295
|
+
const data = enumValue('v1', enumValue('RingVrfSignRequest', { callingProductId, keyHandle, message }));
|
|
296
|
+
emitHostAction(messageId, actionKindFromMessageData(data), userSession.id);
|
|
297
|
+
const responseFilter = (incoming) => {
|
|
298
|
+
if (incoming.data.tag === 'v1' &&
|
|
299
|
+
incoming.data.value.tag === 'RingVrfSignResponse' &&
|
|
300
|
+
incoming.data.value.value.respondingTo === messageId) {
|
|
301
|
+
return incoming.data.value.value.payload;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const request = session.request(RemoteMessageCodec, { messageId, data });
|
|
305
|
+
const reply = session.waitForRequestMessage(RemoteMessageCodec, responseFilter);
|
|
306
|
+
const inner = awaitReplyOrAckFailure(request, reply).andThen(result => result.success ? ok(result.value) : err(result.value));
|
|
307
|
+
return withHostActionTrace(withQueueTimeout(inner, 'ringVrfSign'), messageId, userSession.id);
|
|
308
|
+
});
|
|
309
|
+
},
|
|
310
|
+
registerRingVrfKey(callingProductId, index, ring) {
|
|
311
|
+
return enqueue(() => {
|
|
312
|
+
const messageId = nanoid();
|
|
313
|
+
const data = enumValue('v1', enumValue('RegisterRingVrfKeyRequest', { callingProductId, index, ring }));
|
|
314
|
+
emitHostAction(messageId, actionKindFromMessageData(data), userSession.id);
|
|
315
|
+
const responseFilter = (incoming) => {
|
|
316
|
+
if (incoming.data.tag === 'v1' &&
|
|
317
|
+
incoming.data.value.tag === 'RegisterRingVrfKeyResponse' &&
|
|
318
|
+
incoming.data.value.value.respondingTo === messageId) {
|
|
319
|
+
return incoming.data.value.value.payload;
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const request = session.request(RemoteMessageCodec, { messageId, data });
|
|
323
|
+
const reply = session.waitForRequestMessage(RemoteMessageCodec, responseFilter);
|
|
324
|
+
const inner = awaitReplyOrAckFailure(request, reply).andThen(result => result.success ? ok(result.value) : err(result.value));
|
|
325
|
+
return withHostActionTrace(withQueueTimeout(inner, 'registerRingVrfKey'), messageId, userSession.id);
|
|
326
|
+
});
|
|
327
|
+
},
|
|
328
|
+
listRingVrfKeys(callingProductId, owner, disclosure) {
|
|
329
|
+
return enqueue(() => {
|
|
330
|
+
const messageId = nanoid();
|
|
331
|
+
const data = enumValue('v1', enumValue('ListRingVrfKeysRequest', { callingProductId, owner, disclosure }));
|
|
332
|
+
emitHostAction(messageId, actionKindFromMessageData(data), userSession.id);
|
|
333
|
+
const responseFilter = (incoming) => {
|
|
334
|
+
if (incoming.data.tag === 'v1' &&
|
|
335
|
+
incoming.data.value.tag === 'ListRingVrfKeysResponse' &&
|
|
336
|
+
incoming.data.value.value.respondingTo === messageId) {
|
|
337
|
+
return incoming.data.value.value.payload;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
const request = session.request(RemoteMessageCodec, { messageId, data });
|
|
341
|
+
const reply = session.waitForRequestMessage(RemoteMessageCodec, responseFilter);
|
|
342
|
+
const inner = awaitReplyOrAckFailure(request, reply).andThen(result => result.success ? ok(result.value) : err(result.value));
|
|
343
|
+
return withHostActionTrace(withQueueTimeout(inner, 'listRingVrfKeys'), messageId, userSession.id);
|
|
344
|
+
});
|
|
345
|
+
},
|
|
290
346
|
getProductSubtree(productId) {
|
|
291
347
|
return enqueue(() => {
|
|
292
348
|
const messageId = nanoid();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/host-papp",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.3",
|
|
5
5
|
"description": "Polkadot app integration",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"keywords": [
|
|
12
12
|
"polkadot"
|
|
13
13
|
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"papi:fix": "node ../../scripts/fix-papi-descriptors.mjs .papi/descriptors/dist",
|
|
16
|
+
"papi:update": "papi update && npm run papi:fix"
|
|
17
|
+
},
|
|
14
18
|
"main": "dist/index.js",
|
|
15
19
|
"exports": {
|
|
16
20
|
"./package.json": "./package.json",
|
|
@@ -34,10 +38,10 @@
|
|
|
34
38
|
"@noble/ciphers": "2.2.0",
|
|
35
39
|
"@noble/curves": "2.2.0",
|
|
36
40
|
"@noble/hashes": "2.2.0",
|
|
37
|
-
"@novasamatech/host-api": "0.9.
|
|
38
|
-
"@novasamatech/scale": "0.9.
|
|
39
|
-
"@novasamatech/statement-store": "0.9.
|
|
40
|
-
"@novasamatech/storage-adapter": "0.9.
|
|
41
|
+
"@novasamatech/host-api": "0.9.3",
|
|
42
|
+
"@novasamatech/scale": "0.9.3",
|
|
43
|
+
"@novasamatech/statement-store": "0.9.3",
|
|
44
|
+
"@novasamatech/storage-adapter": "0.9.3",
|
|
41
45
|
"@polkadot-api/utils": "^0.4.0",
|
|
42
46
|
"@polkadot-labs/hdkd-helpers": "^0.0.31",
|
|
43
47
|
"nanoevents": "10.0.0",
|