ox 0.14.38 → 0.14.40
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/CHANGELOG.md +20 -0
- package/_cjs/tempo/MultisigConfig.js +71 -15
- package/_cjs/tempo/MultisigConfig.js.map +1 -1
- package/_cjs/tempo/MultisigOperation.js +43 -35
- package/_cjs/tempo/MultisigOperation.js.map +1 -1
- package/_cjs/tempo/MultisigWitness.js +92 -0
- package/_cjs/tempo/MultisigWitness.js.map +1 -0
- package/_cjs/tempo/SignatureEnvelope.js +71 -108
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/tempo/TransactionRequest.js +7 -1
- package/_cjs/tempo/TransactionRequest.js.map +1 -1
- package/_cjs/tempo/index.js +2 -1
- package/_cjs/tempo/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/tempo/MultisigConfig.js +140 -71
- package/_esm/tempo/MultisigConfig.js.map +1 -1
- package/_esm/tempo/MultisigOperation.js +43 -36
- package/_esm/tempo/MultisigOperation.js.map +1 -1
- package/_esm/tempo/MultisigWitness.js +123 -0
- package/_esm/tempo/MultisigWitness.js.map +1 -0
- package/_esm/tempo/SignatureEnvelope.js +84 -143
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/tempo/TransactionRequest.js +7 -1
- package/_esm/tempo/TransactionRequest.js.map +1 -1
- package/_esm/tempo/index.js +9 -0
- package/_esm/tempo/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/tempo/KeyAuthorization.d.ts +1 -1
- package/_types/tempo/KeyAuthorization.d.ts.map +1 -1
- package/_types/tempo/MultisigConfig.d.ts +137 -73
- package/_types/tempo/MultisigConfig.d.ts.map +1 -1
- package/_types/tempo/MultisigOperation.d.ts +1 -1
- package/_types/tempo/MultisigOperation.d.ts.map +1 -1
- package/_types/tempo/MultisigWitness.d.ts +106 -0
- package/_types/tempo/MultisigWitness.d.ts.map +1 -0
- package/_types/tempo/SignatureEnvelope.d.ts +81 -75
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/tempo/TransactionRequest.d.ts +6 -3
- package/_types/tempo/TransactionRequest.d.ts.map +1 -1
- package/_types/tempo/index.d.ts +9 -0
- package/_types/tempo/index.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/package.json +21 -1
- package/tempo/KeyAuthorization.test-d.ts +12 -0
- package/tempo/KeyAuthorization.test.ts +54 -0
- package/tempo/KeyAuthorization.ts +1 -1
- package/tempo/MultisigConfig.test-d/package.json +6 -0
- package/tempo/MultisigConfig.test-d.ts +52 -0
- package/tempo/MultisigConfig.test.ts +291 -263
- package/tempo/MultisigConfig.ts +250 -95
- package/tempo/MultisigOperation.test-d.ts +6 -0
- package/tempo/MultisigOperation.test.ts +200 -81
- package/tempo/MultisigOperation.ts +42 -34
- package/tempo/MultisigWitness/package.json +6 -0
- package/tempo/MultisigWitness.test-d/package.json +6 -0
- package/tempo/MultisigWitness.test-d.ts +42 -0
- package/tempo/MultisigWitness.test.ts +289 -0
- package/tempo/MultisigWitness.ts +210 -0
- package/tempo/RpcSchemaTempo.test-d.ts +25 -0
- package/tempo/SignatureEnvelope.test-d.ts +57 -40
- package/tempo/SignatureEnvelope.test.ts +523 -480
- package/tempo/SignatureEnvelope.ts +250 -257
- package/tempo/TransactionRequest.test-d/package.json +6 -0
- package/tempo/TransactionRequest.test-d.ts +24 -0
- package/tempo/TransactionRequest.test.ts +102 -1
- package/tempo/TransactionRequest.ts +12 -2
- package/tempo/index.ts +9 -0
- package/tempo/multisig.e2e.test.ts +113 -86
- package/version.ts +1 -1
|
@@ -2,12 +2,6 @@ import * as Address from '../core/Address.js';
|
|
|
2
2
|
import * as Errors from '../core/Errors.js';
|
|
3
3
|
import * as Hash from '../core/Hash.js';
|
|
4
4
|
import * as Hex from '../core/Hex.js';
|
|
5
|
-
/** Maximum number of owners allowed in a native multisig config. */
|
|
6
|
-
export const maxOwners = 48;
|
|
7
|
-
/** Maximum threshold accepted by a native multisig config. */
|
|
8
|
-
export const maxThreshold = 0xff;
|
|
9
|
-
/** Maximum number of owner approvals in a native multisig signature. */
|
|
10
|
-
export const maxSignatures = 8;
|
|
11
5
|
/**
|
|
12
6
|
* Maximum number of native multisig signatures in one nested authorization
|
|
13
7
|
* path, including the top-level transaction signature.
|
|
@@ -15,18 +9,28 @@ export const maxSignatures = 8;
|
|
|
15
9
|
export const maxNestingDepth = 2;
|
|
16
10
|
/** Maximum encoded byte length for one primitive owner approval. */
|
|
17
11
|
export const maxOwnerSignatureBytes = 2049;
|
|
12
|
+
/** Maximum number of owners allowed in a native multisig config. */
|
|
13
|
+
export const maxOwners = 48;
|
|
14
|
+
/** Maximum number of owner approvals in a native multisig signature. */
|
|
15
|
+
export const maxSignatures = 8;
|
|
16
|
+
/** Maximum threshold accepted by a native multisig config. */
|
|
17
|
+
export const maxThreshold = 0xff;
|
|
18
|
+
/** Maximum version accepted by a native multisig config. */
|
|
19
|
+
export const maxVersion = 2n ** 64n - 1n;
|
|
18
20
|
/** Tempo signature type byte for native multisig signatures. */
|
|
19
21
|
export const signatureTypeByte = '0x05';
|
|
20
22
|
/** Zero 32-byte salt (the default when no salt is provided). */
|
|
21
23
|
export const zeroSalt = `0x${'00'.repeat(32)}`;
|
|
22
24
|
/** Domain prefix for the native multisig account address derivation. */
|
|
23
25
|
const accountDomain = 'tempo:multisig:account';
|
|
26
|
+
/** Domain prefix for native multisig configuration commitments. */
|
|
27
|
+
const configDomain = 'tempo:multisig:config';
|
|
24
28
|
/** Domain prefix for native multisig owner approvals. */
|
|
25
29
|
const signatureDomain = 'tempo:multisig:signature';
|
|
26
30
|
/**
|
|
27
31
|
* Asserts that a native multisig {@link ox#MultisigConfig.Config} is valid.
|
|
28
32
|
*
|
|
29
|
-
* Mirrors the Tempo
|
|
33
|
+
* Mirrors the Tempo configuration rules: owners non-empty and
|
|
30
34
|
* `<= maxOwners`, strictly ascending unique nonzero owner addresses, nonzero
|
|
31
35
|
* integer owner weights, integer `threshold` between `1` and `maxThreshold`,
|
|
32
36
|
* total weight `<= 255` (u8 max), and a threshold reachable by at most
|
|
@@ -47,9 +51,10 @@ const signatureDomain = 'tempo:multisig:signature';
|
|
|
47
51
|
* @param config - The multisig config.
|
|
48
52
|
*/
|
|
49
53
|
export function assert(config) {
|
|
50
|
-
const { salt, threshold,
|
|
54
|
+
const { owners, salt, threshold, version = 0n } = config;
|
|
51
55
|
if (typeof salt !== 'undefined' && Hex.size(salt) !== 32)
|
|
52
56
|
throw new InvalidConfigError({ reason: 'salt must be 32 bytes' });
|
|
57
|
+
assertVersion(version);
|
|
53
58
|
if (owners.length === 0)
|
|
54
59
|
throw new InvalidConfigError({ reason: 'owners cannot be empty' });
|
|
55
60
|
if (owners.length > maxOwners)
|
|
@@ -99,38 +104,45 @@ export function assert(config) {
|
|
|
99
104
|
reason: `threshold exceeds weight reachable by ${maxSignatures} owner signatures`,
|
|
100
105
|
});
|
|
101
106
|
}
|
|
107
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
108
|
+
export function from(config) {
|
|
109
|
+
const version = config.version ?? 0n;
|
|
110
|
+
assertVersion(version);
|
|
111
|
+
const owners = [...config.owners].sort((a, b) => Hex.toBigInt(a.owner) < Hex.toBigInt(b.owner) ? -1 : 1);
|
|
112
|
+
const normalized = {
|
|
113
|
+
owners,
|
|
114
|
+
salt: config.salt ? Hex.padLeft(config.salt, 32) : zeroSalt,
|
|
115
|
+
threshold: config.threshold,
|
|
116
|
+
version: BigInt(version),
|
|
117
|
+
};
|
|
118
|
+
assert(normalized);
|
|
119
|
+
return normalized;
|
|
120
|
+
}
|
|
102
121
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* Sorts owners into strictly ascending `owner` address order (the canonical
|
|
106
|
-
* form required for account derivation) and asserts the config is valid.
|
|
122
|
+
* Converts a JSON-RPC multisig configuration to its domain representation.
|
|
107
123
|
*
|
|
108
124
|
* @example
|
|
109
125
|
* ```ts twoslash
|
|
110
126
|
* import { MultisigConfig } from 'ox/tempo'
|
|
111
127
|
*
|
|
112
|
-
* const config = MultisigConfig.
|
|
113
|
-
* threshold: 2,
|
|
128
|
+
* const config = MultisigConfig.fromRpc({
|
|
114
129
|
* owners: [
|
|
115
|
-
* { owner: '0x2222222222222222222222222222222222222222', weight: 1 },
|
|
116
130
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
117
131
|
* ],
|
|
132
|
+
* salt: `0x${'00'.repeat(32)}`,
|
|
133
|
+
* threshold: 1,
|
|
134
|
+
* version: '0x0',
|
|
118
135
|
* })
|
|
119
|
-
* // owners are now sorted ascending by address
|
|
120
136
|
* ```
|
|
121
137
|
*
|
|
122
|
-
* @param config - The multisig
|
|
123
|
-
* @returns The normalized multisig
|
|
138
|
+
* @param config - The JSON-RPC multisig configuration.
|
|
139
|
+
* @returns The normalized multisig configuration.
|
|
124
140
|
*/
|
|
125
|
-
export function
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
owners,
|
|
131
|
-
};
|
|
132
|
-
assert(normalized);
|
|
133
|
-
return normalized;
|
|
141
|
+
export function fromRpc(config) {
|
|
142
|
+
return from({
|
|
143
|
+
...config,
|
|
144
|
+
version: Hex.toBigInt(config.version),
|
|
145
|
+
});
|
|
134
146
|
}
|
|
135
147
|
/**
|
|
136
148
|
* Converts an RLP {@link ox#MultisigConfig.Tuple} back to a
|
|
@@ -142,6 +154,7 @@ export function from(config) {
|
|
|
142
154
|
*
|
|
143
155
|
* const config = MultisigConfig.fromTuple([
|
|
144
156
|
* `0x${'00'.repeat(32)}`,
|
|
157
|
+
* '0x',
|
|
145
158
|
* '0x01',
|
|
146
159
|
* [['0x1111111111111111111111111111111111111111', '0x01']],
|
|
147
160
|
* ])
|
|
@@ -151,10 +164,8 @@ export function from(config) {
|
|
|
151
164
|
* @returns The multisig config.
|
|
152
165
|
*/
|
|
153
166
|
export function fromTuple(tuple) {
|
|
154
|
-
const [salt, threshold, owners] = tuple;
|
|
167
|
+
const [salt, version, threshold, owners] = tuple;
|
|
155
168
|
return {
|
|
156
|
-
salt: salt && salt !== '0x' ? Hex.padLeft(salt, 32) : zeroSalt,
|
|
157
|
-
threshold: threshold === '0x' ? 0 : Hex.toNumber(threshold),
|
|
158
169
|
owners: owners.map((owner) => {
|
|
159
170
|
const [ownerAddress, weight] = owner;
|
|
160
171
|
return {
|
|
@@ -162,6 +173,9 @@ export function fromTuple(tuple) {
|
|
|
162
173
|
weight: !weight || weight === '0x' ? 0 : Hex.toNumber(weight),
|
|
163
174
|
};
|
|
164
175
|
}),
|
|
176
|
+
salt: salt && salt !== '0x' ? Hex.padLeft(salt, 32) : zeroSalt,
|
|
177
|
+
threshold: threshold === '0x' ? 0 : Hex.toNumber(threshold),
|
|
178
|
+
version: version === '0x' ? 0n : Hex.toBigInt(version),
|
|
165
179
|
};
|
|
166
180
|
}
|
|
167
181
|
/**
|
|
@@ -170,28 +184,32 @@ export function fromTuple(tuple) {
|
|
|
170
184
|
* Preimage (fixed-width big-endian, **not** RLP):
|
|
171
185
|
* `keccak256("tempo:multisig:account" || salt || u8(threshold) || u8(owners.length) || (owner || u8(weight)) for each owner)[12:32]`.
|
|
172
186
|
*
|
|
173
|
-
* The address is derived once from the initial
|
|
174
|
-
*
|
|
187
|
+
* The address is derived once from the initial version-0 config. Config
|
|
188
|
+
* updates do not change it.
|
|
175
189
|
*
|
|
176
190
|
* @example
|
|
177
191
|
* ```ts twoslash
|
|
178
192
|
* import { MultisigConfig } from 'ox/tempo'
|
|
179
193
|
*
|
|
180
194
|
* const initialConfig = MultisigConfig.from({
|
|
181
|
-
* threshold: 1,
|
|
182
195
|
* owners: [
|
|
183
196
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
184
197
|
* ],
|
|
198
|
+
* threshold: 1,
|
|
185
199
|
* })
|
|
186
200
|
*
|
|
187
201
|
* const address = MultisigConfig.getAddress(initialConfig)
|
|
188
202
|
* ```
|
|
189
203
|
*
|
|
190
|
-
* @param config - The initial
|
|
204
|
+
* @param config - The initial multisig config.
|
|
191
205
|
* @returns The multisig account address.
|
|
192
206
|
*/
|
|
193
207
|
export function getAddress(config) {
|
|
194
208
|
assert(config);
|
|
209
|
+
if (BigInt(config.version ?? 0) !== 0n)
|
|
210
|
+
throw new InvalidConfigError({
|
|
211
|
+
reason: 'account address requires version zero',
|
|
212
|
+
});
|
|
195
213
|
const hash = Hash.keccak256(Hex.concat(Hex.fromString(accountDomain), Hex.padLeft(config.salt ?? zeroSalt, 32), Hex.fromNumber(config.threshold, { size: 1 }), Hex.fromNumber(config.owners.length, { size: 1 }), ...config.owners.flatMap((owner) => [
|
|
196
214
|
owner.owner,
|
|
197
215
|
Hex.fromNumber(owner.weight, { size: 1 }),
|
|
@@ -199,8 +217,41 @@ export function getAddress(config) {
|
|
|
199
217
|
const account = Address.from(Hex.slice(hash, 12, 32));
|
|
200
218
|
if (Hex.toBigInt(account) === 0n)
|
|
201
219
|
throw new InvalidConfigError({ reason: 'derived account cannot be zero' });
|
|
220
|
+
if (config.owners.some((owner) => Address.isEqual(owner.owner, account)))
|
|
221
|
+
throw new InvalidConfigError({
|
|
222
|
+
reason: 'derived account cannot be an owner',
|
|
223
|
+
});
|
|
202
224
|
return account;
|
|
203
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Computes the commitment for a native multisig configuration.
|
|
228
|
+
*
|
|
229
|
+
* The commitment uses raw fixed-width fields, not RLP or ABI encoding:
|
|
230
|
+
* `keccak256("tempo:multisig:config" || salt || uint64be(version) || uint8(threshold) || uint8(owners.length) || owners)`.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts twoslash
|
|
234
|
+
* import { MultisigConfig } from 'ox/tempo'
|
|
235
|
+
*
|
|
236
|
+
* const commitment = MultisigConfig.getCommitment({
|
|
237
|
+
* owners: [
|
|
238
|
+
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
239
|
+
* ],
|
|
240
|
+
* threshold: 1,
|
|
241
|
+
* version: 1n,
|
|
242
|
+
* })
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @param config - The complete multisig configuration.
|
|
246
|
+
* @returns The configuration commitment.
|
|
247
|
+
*/
|
|
248
|
+
export function getCommitment(config) {
|
|
249
|
+
assert(config);
|
|
250
|
+
return Hash.keccak256(Hex.concat(Hex.fromString(configDomain), Hex.padLeft(config.salt ?? zeroSalt, 32), Hex.fromNumber(config.version ?? 0n, { size: 8 }), Hex.fromNumber(config.threshold, { size: 1 }), Hex.fromNumber(config.owners.length, { size: 1 }), ...config.owners.flatMap((owner) => [
|
|
251
|
+
owner.owner,
|
|
252
|
+
Hex.fromNumber(owner.weight, { size: 1 }),
|
|
253
|
+
])));
|
|
254
|
+
}
|
|
204
255
|
/**
|
|
205
256
|
* Computes the digest a native multisig owner approves (signs).
|
|
206
257
|
*
|
|
@@ -208,9 +259,9 @@ export function getAddress(config) {
|
|
|
208
259
|
* where `inner_digest` is the transaction sign payload
|
|
209
260
|
* ({@link ox#TxEnvelopeTempo.(getSignPayload:function)}).
|
|
210
261
|
*
|
|
211
|
-
* The digest is keyed on the permanent `account`
|
|
212
|
-
*
|
|
213
|
-
*
|
|
262
|
+
* The digest is keyed on the permanent `account` and the supplied config
|
|
263
|
+
* version. Initial approvals use version `0n`; each config update increments
|
|
264
|
+
* it.
|
|
214
265
|
*
|
|
215
266
|
* For a nested multisig owner approval, the parent digest becomes the nested
|
|
216
267
|
* approval's `payload`, with the nested multisig `account`.
|
|
@@ -219,11 +270,11 @@ export function getAddress(config) {
|
|
|
219
270
|
* ```ts twoslash
|
|
220
271
|
* import { MultisigConfig, TxEnvelopeTempo } from 'ox/tempo'
|
|
221
272
|
*
|
|
222
|
-
* const
|
|
223
|
-
* threshold: 1,
|
|
273
|
+
* const config = MultisigConfig.from({
|
|
224
274
|
* owners: [
|
|
225
275
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
226
276
|
* ],
|
|
277
|
+
* threshold: 1,
|
|
227
278
|
* })
|
|
228
279
|
*
|
|
229
280
|
* const envelope = TxEnvelopeTempo.from({
|
|
@@ -232,52 +283,54 @@ export function getAddress(config) {
|
|
|
232
283
|
* })
|
|
233
284
|
*
|
|
234
285
|
* const digest = MultisigConfig.getSignPayload({
|
|
286
|
+
* account: MultisigConfig.getAddress(config),
|
|
287
|
+
* config,
|
|
235
288
|
* payload: TxEnvelopeTempo.getSignPayload(envelope),
|
|
236
|
-
* initialConfig,
|
|
237
289
|
* })
|
|
238
290
|
* ```
|
|
239
291
|
*
|
|
240
|
-
* @
|
|
241
|
-
*
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
292
|
+
* @param value - The digest derivation parameters.
|
|
293
|
+
* @returns The owner approval digest.
|
|
294
|
+
*/
|
|
295
|
+
export function getSignPayload(value) {
|
|
296
|
+
const { account, config, payload } = value;
|
|
297
|
+
assertVersion(config.version);
|
|
298
|
+
return Hash.keccak256(Hex.concat(Hex.fromString(signatureDomain), Hex.from(payload), account, Hex.fromNumber(config.version ?? 0n, { size: 8 })));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Converts a multisig configuration to its JSON-RPC representation.
|
|
245
302
|
*
|
|
303
|
+
* @example
|
|
246
304
|
* ```ts twoslash
|
|
247
|
-
* import { MultisigConfig
|
|
305
|
+
* import { MultisigConfig } from 'ox/tempo'
|
|
248
306
|
*
|
|
249
|
-
* const
|
|
250
|
-
* threshold: 1,
|
|
307
|
+
* const config = MultisigConfig.toRpc({
|
|
251
308
|
* owners: [
|
|
252
309
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
253
310
|
* ],
|
|
254
|
-
*
|
|
255
|
-
* const account = MultisigConfig.getAddress(initialConfig)
|
|
256
|
-
*
|
|
257
|
-
* const envelope = TxEnvelopeTempo.from({ chainId: 1, calls: [] })
|
|
258
|
-
*
|
|
259
|
-
* const digest = MultisigConfig.getSignPayload({
|
|
260
|
-
* payload: TxEnvelopeTempo.getSignPayload(envelope),
|
|
261
|
-
* account,
|
|
262
|
-
* version: 1n
|
|
311
|
+
* threshold: 1,
|
|
263
312
|
* })
|
|
264
313
|
* ```
|
|
265
314
|
*
|
|
266
|
-
* @param
|
|
267
|
-
* @returns The
|
|
315
|
+
* @param config - The multisig configuration.
|
|
316
|
+
* @returns The JSON-RPC multisig configuration.
|
|
268
317
|
*/
|
|
269
|
-
export function
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
318
|
+
export function toRpc(config) {
|
|
319
|
+
const value = from(config);
|
|
320
|
+
return {
|
|
321
|
+
owners: value.owners.map((owner) => ({
|
|
322
|
+
owner: owner.owner,
|
|
323
|
+
weight: Number(owner.weight),
|
|
324
|
+
})),
|
|
325
|
+
salt: value.salt,
|
|
326
|
+
threshold: Number(value.threshold),
|
|
327
|
+
version: Hex.fromNumber(value.version),
|
|
328
|
+
};
|
|
275
329
|
}
|
|
276
330
|
/**
|
|
277
|
-
* Converts a {@link ox#MultisigConfig.Config} to its RLP tuple form
|
|
278
|
-
* by the multisig signature `init`).
|
|
331
|
+
* Converts a {@link ox#MultisigConfig.Config} to its RLP tuple form.
|
|
279
332
|
*
|
|
280
|
-
* Tuple shape: `[salt, threshold, [[owner, weight], ...]]`. The
|
|
333
|
+
* Tuple shape: `[salt, version, threshold, [[owner, weight], ...]]`. The
|
|
281
334
|
* 32-byte `salt` encodes as a full fixed-width string; other integers use
|
|
282
335
|
* canonical RLP encoding (zero values encode as `0x`).
|
|
283
336
|
*
|
|
@@ -286,10 +339,10 @@ export function getSignPayload(value) {
|
|
|
286
339
|
* import { MultisigConfig } from 'ox/tempo'
|
|
287
340
|
*
|
|
288
341
|
* const tuple = MultisigConfig.toTuple({
|
|
289
|
-
* threshold: 1,
|
|
290
342
|
* owners: [
|
|
291
343
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
292
344
|
* ],
|
|
345
|
+
* threshold: 1,
|
|
293
346
|
* })
|
|
294
347
|
* ```
|
|
295
348
|
*
|
|
@@ -302,7 +355,13 @@ export function toTuple(config) {
|
|
|
302
355
|
// `salt` is a fixed 32-byte value: it RLP-encodes as a full 32-byte string
|
|
303
356
|
// (including the zero salt), never trimmed like an integer.
|
|
304
357
|
const salt = config.salt ? Hex.padLeft(config.salt, 32) : zeroSalt;
|
|
305
|
-
|
|
358
|
+
const version = BigInt(config.version ?? 0);
|
|
359
|
+
return [
|
|
360
|
+
salt,
|
|
361
|
+
version === 0n ? '0x' : Hex.fromNumber(version),
|
|
362
|
+
Hex.fromNumber(config.threshold),
|
|
363
|
+
owners,
|
|
364
|
+
];
|
|
306
365
|
}
|
|
307
366
|
/**
|
|
308
367
|
* Validates a native multisig {@link ox#MultisigConfig.Config}. Returns `true`
|
|
@@ -313,10 +372,10 @@ export function toTuple(config) {
|
|
|
313
372
|
* import { MultisigConfig } from 'ox/tempo'
|
|
314
373
|
*
|
|
315
374
|
* const valid = MultisigConfig.validate({
|
|
316
|
-
* threshold: 1,
|
|
317
375
|
* owners: [
|
|
318
376
|
* { owner: '0x1111111111111111111111111111111111111111', weight: 1 },
|
|
319
377
|
* ],
|
|
378
|
+
* threshold: 1,
|
|
320
379
|
* })
|
|
321
380
|
* // @log: true
|
|
322
381
|
* ```
|
|
@@ -345,4 +404,14 @@ export class InvalidConfigError extends Errors.BaseError {
|
|
|
345
404
|
});
|
|
346
405
|
}
|
|
347
406
|
}
|
|
407
|
+
/** @internal */
|
|
408
|
+
function assertVersion(version) {
|
|
409
|
+
if ((typeof version !== 'bigint' && typeof version !== 'number') ||
|
|
410
|
+
(typeof version === 'number' && !Number.isSafeInteger(version)) ||
|
|
411
|
+
BigInt(version) < 0n ||
|
|
412
|
+
BigInt(version) > maxVersion)
|
|
413
|
+
throw new InvalidConfigError({
|
|
414
|
+
reason: 'version must be an unsigned 64-bit integer',
|
|
415
|
+
});
|
|
416
|
+
}
|
|
348
417
|
//# sourceMappingURL=MultisigConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultisigConfig.js","sourceRoot":"","sources":["../../tempo/MultisigConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAE7C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAA;AAGrC,oEAAoE;AACpE,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"MultisigConfig.js","sourceRoot":"","sources":["../../tempo/MultisigConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,8 +34,8 @@ export function getHash(options) {
|
|
|
34
34
|
: KeyAuthorization_.getSignPayload(KeyAuthorization_.deserialize(options.keyAuthorization));
|
|
35
35
|
return MultisigConfig.getSignPayload({
|
|
36
36
|
account,
|
|
37
|
+
config: { version: configVersion },
|
|
37
38
|
payload,
|
|
38
|
-
version: configVersion,
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -100,20 +100,15 @@ export function serializeTransaction(operation, options) {
|
|
|
100
100
|
assertRetainedApprovals(value, approvals);
|
|
101
101
|
const signatures = SignatureEnvelope.sortMultisigApprovals({
|
|
102
102
|
account: value.account,
|
|
103
|
+
config: value.config,
|
|
103
104
|
payload: TxEnvelopeTempo.getSignPayload(envelope),
|
|
104
105
|
signatures: approvals,
|
|
105
|
-
version: value.configVersion,
|
|
106
106
|
});
|
|
107
|
-
const signature =
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
})
|
|
113
|
-
: SignatureEnvelope.from({
|
|
114
|
-
account: value.account,
|
|
115
|
-
signatures,
|
|
116
|
-
});
|
|
107
|
+
const signature = SignatureEnvelope.from({
|
|
108
|
+
account: value.account,
|
|
109
|
+
config: value.config,
|
|
110
|
+
signatures,
|
|
111
|
+
});
|
|
117
112
|
return TxEnvelopeTempo.serialize(envelope, value.transaction.startsWith(TxEnvelopeTempo.feePayerMagic)
|
|
118
113
|
? {
|
|
119
114
|
format: 'feePayer',
|
|
@@ -139,19 +134,24 @@ export function serializeTransaction(operation, options) {
|
|
|
139
134
|
export function from(operation) {
|
|
140
135
|
try {
|
|
141
136
|
const config = MultisigConfig.from(operation.config);
|
|
137
|
+
if (config.version !== operation.configVersion)
|
|
138
|
+
throw new InvalidOperationError({
|
|
139
|
+
reason: 'config.version must equal configVersion',
|
|
140
|
+
});
|
|
142
141
|
if (typeof config.threshold !== 'number' ||
|
|
143
142
|
config.owners.some((owner) => typeof owner.weight !== 'number'))
|
|
144
143
|
throw new InvalidOperationError({
|
|
145
144
|
reason: 'config threshold and owner weights must be numbers',
|
|
146
145
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
146
|
+
const value = { ...operation, config };
|
|
147
|
+
assertBase(value, config);
|
|
148
|
+
if (value.type === 'transaction')
|
|
149
|
+
assertTransaction(value);
|
|
150
|
+
else if (value.type === 'keyAuthorization')
|
|
151
|
+
assertKeyAuthorization(value, config);
|
|
152
152
|
else
|
|
153
153
|
throw new InvalidOperationError({ reason: 'unknown operation type' });
|
|
154
|
-
return
|
|
154
|
+
return value;
|
|
155
155
|
}
|
|
156
156
|
catch (cause) {
|
|
157
157
|
if (cause instanceof InvalidOperationError)
|
|
@@ -185,7 +185,11 @@ export function fromRpc(operation) {
|
|
|
185
185
|
throw new InvalidOperationError({
|
|
186
186
|
reason: 'configVersion must use canonical quantity encoding',
|
|
187
187
|
});
|
|
188
|
-
return from({
|
|
188
|
+
return from({
|
|
189
|
+
...operation,
|
|
190
|
+
config: MultisigConfig.fromRpc(operation.config),
|
|
191
|
+
configVersion,
|
|
192
|
+
});
|
|
189
193
|
}
|
|
190
194
|
catch (cause) {
|
|
191
195
|
if (cause instanceof InvalidOperationError)
|
|
@@ -211,6 +215,7 @@ export function toRpc(operation) {
|
|
|
211
215
|
const value = from(operation);
|
|
212
216
|
return {
|
|
213
217
|
...value,
|
|
218
|
+
config: MultisigConfig.toRpc(value.config),
|
|
214
219
|
configVersion: Hex.fromNumber(value.configVersion),
|
|
215
220
|
};
|
|
216
221
|
}
|
|
@@ -262,10 +267,6 @@ async function selectApprovals_internal(options, path) {
|
|
|
262
267
|
throw new InvalidApprovalError({
|
|
263
268
|
reason: `owner ${group.address} has conflicting signature types`,
|
|
264
269
|
});
|
|
265
|
-
if (nested.some((signature) => signature.init))
|
|
266
|
-
throw new InvalidApprovalError({
|
|
267
|
-
reason: `nested multisig owner ${group.address} cannot carry init`,
|
|
268
|
-
});
|
|
269
270
|
if (path.length >= MultisigConfig.maxNestingDepth ||
|
|
270
271
|
path.includes(group.address.toLowerCase()))
|
|
271
272
|
throw new InvalidApprovalError({
|
|
@@ -276,14 +277,19 @@ async function selectApprovals_internal(options, path) {
|
|
|
276
277
|
reason: `nested multisig owner ${group.address} requires a config resolver`,
|
|
277
278
|
});
|
|
278
279
|
const resolved = await options.resolveConfig({ account: group.address });
|
|
280
|
+
const config = MultisigConfig.from(resolved.config);
|
|
281
|
+
if (config.version !== resolved.version)
|
|
282
|
+
throw new InvalidApprovalError({
|
|
283
|
+
reason: `resolved config.version must equal version for nested multisig owner ${group.address}`,
|
|
284
|
+
});
|
|
279
285
|
const selected = await selectApprovals_internal({
|
|
280
286
|
account: group.address,
|
|
281
287
|
approvals: nested.flatMap((signature) => signature.signatures.map((approval) => SignatureEnvelope.serialize(approval))),
|
|
282
|
-
config
|
|
288
|
+
config,
|
|
283
289
|
hash: MultisigConfig.getSignPayload({
|
|
284
290
|
account: group.address,
|
|
291
|
+
config,
|
|
285
292
|
payload: options.hash,
|
|
286
|
-
version: resolved.version,
|
|
287
293
|
}),
|
|
288
294
|
resolveConfig: options.resolveConfig,
|
|
289
295
|
}, [...path, group.address.toLowerCase()]);
|
|
@@ -291,6 +297,7 @@ async function selectApprovals_internal(options, path) {
|
|
|
291
297
|
address: group.address,
|
|
292
298
|
signature: SignatureEnvelope.serialize(SignatureEnvelope.from({
|
|
293
299
|
account: group.address,
|
|
300
|
+
config,
|
|
294
301
|
signatures: selected.approvals.map((approval) => SignatureEnvelope.from(approval)),
|
|
295
302
|
})),
|
|
296
303
|
});
|
|
@@ -299,6 +306,7 @@ async function selectApprovals_internal(options, path) {
|
|
|
299
306
|
address: group.address,
|
|
300
307
|
signature: SignatureEnvelope.serialize(SignatureEnvelope.from({
|
|
301
308
|
account: group.address,
|
|
309
|
+
config,
|
|
302
310
|
signatures: selected.selectedApprovals.map((approval) => SignatureEnvelope.from(approval)),
|
|
303
311
|
})),
|
|
304
312
|
weight: group.weight,
|
|
@@ -422,7 +430,7 @@ function assertBase(operation, config) {
|
|
|
422
430
|
if (typeof approval !== 'string' ||
|
|
423
431
|
!Hex.validate(approval, { strict: true }))
|
|
424
432
|
throw new InvalidOperationError({ reason: 'approval is invalid' });
|
|
425
|
-
const signature = assertApproval(operation.account, approval);
|
|
433
|
+
const signature = assertApproval(operation.account, approval, config);
|
|
426
434
|
const address = SignatureEnvelope.extractAddress({
|
|
427
435
|
payload: operation.hash,
|
|
428
436
|
signature,
|
|
@@ -586,13 +594,9 @@ function assertKeyAuthorization(operation, config) {
|
|
|
586
594
|
reason: 'key authorization signatureCount does not match its signature',
|
|
587
595
|
});
|
|
588
596
|
assertSelectedApprovals(operation, signature.signatures, authorization);
|
|
589
|
-
if (
|
|
597
|
+
if (!sameConfig(signature.config, config))
|
|
590
598
|
throw new InvalidOperationError({
|
|
591
|
-
reason: 'key authorization
|
|
592
|
-
});
|
|
593
|
-
if (signature.init && !sameConfig(signature.init, config))
|
|
594
|
-
throw new InvalidOperationError({
|
|
595
|
-
reason: 'key authorization bootstrap config does not match',
|
|
599
|
+
reason: 'key authorization config does not match',
|
|
596
600
|
});
|
|
597
601
|
}
|
|
598
602
|
assertOperationHash(operation, KeyAuthorization_.getSignPayload(authorization));
|
|
@@ -607,10 +611,11 @@ function assertKeyAuthorization(operation, config) {
|
|
|
607
611
|
*
|
|
608
612
|
* @internal
|
|
609
613
|
*/
|
|
610
|
-
function assertApproval(account, serialized) {
|
|
614
|
+
function assertApproval(account, serialized, config) {
|
|
611
615
|
const approval = SignatureEnvelope.deserialize(serialized);
|
|
612
616
|
SignatureEnvelope.assert({
|
|
613
617
|
account,
|
|
618
|
+
config,
|
|
614
619
|
signatures: [approval],
|
|
615
620
|
type: 'multisig',
|
|
616
621
|
});
|
|
@@ -652,8 +657,8 @@ function assertSelectedApprovals(operation, selected, authorization) {
|
|
|
652
657
|
}
|
|
653
658
|
const digest = MultisigConfig.getSignPayload({
|
|
654
659
|
account: operation.account,
|
|
660
|
+
config: operation.config,
|
|
655
661
|
payload: KeyAuthorization_.getSignPayload(authorization),
|
|
656
|
-
version: operation.configVersion,
|
|
657
662
|
});
|
|
658
663
|
const addresses = selected.map((signature) => SignatureEnvelope.extractAddress({ payload: digest, signature }));
|
|
659
664
|
for (let index = 1; index < addresses.length; index++) {
|
|
@@ -680,7 +685,8 @@ function includesApproval(retained, selected) {
|
|
|
680
685
|
SignatureEnvelope.serialize(selected).toLowerCase());
|
|
681
686
|
if (retained.account.toLowerCase() !== selected.account.toLowerCase())
|
|
682
687
|
return false;
|
|
683
|
-
|
|
688
|
+
if (!sameConfig(retained.config, selected.config))
|
|
689
|
+
return false;
|
|
684
690
|
let index = 0;
|
|
685
691
|
for (const approval of selected.signatures) {
|
|
686
692
|
while (index < retained.signatures.length &&
|
|
@@ -714,8 +720,8 @@ function isWeightReachable(weights, signatureCount, weight) {
|
|
|
714
720
|
function assertOperationHash(operation, payload) {
|
|
715
721
|
const hash = MultisigConfig.getSignPayload({
|
|
716
722
|
account: operation.account,
|
|
723
|
+
config: operation.config,
|
|
717
724
|
payload,
|
|
718
|
-
version: operation.configVersion,
|
|
719
725
|
});
|
|
720
726
|
if (hash.toLowerCase() !== operation.hash.toLowerCase())
|
|
721
727
|
throw new InvalidOperationError({
|
|
@@ -743,6 +749,7 @@ function sameConfig(a, b) {
|
|
|
743
749
|
const configB = MultisigConfig.from(b);
|
|
744
750
|
return (Hex.isEqual(configA.salt ?? MultisigConfig.zeroSalt, configB.salt ?? MultisigConfig.zeroSalt) &&
|
|
745
751
|
configA.threshold === configB.threshold &&
|
|
752
|
+
configA.version === configB.version &&
|
|
746
753
|
configA.owners.length === configB.owners.length &&
|
|
747
754
|
configA.owners.every((owner, index) => {
|
|
748
755
|
const other = configB.owners[index];
|