@openzeppelin/miden-multisig-client 0.17.0 → 0.18.0-rc.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.
Files changed (151) hide show
  1. package/README.md +171 -46
  2. package/dist/account/builder.d.ts +4 -4
  3. package/dist/account/builder.d.ts.map +1 -1
  4. package/dist/account/builder.js +17 -7
  5. package/dist/account/builder.js.map +1 -1
  6. package/dist/account/layout.d.ts +5 -5
  7. package/dist/account/layout.d.ts.map +1 -1
  8. package/dist/account/layout.js +5 -5
  9. package/dist/account/layout.js.map +1 -1
  10. package/dist/client.d.ts +18 -1
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +79 -6
  13. package/dist/client.js.map +1 -1
  14. package/dist/index.d.ts +6 -6
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +5 -5
  17. package/dist/index.js.map +1 -1
  18. package/dist/multisig/authArgErrors.d.ts +28 -31
  19. package/dist/multisig/authArgErrors.d.ts.map +1 -1
  20. package/dist/multisig/authArgErrors.js +42 -46
  21. package/dist/multisig/authArgErrors.js.map +1 -1
  22. package/dist/multisig/consumeNotesErrors.d.ts +13 -1
  23. package/dist/multisig/consumeNotesErrors.d.ts.map +1 -1
  24. package/dist/multisig/consumeNotesErrors.js +17 -0
  25. package/dist/multisig/consumeNotesErrors.js.map +1 -1
  26. package/dist/multisig/signing.d.ts +1 -1
  27. package/dist/multisig/signing.d.ts.map +1 -1
  28. package/dist/multisig/signing.js +8 -3
  29. package/dist/multisig/signing.js.map +1 -1
  30. package/dist/multisig.d.ts +145 -18
  31. package/dist/multisig.d.ts.map +1 -1
  32. package/dist/multisig.js +493 -162
  33. package/dist/multisig.js.map +1 -1
  34. package/dist/procedures.d.ts +7 -7
  35. package/dist/procedures.js +7 -7
  36. package/dist/proposal/factory.d.ts.map +1 -1
  37. package/dist/proposal/factory.js +7 -0
  38. package/dist/proposal/factory.js.map +1 -1
  39. package/dist/prover/workflow.d.ts +7 -3
  40. package/dist/prover/workflow.d.ts.map +1 -1
  41. package/dist/prover/workflow.js +7 -5
  42. package/dist/prover/workflow.js.map +1 -1
  43. package/dist/raw-client.d.ts +1 -0
  44. package/dist/raw-client.d.ts.map +1 -1
  45. package/dist/raw-client.js +10 -2
  46. package/dist/raw-client.js.map +1 -1
  47. package/dist/recovery/publicNoteBackfill.js +1 -1
  48. package/dist/recovery/publicNoteBackfill.js.map +1 -1
  49. package/dist/retry/classify.d.ts +3 -0
  50. package/dist/retry/classify.d.ts.map +1 -1
  51. package/dist/retry/classify.js +2 -2
  52. package/dist/retry/classify.js.map +1 -1
  53. package/dist/signer.d.ts +1 -0
  54. package/dist/signer.d.ts.map +1 -1
  55. package/dist/signer.js +1 -0
  56. package/dist/signer.js.map +1 -1
  57. package/dist/signers/index.d.ts +1 -0
  58. package/dist/signers/index.d.ts.map +1 -1
  59. package/dist/signers/index.js +1 -0
  60. package/dist/signers/index.js.map +1 -1
  61. package/dist/signers/ledger.d.ts +25 -0
  62. package/dist/signers/ledger.d.ts.map +1 -0
  63. package/dist/signers/ledger.js +96 -0
  64. package/dist/signers/ledger.js.map +1 -0
  65. package/dist/state/adopt.d.ts +45 -0
  66. package/dist/state/adopt.d.ts.map +1 -0
  67. package/dist/state/adopt.js +101 -0
  68. package/dist/state/adopt.js.map +1 -0
  69. package/dist/transaction/authArgs.d.ts +57 -0
  70. package/dist/transaction/authArgs.d.ts.map +1 -0
  71. package/dist/transaction/authArgs.js +108 -0
  72. package/dist/transaction/authArgs.js.map +1 -0
  73. package/dist/transaction/consumeNotes.d.ts +9 -5
  74. package/dist/transaction/consumeNotes.d.ts.map +1 -1
  75. package/dist/transaction/consumeNotes.js +8 -23
  76. package/dist/transaction/consumeNotes.js.map +1 -1
  77. package/dist/transaction/noteAuthentication.d.ts +39 -0
  78. package/dist/transaction/noteAuthentication.d.ts.map +1 -0
  79. package/dist/transaction/noteAuthentication.js +94 -0
  80. package/dist/transaction/noteAuthentication.js.map +1 -0
  81. package/dist/transaction/options.d.ts +25 -0
  82. package/dist/transaction/options.d.ts.map +1 -1
  83. package/dist/transaction/p2id.d.ts +3 -2
  84. package/dist/transaction/p2id.d.ts.map +1 -1
  85. package/dist/transaction/p2id.js +36 -27
  86. package/dist/transaction/p2id.js.map +1 -1
  87. package/dist/transaction/summary.d.ts +126 -22
  88. package/dist/transaction/summary.d.ts.map +1 -1
  89. package/dist/transaction/summary.js +164 -22
  90. package/dist/transaction/summary.js.map +1 -1
  91. package/dist/transaction/updateGuardian.d.ts +3 -3
  92. package/dist/transaction/updateGuardian.d.ts.map +1 -1
  93. package/dist/transaction/updateGuardian.js +5 -16
  94. package/dist/transaction/updateGuardian.js.map +1 -1
  95. package/dist/transaction/updateProcedureThreshold.d.ts +3 -3
  96. package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -1
  97. package/dist/transaction/updateProcedureThreshold.js +6 -16
  98. package/dist/transaction/updateProcedureThreshold.js.map +1 -1
  99. package/dist/transaction/updateSigners.d.ts +3 -3
  100. package/dist/transaction/updateSigners.d.ts.map +1 -1
  101. package/dist/transaction/updateSigners.js +9 -16
  102. package/dist/transaction/updateSigners.js.map +1 -1
  103. package/dist/transaction.d.ts +3 -2
  104. package/dist/transaction.d.ts.map +1 -1
  105. package/dist/transaction.js +3 -2
  106. package/dist/transaction.js.map +1 -1
  107. package/dist/types/proposal.d.ts +37 -5
  108. package/dist/types/proposal.d.ts.map +1 -1
  109. package/dist/types/proposal.js +8 -0
  110. package/dist/types/proposal.js.map +1 -1
  111. package/dist/utils/eip712.d.ts +80 -0
  112. package/dist/utils/eip712.d.ts.map +1 -0
  113. package/dist/utils/eip712.js +49 -0
  114. package/dist/utils/eip712.js.map +1 -0
  115. package/dist/utils/signature.d.ts +4 -0
  116. package/dist/utils/signature.d.ts.map +1 -1
  117. package/dist/utils/signature.js +49 -1
  118. package/dist/utils/signature.js.map +1 -1
  119. package/package.json +11 -6
  120. package/src/account/builder.ts +18 -7
  121. package/src/account/layout.ts +5 -5
  122. package/src/client.ts +94 -6
  123. package/src/index.ts +24 -3
  124. package/src/multisig/authArgErrors.ts +47 -53
  125. package/src/multisig/consumeNotesErrors.ts +20 -1
  126. package/src/multisig/signing.ts +8 -2
  127. package/src/multisig.ts +614 -205
  128. package/src/procedures.ts +7 -7
  129. package/src/proposal/factory.ts +7 -0
  130. package/src/prover/workflow.ts +7 -10
  131. package/src/raw-client.ts +11 -7
  132. package/src/recovery/publicNoteBackfill.ts +1 -1
  133. package/src/retry/classify.ts +3 -3
  134. package/src/signer.ts +1 -0
  135. package/src/signers/index.ts +1 -0
  136. package/src/signers/ledger.ts +122 -0
  137. package/src/state/adopt.ts +132 -0
  138. package/src/transaction/authArgs.ts +142 -0
  139. package/src/transaction/consumeNotes.ts +23 -30
  140. package/src/transaction/noteAuthentication.ts +136 -0
  141. package/src/transaction/options.ts +27 -0
  142. package/src/transaction/p2id.ts +45 -34
  143. package/src/transaction/summary.ts +239 -30
  144. package/src/transaction/updateGuardian.ts +8 -22
  145. package/src/transaction/updateProcedureThreshold.ts +8 -20
  146. package/src/transaction/updateSigners.ts +11 -22
  147. package/src/transaction.ts +18 -1
  148. package/src/types/proposal.ts +36 -5
  149. package/src/utils/eip712.ts +57 -0
  150. package/src/utils/signature.ts +57 -0
  151. package/src/prover/test-node.d.ts +0 -6
