@novasamatech/statement-store 0.8.7-0 → 0.8.7-2
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/dist/adapter/inMemory.d.ts +32 -0
- package/dist/adapter/inMemory.js +56 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -1
- package/dist/session/priority.d.ts +1 -0
- package/dist/session/priority.js +22 -0
- package/dist/session/priority.spec.d.ts +1 -0
- package/dist/session/priority.spec.js +43 -0
- package/dist/session/session.d.ts +7 -1
- package/dist/session/session.js +384 -134
- package/dist/session/session.spec.js +943 -346
- package/dist/session/statementProver.d.ts +3 -0
- package/dist/session/statementProver.js +20 -4
- package/dist/session/statementProver.spec.d.ts +1 -0
- package/dist/session/statementProver.spec.js +71 -0
- package/dist/session/types.d.ts +12 -0
- package/package.json +3 -3
|
@@ -4,4 +4,7 @@ export type StatementProver = {
|
|
|
4
4
|
generateMessageProof(statement: Statement): ResultAsync<SignedStatement, Error>;
|
|
5
5
|
verifyMessageProof(statement: Statement): ResultAsync<boolean, Error>;
|
|
6
6
|
};
|
|
7
|
+
/** Prover for scure-HDKD / device statement account secrets. */
|
|
7
8
|
export declare function createSr25519Prover(secret: Uint8Array): StatementProver;
|
|
9
|
+
/** Prover for a mobile slot-account secret (`privateKey || nonce`). Call `ensureSubstrateSlotSr25519Ready()` first. */
|
|
10
|
+
export declare function createSlotAccountProver(secret: Uint8Array): StatementProver;
|
|
@@ -2,11 +2,11 @@ import { getStatementSigner, statementCodec } from '@novasamatech/sdk-statement'
|
|
|
2
2
|
import { compact } from '@polkadot-api/substrate-bindings';
|
|
3
3
|
import { errAsync, fromPromise, fromThrowable, okAsync } from 'neverthrow';
|
|
4
4
|
import { fromHex } from 'polkadot-api/utils';
|
|
5
|
-
import { deriveSr25519PublicKey, signWithSr25519Secret, verifySr25519Signature } from '../crypto.js';
|
|
5
|
+
import { deriveSlotAccountPublicKey, deriveSr25519PublicKey, signSlotAccountSecret, signWithSr25519Secret, verifySlotAccountSignature, verifySr25519Signature, } from '../crypto.js';
|
|
6
6
|
import { toError } from '../helpers.js';
|
|
7
|
-
|
|
8
|
-
const signer = getStatementSigner(
|
|
9
|
-
const verify = fromThrowable(
|
|
7
|
+
function createSr25519SchemeProver(secret, scheme) {
|
|
8
|
+
const signer = getStatementSigner(scheme.derivePublicKey(secret), 'sr25519', data => scheme.sign(secret, data));
|
|
9
|
+
const verify = fromThrowable(scheme.verify, toError);
|
|
10
10
|
return {
|
|
11
11
|
generateMessageProof(statement) {
|
|
12
12
|
return fromPromise(signer.sign(statement), toError);
|
|
@@ -27,3 +27,19 @@ export function createSr25519Prover(secret) {
|
|
|
27
27
|
},
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
+
/** Prover for scure-HDKD / device statement account secrets. */
|
|
31
|
+
export function createSr25519Prover(secret) {
|
|
32
|
+
return createSr25519SchemeProver(secret, {
|
|
33
|
+
derivePublicKey: deriveSr25519PublicKey,
|
|
34
|
+
sign: signWithSr25519Secret,
|
|
35
|
+
verify: verifySr25519Signature,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Prover for a mobile slot-account secret (`privateKey || nonce`). Call `ensureSubstrateSlotSr25519Ready()` first. */
|
|
39
|
+
export function createSlotAccountProver(secret) {
|
|
40
|
+
return createSr25519SchemeProver(secret, {
|
|
41
|
+
derivePublicKey: deriveSlotAccountPublicKey,
|
|
42
|
+
sign: signSlotAccountSecret,
|
|
43
|
+
verify: verifySlotAccountSignature,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createExpiryFromDuration } from '@novasamatech/sdk-statement';
|
|
2
|
+
import { ensureSubstrateSlotSr25519Ready, substrateSlotSecretFromSeedBytes, } from '@novasamatech/substrate-slot-sr25519-wasm';
|
|
3
|
+
import { mnemonicToEntropy, mnemonicToMiniSecret } from '@polkadot-labs/hdkd-helpers';
|
|
4
|
+
import { beforeAll, describe, expect, it } from 'vitest';
|
|
5
|
+
import { createSr25519Secret, deriveSlotAccountPublicKey, deriveSr25519PublicKey } from '../crypto.js';
|
|
6
|
+
import { createSlotAccountProver, createSr25519Prover } from './statementProver.js';
|
|
7
|
+
const DEV_MNEMONIC = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk';
|
|
8
|
+
const toHex = (bytes) => `0x${[...bytes].map(b => b.toString(16).padStart(2, '0')).join('')}`;
|
|
9
|
+
function makeStatement(data) {
|
|
10
|
+
return {
|
|
11
|
+
expiry: createExpiryFromDuration(7 * 24 * 60 * 60),
|
|
12
|
+
data,
|
|
13
|
+
topics: [],
|
|
14
|
+
channel: `0x${'00'.repeat(32)}`,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function proofSigner(signed) {
|
|
18
|
+
if (signed.proof.type !== 'sr25519') {
|
|
19
|
+
throw new Error(`unexpected proof type ${signed.proof.type}`);
|
|
20
|
+
}
|
|
21
|
+
return signed.proof.value.signer;
|
|
22
|
+
}
|
|
23
|
+
describe('statementProver', () => {
|
|
24
|
+
beforeAll(async () => {
|
|
25
|
+
// Only the slot scheme needs explicit init; the scure path initializes lazily.
|
|
26
|
+
await ensureSubstrateSlotSr25519Ready();
|
|
27
|
+
});
|
|
28
|
+
describe('createSr25519Prover (scure-HDKD secrets)', () => {
|
|
29
|
+
it('signs a statement under the scure-derived public key and verifies it', async () => {
|
|
30
|
+
const secret = createSr25519Secret(mnemonicToEntropy(DEV_MNEMONIC));
|
|
31
|
+
const prover = createSr25519Prover(secret);
|
|
32
|
+
const signed = (await prover.generateMessageProof(makeStatement(new Uint8Array([1, 2, 3]))))._unsafeUnwrap();
|
|
33
|
+
expect(proofSigner(signed)).toBe(toHex(deriveSr25519PublicKey(secret)));
|
|
34
|
+
const verified = await prover.verifyMessageProof(signed);
|
|
35
|
+
expect(verified._unsafeUnwrap()).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('createSlotAccountProver (mobile slot secrets)', () => {
|
|
39
|
+
// Derived inside each test: the wasm is only ready after beforeAll runs.
|
|
40
|
+
const makeSlotSecret = () => substrateSlotSecretFromSeedBytes(mnemonicToMiniSecret(DEV_MNEMONIC));
|
|
41
|
+
it('signs a statement under the slot-derived public key and verifies it', async () => {
|
|
42
|
+
const slotSecret = makeSlotSecret();
|
|
43
|
+
const prover = createSlotAccountProver(slotSecret);
|
|
44
|
+
const signed = (await prover.generateMessageProof(makeStatement(new Uint8Array([4, 5, 6]))))._unsafeUnwrap();
|
|
45
|
+
expect(proofSigner(signed)).toBe(toHex(deriveSlotAccountPublicKey(slotSecret)));
|
|
46
|
+
const verified = await prover.verifyMessageProof(signed);
|
|
47
|
+
expect(verified._unsafeUnwrap()).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
it('signs under a different public key than the scure prover would for the same secret', () => {
|
|
50
|
+
// Regression guard: a slot secret pushed through the scure scheme derives the WRONG
|
|
51
|
+
// signer, which is the bug createSlotAccountProver fixes for getStatementStoreProver.
|
|
52
|
+
const slotSecret = makeSlotSecret();
|
|
53
|
+
expect(toHex(deriveSlotAccountPublicKey(slotSecret))).not.toBe(toHex(deriveSr25519PublicKey(slotSecret)));
|
|
54
|
+
});
|
|
55
|
+
it('rejects a proof whose statement data was tampered with', async () => {
|
|
56
|
+
const slotSecret = makeSlotSecret();
|
|
57
|
+
const prover = createSlotAccountProver(slotSecret);
|
|
58
|
+
const signed = (await prover.generateMessageProof(makeStatement(new Uint8Array([7, 8, 9]))))._unsafeUnwrap();
|
|
59
|
+
const tampered = { ...signed, data: new Uint8Array([9, 9, 9]) };
|
|
60
|
+
const verified = await prover.verifyMessageProof(tampered);
|
|
61
|
+
expect(verified._unsafeUnwrap()).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('verifyMessageProof', () => {
|
|
65
|
+
it('errors when the statement carries no proof', async () => {
|
|
66
|
+
const prover = createSr25519Prover(createSr25519Secret(mnemonicToEntropy(DEV_MNEMONIC)));
|
|
67
|
+
const verified = await prover.verifyMessageProof(makeStatement(new Uint8Array([1])));
|
|
68
|
+
expect(verified.isErr()).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
package/dist/session/types.d.ts
CHANGED
|
@@ -31,6 +31,18 @@ export type Session = {
|
|
|
31
31
|
requestId: string;
|
|
32
32
|
}, Error>;
|
|
33
33
|
submitResponseMessage(requestId: string, responseCode: ResponseStatus): ResultAsync<void, Error>;
|
|
34
|
+
/**
|
|
35
|
+
* Subscribe to incoming peer requests and answer each one automatically.
|
|
36
|
+
* The handler returns the transport-level {@link ResponseStatus} (or a
|
|
37
|
+
* `ResultAsync` resolving to one) that the session submits as the response on
|
|
38
|
+
* the peer's behalf; a handler that errors is answered with `'unknown'`.
|
|
39
|
+
*
|
|
40
|
+
* This is the can't-forget counterpart to {@link submitResponseMessage}: the
|
|
41
|
+
* ACK is driven by the handler's return value, so a consumer cannot receive a
|
|
42
|
+
* request and silently fail to respond. Response-type statements are ignored
|
|
43
|
+
* (only requests are answered).
|
|
44
|
+
*/
|
|
45
|
+
respondToRequests<T>(codec: Codec<T>, handler: (request: RequestMessage<T>) => ResponseStatus | ResultAsync<ResponseStatus, Error>): VoidFunction;
|
|
34
46
|
/**
|
|
35
47
|
* Replace the in-flight outgoing request batch with an empty one on the same
|
|
36
48
|
* request channel at the session's current expiry (the statement store keeps
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/statement-store",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.7-
|
|
4
|
+
"version": "0.8.7-2",
|
|
5
5
|
"description": "Statement store integration",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"README.md"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@novasamatech/scale": "0.8.7-
|
|
28
|
+
"@novasamatech/scale": "0.8.7-2",
|
|
29
29
|
"@novasamatech/sdk-statement": "^0.6.0",
|
|
30
|
-
"@novasamatech/substrate-slot-sr25519-wasm": "0.8.7-
|
|
30
|
+
"@novasamatech/substrate-slot-sr25519-wasm": "0.8.7-2",
|
|
31
31
|
"@polkadot-api/substrate-bindings": "^0.20.3",
|
|
32
32
|
"@polkadot-api/substrate-client": "^0.7.0",
|
|
33
33
|
"@polkadot-labs/hdkd-helpers": "^0.0.30",
|