@openzeppelin/miden-multisig-client 0.13.1 → 0.13.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/README.md +98 -119
- package/dist/account/builder.d.ts +18 -0
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +59 -29
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +108 -32
- package/dist/account/builder.test.js.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/index.js +1 -1
- package/dist/account/index.js.map +1 -1
- package/dist/account/masm/account-components/auth.d.ts +5 -0
- package/dist/account/masm/account-components/auth.d.ts.map +1 -0
- package/dist/account/masm/account-components/auth.js +67 -0
- package/dist/account/masm/account-components/auth.js.map +1 -0
- package/dist/account/masm/auth.d.ts +5 -0
- package/dist/account/masm/auth.d.ts.map +1 -0
- package/dist/account/masm/auth.js +1395 -0
- package/dist/account/masm/auth.js.map +1 -0
- package/dist/account/masm/index.d.ts +3 -0
- package/dist/account/masm/index.d.ts.map +1 -0
- package/dist/account/masm/index.js +5 -0
- package/dist/account/masm/index.js.map +1 -0
- package/dist/account/masm.d.ts +1 -4
- package/dist/account/masm.d.ts.map +1 -1
- package/dist/account/masm.js +3 -1034
- package/dist/account/masm.js.map +1 -1
- package/dist/account/storage.d.ts +2 -2
- package/dist/account/storage.d.ts.map +1 -1
- package/dist/account/storage.js +18 -16
- package/dist/account/storage.js.map +1 -1
- package/dist/client.d.ts +67 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +73 -22
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +31 -32
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +54 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -9
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts +32 -6
- package/dist/inspector.d.ts.map +1 -1
- package/dist/inspector.js +58 -23
- package/dist/inspector.js.map +1 -1
- package/dist/inspector.test.js +18 -18
- package/dist/inspector.test.js.map +1 -1
- package/dist/multisig/proposal/execution.d.ts +4 -4
- package/dist/multisig/proposal/execution.d.ts.map +1 -1
- package/dist/multisig/proposal/execution.js +42 -31
- package/dist/multisig/proposal/execution.js.map +1 -1
- package/dist/multisig/proposal/parser.d.ts +3 -3
- package/dist/multisig/proposal/parser.d.ts.map +1 -1
- package/dist/multisig/proposal/parser.js +23 -23
- package/dist/multisig/proposal/parser.js.map +1 -1
- package/dist/multisig/signing.d.ts +3 -3
- package/dist/multisig/signing.d.ts.map +1 -1
- package/dist/multisig/signing.js +3 -3
- package/dist/multisig/signing.js.map +1 -1
- package/dist/multisig.d.ts +188 -48
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +650 -308
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +1680 -241
- package/dist/multisig.test.js.map +1 -1
- package/dist/procedures.d.ts +46 -24
- package/dist/procedures.d.ts.map +1 -1
- package/dist/procedures.js +46 -21
- package/dist/procedures.js.map +1 -1
- package/dist/proposal/factory.d.ts +18 -0
- package/dist/proposal/factory.d.ts.map +1 -0
- package/dist/proposal/factory.js +99 -0
- package/dist/proposal/factory.js.map +1 -0
- package/dist/proposal/metadata.d.ts +5 -12
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +118 -174
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/signatures.d.ts +10 -0
- package/dist/proposal/signatures.d.ts.map +1 -0
- package/dist/proposal/signatures.js +54 -0
- package/dist/proposal/signatures.js.map +1 -0
- package/dist/signer.d.ts +2 -0
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +2 -0
- package/dist/signer.js.map +1 -1
- package/dist/signers/ecdsa.d.ts +3 -0
- package/dist/signers/ecdsa.d.ts.map +1 -1
- package/dist/signers/ecdsa.js +8 -4
- package/dist/signers/ecdsa.js.map +1 -1
- package/dist/signers/ecdsa.test.d.ts +2 -0
- package/dist/signers/ecdsa.test.d.ts.map +1 -0
- package/dist/signers/ecdsa.test.js +65 -0
- package/dist/signers/ecdsa.test.js.map +1 -0
- package/dist/signers/falcon.d.ts +3 -0
- package/dist/signers/falcon.d.ts.map +1 -1
- package/dist/signers/falcon.js +8 -4
- package/dist/signers/falcon.js.map +1 -1
- package/dist/signers/falcon.test.js +12 -0
- package/dist/signers/falcon.test.js.map +1 -1
- package/dist/signers/miden-wallet.d.ts +3 -1
- package/dist/signers/miden-wallet.d.ts.map +1 -1
- package/dist/signers/miden-wallet.js +11 -2
- package/dist/signers/miden-wallet.js.map +1 -1
- package/dist/signers/miden-wallet.test.js +26 -0
- package/dist/signers/miden-wallet.test.js.map +1 -1
- package/dist/signers/para.d.ts +3 -3
- package/dist/signers/para.d.ts.map +1 -1
- package/dist/signers/para.js +15 -6
- package/dist/signers/para.js.map +1 -1
- package/dist/signers/para.test.js +39 -0
- package/dist/signers/para.test.js.map +1 -1
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +1 -0
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/index.d.ts +2 -1
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction/index.js +2 -1
- package/dist/transaction/index.js.map +1 -1
- package/dist/transaction/options.d.ts +1 -1
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +1 -0
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +9 -3
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/updateGuardian.d.ts +7 -0
- package/dist/transaction/updateGuardian.d.ts.map +1 -0
- package/dist/transaction/{updatePsm.js → updateGuardian.js} +15 -29
- package/dist/transaction/updateGuardian.js.map +1 -0
- package/dist/transaction/updateProcedureThreshold.d.ts +9 -0
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -0
- package/dist/transaction/updateProcedureThreshold.js +55 -0
- package/dist/transaction/updateProcedureThreshold.js.map +1 -0
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js +5 -23
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +2 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +2 -1
- package/dist/transaction.js.map +1 -1
- package/dist/types/proposal.d.ts +32 -15
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types.d.ts +24 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/digest.d.ts +5 -0
- package/dist/utils/digest.d.ts.map +1 -1
- package/dist/utils/digest.js +34 -1
- package/dist/utils/digest.js.map +1 -1
- package/dist/utils/digest.test.d.ts +2 -0
- package/dist/utils/digest.test.d.ts.map +1 -0
- package/dist/utils/digest.test.js +48 -0
- package/dist/utils/digest.test.js.map +1 -0
- package/dist/utils/signature.d.ts +3 -1
- package/dist/utils/signature.d.ts.map +1 -1
- package/dist/utils/signature.js +31 -6
- package/dist/utils/signature.js.map +1 -1
- package/dist/utils/word.test.js +1 -52
- package/dist/utils/word.test.js.map +1 -1
- package/masm/account_components/auth/multisig.masm +13 -0
- package/masm/account_components/auth/multisig_ecdsa.masm +13 -0
- package/masm/account_components/auth/multisig_guardian.masm +17 -0
- package/masm/account_components/auth/multisig_guardian_ecdsa.masm +17 -0
- package/masm/auth/guardian.masm +177 -0
- package/masm/auth/guardian_ecdsa.masm +178 -0
- package/masm/{multisig.masm → auth/multisig.masm} +149 -55
- package/masm/{multisig_ecdsa.masm → auth/multisig_ecdsa.masm} +148 -56
- package/package.json +11 -9
- package/src/account/builder.test.ts +165 -0
- package/src/account/builder.ts +71 -34
- package/src/account/index.ts +1 -1
- package/src/account/masm/account-components/auth.ts +70 -0
- package/src/account/masm/auth.ts +1398 -0
- package/src/account/masm/index.ts +5 -0
- package/src/account/masm.ts +3 -1040
- package/src/account/storage.ts +18 -16
- package/src/client.test.ts +31 -35
- package/src/client.ts +98 -26
- package/src/index.ts +84 -22
- package/src/inspector.test.ts +17 -17
- package/src/inspector.ts +63 -29
- package/src/multisig/proposal/execution.ts +66 -49
- package/src/multisig/proposal/parser.ts +26 -26
- package/src/multisig/signing.ts +4 -4
- package/src/multisig.test.ts +2097 -248
- package/src/multisig.ts +882 -388
- package/src/procedures.ts +50 -26
- package/src/proposal/factory.ts +171 -0
- package/src/proposal/metadata.ts +165 -0
- package/src/proposal/signatures.ts +68 -0
- package/src/signer.ts +2 -0
- package/src/signers/ecdsa.test.ts +80 -0
- package/src/signers/ecdsa.ts +15 -4
- package/src/signers/falcon.test.ts +19 -0
- package/src/signers/falcon.ts +16 -5
- package/src/signers/miden-wallet.test.ts +47 -0
- package/src/signers/miden-wallet.ts +18 -1
- package/src/signers/para.test.ts +57 -0
- package/src/signers/para.ts +26 -7
- package/src/transaction/consumeNotes.ts +1 -0
- package/src/transaction/index.ts +2 -2
- package/src/transaction/options.ts +1 -2
- package/src/transaction/p2id.test.ts +190 -0
- package/src/transaction/p2id.ts +11 -5
- package/src/transaction/rpoRandomCoin.test.ts +64 -0
- package/src/transaction/rpoRandomCoin.ts +24 -0
- package/src/transaction/{updatePsm.ts → updateGuardian.ts} +19 -32
- package/src/transaction/updateProcedureThreshold.ts +97 -0
- package/src/transaction/updateSigners.ts +12 -27
- package/src/transaction.ts +5 -3
- package/src/types/proposal.ts +43 -11
- package/src/types.ts +29 -11
- package/src/utils/digest.test.ts +55 -0
- package/src/utils/digest.ts +51 -1
- package/src/utils/signature.ts +47 -9
- package/src/utils/word.test.ts +1 -55
- package/dist/account.d.ts +0 -104
- package/dist/account.d.ts.map +0 -1
- package/dist/account.js +0 -136
- package/dist/account.js.map +0 -1
- package/dist/builder.d.ts +0 -54
- package/dist/builder.d.ts.map +0 -1
- package/dist/builder.js +0 -78
- package/dist/builder.js.map +0 -1
- package/dist/http.d.ts +0 -64
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -162
- package/dist/http.js.map +0 -1
- package/dist/keystore.d.ts +0 -65
- package/dist/keystore.d.ts.map +0 -1
- package/dist/keystore.js +0 -121
- package/dist/keystore.js.map +0 -1
- package/dist/miden.d.ts +0 -9
- package/dist/miden.d.ts.map +0 -1
- package/dist/miden.js +0 -26
- package/dist/miden.js.map +0 -1
- package/dist/multisig/metadata.d.ts +0 -18
- package/dist/multisig/metadata.d.ts.map +0 -1
- package/dist/multisig/metadata.js +0 -100
- package/dist/multisig/metadata.js.map +0 -1
- package/dist/multisig/metadata.test.d.ts +0 -2
- package/dist/multisig/metadata.test.d.ts.map +0 -1
- package/dist/multisig/metadata.test.js +0 -323
- package/dist/multisig/metadata.test.js.map +0 -1
- package/dist/proposal/exported.d.ts +0 -12
- package/dist/proposal/exported.d.ts.map +0 -1
- package/dist/proposal/exported.js +0 -88
- package/dist/proposal/exported.js.map +0 -1
- package/dist/signer.test.d.ts +0 -2
- package/dist/signer.test.d.ts.map +0 -1
- package/dist/signer.test.js +0 -123
- package/dist/signer.test.js.map +0 -1
- package/dist/transaction/p2id.interop.test.d.ts +0 -2
- package/dist/transaction/p2id.interop.test.d.ts.map +0 -1
- package/dist/transaction/p2id.interop.test.js +0 -36
- package/dist/transaction/p2id.interop.test.js.map +0 -1
- package/dist/transaction/updatePsm.d.ts +0 -7
- package/dist/transaction/updatePsm.d.ts.map +0 -1
- package/dist/transaction/updatePsm.js.map +0 -1
- package/dist/transport/http.d.ts +0 -64
- package/dist/transport/http.d.ts.map +0 -1
- package/dist/transport/http.js +0 -162
- package/dist/transport/http.js.map +0 -1
- package/dist/transport/index.d.ts +0 -5
- package/dist/transport/index.d.ts.map +0 -1
- package/dist/transport/index.js +0 -5
- package/dist/transport/index.js.map +0 -1
- package/dist/utils/state-validation.d.ts +0 -5
- package/dist/utils/state-validation.d.ts.map +0 -1
- package/dist/utils/state-validation.js +0 -30
- package/dist/utils/state-validation.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -6
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -52
- package/dist/utils/validation.js.map +0 -1
- package/masm/psm.masm +0 -178
- package/masm/psm_ecdsa.masm +0 -179
package/src/inspector.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Inspector - Inspects account storage to detect multisig configuration.
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
import { Account, Word } from '@miden-sdk/miden-sdk';
|
|
2
6
|
import { base64ToUint8Array } from './utils/encoding.js';
|
|
3
7
|
import { wordElementToBigInt, wordToHex } from './utils/word.js';
|
|
4
8
|
import { getProcedureRoot, getProcedureNames, type ProcedureName } from './procedures.js';
|
|
5
|
-
import type { SignatureScheme } from './types.js';
|
|
6
9
|
|
|
10
|
+
// Storage slot names matching the MASM definitions
|
|
7
11
|
const MULTISIG_SLOT_NAMES = {
|
|
8
12
|
THRESHOLD_CONFIG: 'openzeppelin::multisig::threshold_config',
|
|
9
13
|
SIGNER_PUBLIC_KEYS: 'openzeppelin::multisig::signer_public_keys',
|
|
@@ -11,9 +15,9 @@ const MULTISIG_SLOT_NAMES = {
|
|
|
11
15
|
PROCEDURE_THRESHOLDS: 'openzeppelin::multisig::procedure_thresholds',
|
|
12
16
|
} as const;
|
|
13
17
|
|
|
14
|
-
const
|
|
15
|
-
SELECTOR: 'openzeppelin::
|
|
16
|
-
PUBLIC_KEY: 'openzeppelin::
|
|
18
|
+
const GUARDIAN_SLOT_NAMES = {
|
|
19
|
+
SELECTOR: 'openzeppelin::guardian::selector',
|
|
20
|
+
PUBLIC_KEY: 'openzeppelin::guardian::public_key',
|
|
17
21
|
} as const;
|
|
18
22
|
|
|
19
23
|
export interface VaultBalance {
|
|
@@ -25,23 +29,48 @@ export interface DetectedMultisigConfig {
|
|
|
25
29
|
threshold: number;
|
|
26
30
|
numSigners: number;
|
|
27
31
|
signerCommitments: string[];
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
guardianEnabled: boolean;
|
|
33
|
+
guardianCommitment: string | null;
|
|
30
34
|
vaultBalances: VaultBalance[];
|
|
31
35
|
procedureThresholds: Map<ProcedureName, number>;
|
|
32
|
-
signatureScheme: SignatureScheme;
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Inspects an account to detect its multisig configuration.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // From base64-encoded state
|
|
44
|
+
* const config = AccountInspector.fromBase64(stateDataBase64);
|
|
45
|
+
* console.log(`${config.threshold}-of-${config.numSigners} multisig`);
|
|
46
|
+
*
|
|
47
|
+
* // From Miden SDK Account
|
|
48
|
+
* const config = AccountInspector.fromAccount(account);
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
35
51
|
export class AccountInspector {
|
|
36
52
|
private constructor() {}
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Inspect a base64-encoded serialized account.
|
|
56
|
+
*
|
|
57
|
+
* @param base64Data - Base64-encoded Account bytes
|
|
58
|
+
* @returns Detected multisig configuration
|
|
59
|
+
*/
|
|
60
|
+
static fromBase64(base64Data: string): DetectedMultisigConfig {
|
|
61
|
+
const bytes = base64ToUint8Array(base64Data);
|
|
62
|
+
const account = Account.deserialize(bytes);
|
|
63
|
+
return AccountInspector.fromAccount(account);
|
|
42
64
|
}
|
|
43
65
|
|
|
44
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Inspect a Miden SDK Account object.
|
|
68
|
+
*
|
|
69
|
+
* @param account - The Account object from Miden SDK
|
|
70
|
+
* @returns Detected multisig configuration
|
|
71
|
+
*/
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
static fromAccount(account: Account): DetectedMultisigConfig {
|
|
45
74
|
const storage = account.storage();
|
|
46
75
|
|
|
47
76
|
const slot0 = storage.getItem(MULTISIG_SLOT_NAMES.THRESHOLD_CONFIG) as Word;
|
|
@@ -56,26 +85,28 @@ export class AccountInspector {
|
|
|
56
85
|
if (commitment) {
|
|
57
86
|
signerCommitments.push(wordToHex(commitment));
|
|
58
87
|
}
|
|
59
|
-
} catch {
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.warn(error);
|
|
60
90
|
}
|
|
61
91
|
}
|
|
62
92
|
|
|
63
|
-
let
|
|
64
|
-
let
|
|
93
|
+
let guardianEnabled = false;
|
|
94
|
+
let guardianCommitment: string | null = null;
|
|
65
95
|
|
|
66
96
|
try {
|
|
67
|
-
const
|
|
68
|
-
const selector = Number(wordElementToBigInt(
|
|
69
|
-
|
|
97
|
+
const guardianSlot0 = storage.getItem(GUARDIAN_SLOT_NAMES.SELECTOR) as Word;
|
|
98
|
+
const selector = Number(wordElementToBigInt(guardianSlot0, 0));
|
|
99
|
+
guardianEnabled = selector === 1;
|
|
70
100
|
|
|
71
|
-
if (
|
|
101
|
+
if (guardianEnabled) {
|
|
72
102
|
const zeroKey = new Word(new BigUint64Array([0n, 0n, 0n, 0n]));
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
75
|
-
|
|
103
|
+
const guardianKey = storage.getMapItem(GUARDIAN_SLOT_NAMES.PUBLIC_KEY, zeroKey) as Word;
|
|
104
|
+
if (guardianKey) {
|
|
105
|
+
guardianCommitment = wordToHex(guardianKey);
|
|
76
106
|
}
|
|
77
107
|
}
|
|
78
|
-
} catch {
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.warn(error);
|
|
79
110
|
}
|
|
80
111
|
|
|
81
112
|
const vaultBalances: VaultBalance[] = [];
|
|
@@ -88,13 +119,16 @@ export class AccountInspector {
|
|
|
88
119
|
amount: BigInt(asset.amount()),
|
|
89
120
|
});
|
|
90
121
|
}
|
|
91
|
-
} catch {
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.warn(error);
|
|
92
124
|
}
|
|
93
125
|
|
|
126
|
+
// Read procedure threshold overrides from storage slot 3
|
|
127
|
+
// Storage layout: slot 3 is a map of PROC_ROOT => [threshold, 0, 0, 0]
|
|
94
128
|
const procedureThresholds = new Map<ProcedureName, number>();
|
|
95
|
-
for (const procName of getProcedureNames(
|
|
129
|
+
for (const procName of getProcedureNames()) {
|
|
96
130
|
try {
|
|
97
|
-
const rootHex = getProcedureRoot(procName
|
|
131
|
+
const rootHex = getProcedureRoot(procName);
|
|
98
132
|
const rootWord = Word.fromHex(rootHex);
|
|
99
133
|
const value = storage.getMapItem(MULTISIG_SLOT_NAMES.PROCEDURE_THRESHOLDS, rootWord) as Word;
|
|
100
134
|
if (value) {
|
|
@@ -104,6 +138,7 @@ export class AccountInspector {
|
|
|
104
138
|
}
|
|
105
139
|
}
|
|
106
140
|
} catch {
|
|
141
|
+
// Procedure threshold not set - use default
|
|
107
142
|
}
|
|
108
143
|
}
|
|
109
144
|
|
|
@@ -111,11 +146,10 @@ export class AccountInspector {
|
|
|
111
146
|
threshold,
|
|
112
147
|
numSigners,
|
|
113
148
|
signerCommitments,
|
|
114
|
-
|
|
115
|
-
|
|
149
|
+
guardianEnabled,
|
|
150
|
+
guardianCommitment,
|
|
116
151
|
vaultBalances,
|
|
117
152
|
procedureThresholds,
|
|
118
|
-
signatureScheme,
|
|
119
153
|
};
|
|
120
154
|
}
|
|
121
155
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DeltaObject, type
|
|
1
|
+
import { type DeltaObject, type GuardianHttpClient } from '@openzeppelin/guardian-client';
|
|
2
2
|
import type { WebClient, TransactionRequest } from '@miden-sdk/miden-sdk';
|
|
3
3
|
import {
|
|
4
4
|
AccountId,
|
|
@@ -12,7 +12,8 @@ import type { ProposalType, TransactionProposal } from '../../types.js';
|
|
|
12
12
|
import {
|
|
13
13
|
buildConsumeNotesTransactionRequest,
|
|
14
14
|
buildP2idTransactionRequest,
|
|
15
|
-
|
|
15
|
+
buildUpdateGuardianTransactionRequest,
|
|
16
|
+
buildUpdateProcedureThresholdTransactionRequest,
|
|
16
17
|
buildUpdateSignersTransactionRequest,
|
|
17
18
|
} from '../../transaction.js';
|
|
18
19
|
import { base64ToUint8Array, normalizeHexWord } from '../../utils/encoding.js';
|
|
@@ -39,11 +40,11 @@ interface ExecuteProposalWorkflowParams {
|
|
|
39
40
|
accountId: string;
|
|
40
41
|
threshold: number;
|
|
41
42
|
signerCommitments: string[];
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
guardianCommitment: string;
|
|
44
|
+
guardianPublicKey?: string;
|
|
44
45
|
signatureScheme: 'falcon' | 'ecdsa';
|
|
45
46
|
getEffectiveThreshold: (proposalType: ProposalType) => number;
|
|
46
|
-
|
|
47
|
+
guardian: GuardianHttpClient;
|
|
47
48
|
webClient: WebClient;
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -56,12 +57,12 @@ export async function executeProposalWorkflow(
|
|
|
56
57
|
params.getEffectiveThreshold,
|
|
57
58
|
);
|
|
58
59
|
|
|
59
|
-
const
|
|
60
|
+
const isSwitchGuardian = params.proposal.metadata.proposalType === 'switch_guardian';
|
|
60
61
|
const executionSource = await resolveExecutionSource(
|
|
61
|
-
params.
|
|
62
|
+
params.guardian,
|
|
62
63
|
params.accountId,
|
|
63
64
|
params.proposal,
|
|
64
|
-
|
|
65
|
+
isSwitchGuardian,
|
|
65
66
|
);
|
|
66
67
|
const executionData = prepareExecutionData(executionSource.txSummaryBase64);
|
|
67
68
|
|
|
@@ -71,12 +72,12 @@ export async function executeProposalWorkflow(
|
|
|
71
72
|
executionData.txCommitmentHex,
|
|
72
73
|
);
|
|
73
74
|
|
|
74
|
-
if (!
|
|
75
|
-
await
|
|
76
|
-
params.
|
|
75
|
+
if (!isSwitchGuardian && executionSource.delta) {
|
|
76
|
+
await appendGuardianAckAdvice(
|
|
77
|
+
params.guardian,
|
|
77
78
|
executionSource.delta,
|
|
78
|
-
params.
|
|
79
|
-
params.
|
|
79
|
+
params.guardianCommitment,
|
|
80
|
+
params.guardianPublicKey,
|
|
80
81
|
params.signatureScheme,
|
|
81
82
|
executionData.txCommitmentHex,
|
|
82
83
|
adviceMap,
|
|
@@ -101,12 +102,12 @@ export async function createTransactionProposalRequest(
|
|
|
101
102
|
params.getEffectiveThreshold,
|
|
102
103
|
);
|
|
103
104
|
|
|
104
|
-
const
|
|
105
|
+
const isSwitchGuardian = params.proposal.metadata.proposalType === 'switch_guardian';
|
|
105
106
|
const executionSource = await resolveExecutionSource(
|
|
106
|
-
params.
|
|
107
|
+
params.guardian,
|
|
107
108
|
params.accountId,
|
|
108
109
|
params.proposal,
|
|
109
|
-
|
|
110
|
+
isSwitchGuardian,
|
|
110
111
|
);
|
|
111
112
|
const executionData = prepareExecutionData(executionSource.txSummaryBase64);
|
|
112
113
|
|
|
@@ -116,12 +117,12 @@ export async function createTransactionProposalRequest(
|
|
|
116
117
|
executionData.txCommitmentHex,
|
|
117
118
|
);
|
|
118
119
|
|
|
119
|
-
if (!
|
|
120
|
-
await
|
|
121
|
-
params.
|
|
120
|
+
if (!isSwitchGuardian && executionSource.delta) {
|
|
121
|
+
await appendGuardianAckAdvice(
|
|
122
|
+
params.guardian,
|
|
122
123
|
executionSource.delta,
|
|
123
|
-
params.
|
|
124
|
-
params.
|
|
124
|
+
params.guardianCommitment,
|
|
125
|
+
params.guardianPublicKey,
|
|
125
126
|
params.signatureScheme,
|
|
126
127
|
executionData.txCommitmentHex,
|
|
127
128
|
adviceMap,
|
|
@@ -151,16 +152,16 @@ function ensureProposalReady(
|
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
async function resolveExecutionSource(
|
|
154
|
-
|
|
155
|
+
guardian: GuardianHttpClient,
|
|
155
156
|
accountId: string,
|
|
156
157
|
proposal: TransactionProposal,
|
|
157
|
-
|
|
158
|
+
isSwitchGuardian: boolean,
|
|
158
159
|
): Promise<ResolveExecutionSourceResult> {
|
|
159
|
-
if (
|
|
160
|
+
if (isSwitchGuardian) {
|
|
160
161
|
return { txSummaryBase64: proposal.txSummary };
|
|
161
162
|
}
|
|
162
163
|
|
|
163
|
-
const deltas = await
|
|
164
|
+
const deltas = await guardian.getDeltaProposals(accountId);
|
|
164
165
|
const delta = deltas.find(
|
|
165
166
|
(d) => computeCommitmentFromTxSummary(d.deltaPayload.txSummary.data) === proposal.commitment,
|
|
166
167
|
);
|
|
@@ -214,14 +215,17 @@ function buildCosignerAdviceMap(
|
|
|
214
215
|
);
|
|
215
216
|
const signature = Signature.deserialize(sigBytes);
|
|
216
217
|
const txCommitment = Word.fromHex(normalizeHexWord(txCommitmentHex));
|
|
217
|
-
const
|
|
218
|
-
cosignerSig.signature.scheme === 'ecdsa'
|
|
218
|
+
const ecdsaPublicKey =
|
|
219
|
+
cosignerSig.signature.scheme === 'ecdsa'
|
|
220
|
+
? cosignerSig.signature.publicKey
|
|
221
|
+
: undefined;
|
|
222
|
+
const isEcdsa = cosignerSig.signature.scheme === 'ecdsa' && Boolean(ecdsaPublicKey);
|
|
219
223
|
|
|
220
224
|
const { key, values } = buildSignatureAdviceEntry(
|
|
221
225
|
signerCommitment,
|
|
222
226
|
txCommitment,
|
|
223
227
|
signature,
|
|
224
|
-
|
|
228
|
+
ecdsaPublicKey,
|
|
225
229
|
isEcdsa ? cosignerSig.signature.signature : undefined,
|
|
226
230
|
);
|
|
227
231
|
adviceMap.insert(key, new FeltArray(values));
|
|
@@ -230,11 +234,11 @@ function buildCosignerAdviceMap(
|
|
|
230
234
|
return adviceMap;
|
|
231
235
|
}
|
|
232
236
|
|
|
233
|
-
async function
|
|
234
|
-
|
|
237
|
+
async function appendGuardianAckAdvice(
|
|
238
|
+
guardian: GuardianHttpClient,
|
|
235
239
|
delta: DeltaObject,
|
|
236
|
-
|
|
237
|
-
|
|
240
|
+
guardianCommitmentHex: string,
|
|
241
|
+
guardianPublicKey: string | undefined,
|
|
238
242
|
defaultAckScheme: 'falcon' | 'ecdsa',
|
|
239
243
|
txCommitmentHex: string,
|
|
240
244
|
adviceMap: AdviceMap,
|
|
@@ -244,31 +248,31 @@ async function appendPsmAckAdvice(
|
|
|
244
248
|
deltaPayload: delta.deltaPayload.txSummary,
|
|
245
249
|
};
|
|
246
250
|
|
|
247
|
-
const pushResult = await
|
|
251
|
+
const pushResult = await guardian.pushDelta(executionDelta);
|
|
248
252
|
const ackSigHex = pushResult.ackSig;
|
|
249
253
|
if (!ackSigHex) {
|
|
250
|
-
throw new Error('
|
|
254
|
+
throw new Error('GUARDIAN did not return acknowledgment signature');
|
|
251
255
|
}
|
|
252
256
|
|
|
253
|
-
const
|
|
257
|
+
const guardianAckScheme: 'ecdsa' | 'falcon' =
|
|
254
258
|
(pushResult.ackScheme as 'ecdsa' | 'falcon') || defaultAckScheme;
|
|
255
|
-
const ackPubkey = pushResult.ackPubkey ||
|
|
256
|
-
const
|
|
259
|
+
const ackPubkey = pushResult.ackPubkey || guardianPublicKey;
|
|
260
|
+
const normalizedGuardianCommitment = normalizeHexWord(guardianCommitmentHex);
|
|
257
261
|
|
|
258
|
-
if (
|
|
262
|
+
if (guardianAckScheme === 'ecdsa' && ackPubkey) {
|
|
259
263
|
const derived = tryComputeEcdsaCommitmentHex(ackPubkey);
|
|
260
|
-
if (derived && derived !==
|
|
261
|
-
throw new Error('
|
|
264
|
+
if (derived && derived !== normalizedGuardianCommitment) {
|
|
265
|
+
throw new Error('GUARDIAN public key commitment mismatch');
|
|
262
266
|
}
|
|
263
267
|
}
|
|
264
268
|
|
|
265
|
-
const
|
|
266
|
-
const ackSigBytes = signatureHexToBytes(ackSigHex,
|
|
269
|
+
const guardianCommitment = Word.fromHex(normalizedGuardianCommitment);
|
|
270
|
+
const ackSigBytes = signatureHexToBytes(ackSigHex, guardianAckScheme);
|
|
267
271
|
const ackSignature = Signature.deserialize(ackSigBytes);
|
|
268
272
|
const txCommitment = Word.fromHex(normalizeHexWord(txCommitmentHex));
|
|
269
|
-
const isAckEcdsa =
|
|
273
|
+
const isAckEcdsa = guardianAckScheme === 'ecdsa' && ackPubkey;
|
|
270
274
|
const { key, values } = buildSignatureAdviceEntry(
|
|
271
|
-
|
|
275
|
+
guardianCommitment,
|
|
272
276
|
txCommitment,
|
|
273
277
|
ackSignature,
|
|
274
278
|
isAckEcdsa ? ackPubkey : undefined,
|
|
@@ -299,15 +303,28 @@ async function buildFinalRequest(
|
|
|
299
303
|
);
|
|
300
304
|
return request;
|
|
301
305
|
}
|
|
302
|
-
case '
|
|
303
|
-
if (!metadata.
|
|
306
|
+
case 'switch_guardian': {
|
|
307
|
+
if (!metadata.newGuardianPubkey) {
|
|
304
308
|
throw new Error(
|
|
305
|
-
'Proposal missing
|
|
309
|
+
'Proposal missing newGuardianPubkey. Was it created with createSwitchGuardianProposal?',
|
|
306
310
|
);
|
|
307
311
|
}
|
|
308
|
-
const { request } = await
|
|
312
|
+
const { request } = await buildUpdateGuardianTransactionRequest(
|
|
309
313
|
params.webClient,
|
|
310
|
-
metadata.
|
|
314
|
+
metadata.newGuardianPubkey,
|
|
315
|
+
{
|
|
316
|
+
salt: normalizedSalt,
|
|
317
|
+
signatureAdviceMap: adviceMap,
|
|
318
|
+
signatureScheme: params.signatureScheme,
|
|
319
|
+
},
|
|
320
|
+
);
|
|
321
|
+
return request;
|
|
322
|
+
}
|
|
323
|
+
case 'update_procedure_threshold': {
|
|
324
|
+
const { request } = await buildUpdateProcedureThresholdTransactionRequest(
|
|
325
|
+
params.webClient,
|
|
326
|
+
metadata.targetProcedure,
|
|
327
|
+
metadata.targetThreshold,
|
|
311
328
|
{
|
|
312
329
|
salt: normalizedSalt,
|
|
313
330
|
signatureAdviceMap: adviceMap,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DeltaObject,
|
|
3
3
|
DeltaStatus,
|
|
4
|
-
ProposalMetadata as
|
|
5
|
-
} from '@openzeppelin/
|
|
4
|
+
ProposalMetadata as GuardianProposalMetadata,
|
|
5
|
+
} from '@openzeppelin/guardian-client';
|
|
6
6
|
import type {
|
|
7
7
|
ProposalMetadata,
|
|
8
8
|
ProposalType,
|
|
@@ -11,8 +11,8 @@ import type {
|
|
|
11
11
|
TransactionProposalStatus,
|
|
12
12
|
} from '../../types.js';
|
|
13
13
|
|
|
14
|
-
export function
|
|
15
|
-
const base:
|
|
14
|
+
export function buildGuardianMetadata(metadata: ProposalMetadata): GuardianProposalMetadata {
|
|
15
|
+
const base: GuardianProposalMetadata = {
|
|
16
16
|
proposalType: metadata.proposalType,
|
|
17
17
|
description: metadata.description,
|
|
18
18
|
salt: metadata.saltHex,
|
|
@@ -31,13 +31,13 @@ export function buildPsmMetadata(metadata: ProposalMetadata): PsmProposalMetadat
|
|
|
31
31
|
faucetId: metadata.faucetId,
|
|
32
32
|
amount: metadata.amount,
|
|
33
33
|
};
|
|
34
|
-
case '
|
|
34
|
+
case 'switch_guardian':
|
|
35
35
|
return {
|
|
36
36
|
...base,
|
|
37
37
|
targetThreshold: metadata.targetThreshold,
|
|
38
38
|
signerCommitments: metadata.targetSignerCommitments,
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
newGuardianPubkey: metadata.newGuardianPubkey,
|
|
40
|
+
newGuardianEndpoint: metadata.newGuardianEndpoint,
|
|
41
41
|
};
|
|
42
42
|
case 'add_signer':
|
|
43
43
|
case 'remove_signer':
|
|
@@ -54,46 +54,46 @@ export function buildPsmMetadata(metadata: ProposalMetadata): PsmProposalMetadat
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export function
|
|
58
|
-
if (!
|
|
57
|
+
export function fromGuardianMetadata(guardian: GuardianProposalMetadata): ProposalMetadata | undefined {
|
|
58
|
+
if (!guardian.proposalType) return undefined;
|
|
59
59
|
|
|
60
60
|
const base = {
|
|
61
|
-
description:
|
|
62
|
-
saltHex:
|
|
61
|
+
description: guardian.description ?? '',
|
|
62
|
+
saltHex: guardian.salt,
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
-
switch (
|
|
65
|
+
switch (guardian.proposalType) {
|
|
66
66
|
case 'p2id':
|
|
67
67
|
return {
|
|
68
68
|
...base,
|
|
69
69
|
proposalType: 'p2id',
|
|
70
|
-
recipientId:
|
|
71
|
-
faucetId:
|
|
72
|
-
amount:
|
|
70
|
+
recipientId: guardian.recipientId ?? '',
|
|
71
|
+
faucetId: guardian.faucetId ?? '',
|
|
72
|
+
amount: guardian.amount ?? '0',
|
|
73
73
|
};
|
|
74
74
|
case 'consume_notes':
|
|
75
75
|
return {
|
|
76
76
|
...base,
|
|
77
77
|
proposalType: 'consume_notes',
|
|
78
|
-
noteIds:
|
|
78
|
+
noteIds: guardian.noteIds ?? [],
|
|
79
79
|
};
|
|
80
|
-
case '
|
|
80
|
+
case 'switch_guardian':
|
|
81
81
|
return {
|
|
82
82
|
...base,
|
|
83
|
-
proposalType: '
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
targetThreshold:
|
|
87
|
-
targetSignerCommitments:
|
|
83
|
+
proposalType: 'switch_guardian',
|
|
84
|
+
newGuardianPubkey: guardian.newGuardianPubkey ?? '',
|
|
85
|
+
newGuardianEndpoint: guardian.newGuardianEndpoint,
|
|
86
|
+
targetThreshold: guardian.targetThreshold,
|
|
87
|
+
targetSignerCommitments: guardian.signerCommitments,
|
|
88
88
|
};
|
|
89
89
|
case 'add_signer':
|
|
90
90
|
case 'remove_signer':
|
|
91
91
|
case 'change_threshold':
|
|
92
92
|
return {
|
|
93
93
|
...base,
|
|
94
|
-
proposalType:
|
|
95
|
-
targetThreshold:
|
|
96
|
-
targetSignerCommitments:
|
|
94
|
+
proposalType: guardian.proposalType,
|
|
95
|
+
targetThreshold: guardian.targetThreshold ?? 0,
|
|
96
|
+
targetSignerCommitments: guardian.signerCommitments ?? [],
|
|
97
97
|
};
|
|
98
98
|
default:
|
|
99
99
|
return undefined;
|
|
@@ -178,7 +178,7 @@ export function resolveMetadata(
|
|
|
178
178
|
): ProposalMetadata | undefined {
|
|
179
179
|
if (existingMetadata) return existingMetadata;
|
|
180
180
|
if (!delta.deltaPayload.metadata) return undefined;
|
|
181
|
-
return
|
|
181
|
+
return fromGuardianMetadata(delta.deltaPayload.metadata);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
export function signatureRequirementForProposal(
|
package/src/multisig/signing.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ProposalSignature, Signer } from '@openzeppelin/
|
|
1
|
+
import type { ProposalSignature, Signer } from '@openzeppelin/guardian-client';
|
|
2
2
|
import type { SignatureScheme } from '../types.js';
|
|
3
3
|
|
|
4
|
-
export function
|
|
4
|
+
export function toGuardianSignature(
|
|
5
5
|
scheme: SignatureScheme,
|
|
6
6
|
signatureHex: string,
|
|
7
7
|
publicKey?: string,
|
|
@@ -15,10 +15,10 @@ export function toPsmSignature(
|
|
|
15
15
|
return { scheme: 'falcon', signature: signatureHex };
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export async function
|
|
18
|
+
export async function buildGuardianSignatureFromSigner(
|
|
19
19
|
signer: Signer,
|
|
20
20
|
commitment: string,
|
|
21
21
|
): Promise<ProposalSignature> {
|
|
22
22
|
const signatureHex = await signer.signCommitment(commitment);
|
|
23
|
-
return
|
|
23
|
+
return toGuardianSignature(signer.scheme, signatureHex, signer.publicKey);
|
|
24
24
|
}
|