@@ -0,0 +1,57 @@
1
+ import { keccak_256 } from '@noble/hashes/sha3.js';
2
+ import { bytesToHex, hexToBytes } from './encoding.js';
3
+
4
+ type TypedField = { name: string; type: string };
5
+ const EIP191_PREFIX = 0x19;
6
+ const EIP712_VERSION = 0x01;
7
+ const DOMAIN_VERSION = '1';
8
+
9
+ const domainFields: TypedField[] = [
10
+ { name: 'name', type: 'string' },
11
+ { name: 'version', type: 'string' },
12
+ ];
13
+
14
+ function typedData(name: string, primaryType: string, fieldName: string, value: string) {
15
+ return {
16
+ types: {
17
+ EIP712Domain: domainFields,
18
+ [primaryType]: [{ name: fieldName, type: 'bytes32' }],
19
+ },
20
+ primaryType,
21
+ domain: { name, version: DOMAIN_VERSION },
22
+ message: { [fieldName]: value },
23
+ };
24
+ }
25
+
26
+ export function guardianRequestTypedData(requestHash: Uint8Array) {
27
+ return typedData('Guardian Request', 'GuardianRequest', 'requestHash', bytesToHex(requestHash));
28
+ }
29
+
30
+ export function guardianLookupTypedData(lookupHash: Uint8Array) {
31
+ return typedData('Guardian Lookup', 'GuardianLookup', 'lookupHash', bytesToHex(lookupHash));
32
+ }
33
+
34
+ export function midenTransactionTypedData(txSummaryHash: Uint8Array) {
35
+ return typedData('Miden Transaction', 'MidenTransaction', 'txSummaryHash', bytesToHex(txSummaryHash));
36
+ }
37
+
38
+ export function guardianKeyDiscoveryTypedData(challenge: Uint8Array) {
39
+ return typedData('Guardian Key Discovery', 'GuardianKeyDiscovery', 'challenge', bytesToHex(challenge));
40
+ }
41
+
42
+ export function typedDataDigest(data: ReturnType<typeof typedData>): Uint8Array {
43
+ const domainType = new TextEncoder().encode('EIP712Domain(string name,string version)');
44
+ const primaryType = new TextEncoder().encode(`${data.primaryType}(bytes32 ${Object.keys(data.message)[0]})`);
45
+ const domain = new Uint8Array(96);
46
+ domain.set(keccak_256(domainType));
47
+ domain.set(keccak_256(new TextEncoder().encode(data.domain.name)), 32);
48
+ domain.set(keccak_256(new TextEncoder().encode(data.domain.version)), 64);
49
+ const struct = new Uint8Array(64);
50
+ struct.set(keccak_256(primaryType));
51
+ struct.set(hexToBytes(Object.values(data.message)[0]), 32);
52
+ const preimage = new Uint8Array(66);
53
+ preimage.set([EIP191_PREFIX, EIP712_VERSION]);
54
+ preimage.set(keccak_256(domain), 2);
55
+ preimage.set(keccak_256(struct), 34);
56
+ return keccak_256(preimage);
57
+ }
@@ -1,7 +1,10 @@
1
1
  import { AdviceMap, Felt, FeltArray, Poseidon2, Signature, Word } from '@miden-sdk/miden-sdk';
2
2
  import * as midenSdk from '@miden-sdk/miden-sdk';
3
3
  import { EcdsaFormat } from './ecdsa.js';
4
+ import { midenTransactionTypedData, typedDataDigest } from './eip712.js';
4
5
  import { hexToBytes, normalizeHexWord } from './encoding.js';
6
+ import { wordToBytes } from './word.js';
7
+ import { secp256k1 } from '@noble/curves/secp256k1';
5
8
  import type { ProposalSignatureEntry, SignatureScheme } from '../types.js';
6
9
 
7
10
  export const ECDSA_AUTH_SCHEME_ID = 1;
@@ -43,6 +46,60 @@ export function buildSignatureAdviceEntry(
43
46
  return { key, values: signature.toPreparedSignature(message) };
44
47
  }
45
48
 
49
+ // Little-endian ASCII "EIP712", matching the protocol advice-key domain.
50
+ const EIP712_SIGNATURE_KEY_DOMAIN = 0x323137504945n;
51
+
52
+ function littleEndianU32Limbs(bytes: Uint8Array): Felt[] {
53
+ const limbs: Felt[] = [];
54
+ for (let i = 28; i >= 0; i -= 4) {
55
+ const limb = (bytes[i] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] << 8) | bytes[i + 3];
56
+ limbs.push(new Felt(BigInt(limb >>> 0)));
57
+ }
58
+ return limbs;
59
+ }
60
+
61
+ export function buildEip712SignatureAdviceEntry(
62
+ pubkeyCommitment: Word,
63
+ txSummaryCommitment: Word,
64
+ signatureHex: string,
65
+ publicKeyHex: string,
66
+ ): { key: Word; values: Felt[] } {
67
+ const expectedCommitment = tryComputeEcdsaCommitmentHex(publicKeyHex);
68
+ if (expectedCommitment !== normalizeHexWord(pubkeyCommitment.toHex())) {
69
+ throw new Error('EIP-712 public key commitment mismatch');
70
+ }
71
+ const publicKey = secp256k1.ProjectivePoint.fromHex(publicKeyHex.replace(/^0x/i, ''));
72
+ const uncompressed = publicKey.toRawBytes(false);
73
+ const normalizedSignature = EcdsaFormat.normalizeRecoveryByte(signatureHex);
74
+ if (!/^0x[0-9a-fA-F]{130}$/.test(normalizedSignature)) {
75
+ throw new Error('EIP-712 signature must be 65 hex-encoded bytes');
76
+ }
77
+ const signature = hexToBytes(normalizedSignature);
78
+ if (signature.length !== 65 || (signature[64] !== 0 && signature[64] !== 1)) {
79
+ throw new Error('EIP-712 signature must contain a valid recovery ID');
80
+ }
81
+ const typedData = midenTransactionTypedData(wordToBytes(txSummaryCommitment));
82
+ if (!secp256k1.verify(signature.slice(0, 64), typedDataDigest(typedData), publicKey.toRawBytes(true))) {
83
+ throw new Error('EIP-712 signature does not match the transaction summary');
84
+ }
85
+
86
+ const rawKey = Poseidon2.hashElements(new FeltArray([
87
+ ...pubkeyCommitment.toFelts(),
88
+ ...txSummaryCommitment.toFelts(),
89
+ ]));
90
+ const domain = new Word(new BigUint64Array([EIP712_SIGNATURE_KEY_DOMAIN, 0n, 0n, 0n]));
91
+ const key = Poseidon2.hashElements(new FeltArray([...rawKey.toFelts(), ...domain.toFelts()]));
92
+ return {
93
+ key,
94
+ values: [
95
+ ...littleEndianU32Limbs(uncompressed.slice(1, 33)),
96
+ ...littleEndianU32Limbs(uncompressed.slice(33, 65)),
97
+ ...littleEndianU32Limbs(signature.slice(0, 32)),
98
+ ...littleEndianU32Limbs(signature.slice(32, 64)),
99
+ ],
100
+ };
101
+ }
102
+
46
103
  /** Rejects unrecoverable ECDSA signatures before entering WASM. */
47
104
  export function assertEcdsaSignatureRecoverable(
48
105
  signatureHex: string,
@@ -1,6 +0,0 @@
1
- declare module 'node:fs' {
2
- export function readFileSync(
3
- path: URL,
4
- encoding: 'utf8',
5
- ): string;
6
- }