ox 0.14.40 → 0.14.41
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 +6 -0
- package/_cjs/tempo/MultisigOperation.js +27 -44
- package/_cjs/tempo/MultisigOperation.js.map +1 -1
- package/_cjs/tempo/SignatureEnvelope.js +5 -2
- package/_cjs/tempo/SignatureEnvelope.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/tempo/MultisigOperation.js +28 -47
- package/_esm/tempo/MultisigOperation.js.map +1 -1
- package/_esm/tempo/SignatureEnvelope.js +5 -2
- package/_esm/tempo/SignatureEnvelope.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/tempo/MultisigOperation.d.ts +4 -25
- package/_types/tempo/MultisigOperation.d.ts.map +1 -1
- package/_types/tempo/SignatureEnvelope.d.ts +3 -3
- package/_types/tempo/SignatureEnvelope.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/package.json +1 -1
- package/tempo/KeyAuthorization.test-d.ts +1 -1
- package/tempo/MultisigOperation.test-d.ts +0 -6
- package/tempo/MultisigOperation.test.ts +142 -169
- package/tempo/MultisigOperation.ts +37 -82
- package/tempo/SignatureEnvelope.test-d.ts +4 -4
- package/tempo/SignatureEnvelope.test.ts +2 -2
- package/tempo/SignatureEnvelope.ts +9 -5
- package/version.ts +1 -1
|
@@ -15,14 +15,10 @@ export type Base<quantity = bigint> = {
|
|
|
15
15
|
approvals: readonly Hex.Hex[]
|
|
16
16
|
/** Root configuration used to verify approvals. */
|
|
17
17
|
config: MultisigConfig.Config<quantity>
|
|
18
|
-
/** Root configuration version. */
|
|
19
|
-
configVersion: quantity
|
|
20
18
|
/** Unix creation time in milliseconds. */
|
|
21
19
|
createdAt: number
|
|
22
20
|
/** Deterministic multisig operation hash. */
|
|
23
21
|
hash: Hex.Hex
|
|
24
|
-
/** Whether the operation initializes the root multisig account. */
|
|
25
|
-
init: boolean
|
|
26
22
|
/** Number of approvals selected for quorum evaluation. */
|
|
27
23
|
signatureCount: number
|
|
28
24
|
/** Required root owner weight. */
|
|
@@ -73,9 +69,6 @@ export type KeyAuthorizationRpc = KeyAuthorizationOperation<Hex.Hex>
|
|
|
73
69
|
/** JSON-RPC multisig operation. */
|
|
74
70
|
export type Rpc = Operation<Hex.Hex>
|
|
75
71
|
|
|
76
|
-
/** Maximum supported multisig configuration version. */
|
|
77
|
-
const maxConfigVersion = 2n ** 64n - 1n
|
|
78
|
-
|
|
79
72
|
/**
|
|
80
73
|
* Derives the deterministic hash for a multisig operation.
|
|
81
74
|
*
|
|
@@ -86,7 +79,7 @@ const maxConfigVersion = 2n ** 64n - 1n
|
|
|
86
79
|
*
|
|
87
80
|
* const hash = MultisigOperation.getHash({
|
|
88
81
|
* account,
|
|
89
|
-
*
|
|
82
|
+
* config,
|
|
90
83
|
* transaction,
|
|
91
84
|
* type: 'transaction',
|
|
92
85
|
* })
|
|
@@ -96,7 +89,7 @@ const maxConfigVersion = 2n ** 64n - 1n
|
|
|
96
89
|
* @returns The operation hash signed by each owner.
|
|
97
90
|
*/
|
|
98
91
|
export function getHash(options: getHash.Options): Hex.Hex {
|
|
99
|
-
const { account,
|
|
92
|
+
const { account, config } = options
|
|
100
93
|
const payload =
|
|
101
94
|
options.type === 'transaction'
|
|
102
95
|
? TxEnvelopeTempo.getSignPayload(
|
|
@@ -109,7 +102,7 @@ export function getHash(options: getHash.Options): Hex.Hex {
|
|
|
109
102
|
)
|
|
110
103
|
return MultisigConfig.getSignPayload({
|
|
111
104
|
account,
|
|
112
|
-
config
|
|
105
|
+
config,
|
|
113
106
|
payload,
|
|
114
107
|
})
|
|
115
108
|
}
|
|
@@ -119,8 +112,8 @@ export declare namespace getHash {
|
|
|
119
112
|
export type Options = {
|
|
120
113
|
/** Root multisig account. */
|
|
121
114
|
account: Address.Address
|
|
122
|
-
/**
|
|
123
|
-
|
|
115
|
+
/** Complete root multisig configuration witness. */
|
|
116
|
+
config: MultisigConfig.Config
|
|
124
117
|
} & (
|
|
125
118
|
| {
|
|
126
119
|
/** Canonical serialized key authorization. */
|
|
@@ -163,7 +156,6 @@ export declare namespace getHash {
|
|
|
163
156
|
* approvals,
|
|
164
157
|
* config,
|
|
165
158
|
* hash,
|
|
166
|
-
* resolveConfig,
|
|
167
159
|
* })
|
|
168
160
|
* ```
|
|
169
161
|
*
|
|
@@ -173,18 +165,25 @@ export declare namespace getHash {
|
|
|
173
165
|
export async function selectApprovals(
|
|
174
166
|
options: selectApprovals.Options,
|
|
175
167
|
): Promise<selectApprovals.ReturnValue> {
|
|
176
|
-
const { account, approvals, hash
|
|
168
|
+
const { account, approvals, hash } = options
|
|
177
169
|
if (!Address.validate(account) || Hex.toBigInt(account) === 0n)
|
|
178
170
|
throw new InvalidApprovalError({ reason: 'account is invalid' })
|
|
179
171
|
if (!Hash.validate(hash))
|
|
180
172
|
throw new InvalidApprovalError({ reason: 'hash is invalid' })
|
|
173
|
+
const config = MultisigConfig.from(options.config)
|
|
174
|
+
if (
|
|
175
|
+
config.version === 0n &&
|
|
176
|
+
!Address.isEqual(MultisigConfig.getAddress(config), account)
|
|
177
|
+
)
|
|
178
|
+
throw new InvalidApprovalError({
|
|
179
|
+
reason: 'initial config does not derive the root multisig account',
|
|
180
|
+
})
|
|
181
181
|
return selectApprovals_internal(
|
|
182
182
|
{
|
|
183
183
|
account,
|
|
184
184
|
approvals,
|
|
185
|
-
config
|
|
185
|
+
config,
|
|
186
186
|
hash,
|
|
187
|
-
resolveConfig,
|
|
188
187
|
},
|
|
189
188
|
[account.toLowerCase()],
|
|
190
189
|
)
|
|
@@ -201,27 +200,6 @@ export declare namespace selectApprovals {
|
|
|
201
200
|
config: MultisigConfig.Config
|
|
202
201
|
/** Deterministic operation hash approved by root owners. */
|
|
203
202
|
hash: Hex.Hex
|
|
204
|
-
/** Resolves the current configuration of a nested multisig owner. */
|
|
205
|
-
resolveConfig?: ResolveConfig | undefined
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/** Resolves an initialized nested multisig configuration. */
|
|
209
|
-
export type ResolveConfig = (
|
|
210
|
-
options: ResolveConfigOptions,
|
|
211
|
-
) => ResolvedConfig | Promise<ResolvedConfig>
|
|
212
|
-
|
|
213
|
-
/** Nested multisig configuration lookup parameters. */
|
|
214
|
-
export type ResolveConfigOptions = {
|
|
215
|
-
/** Nested multisig account. */
|
|
216
|
-
account: Address.Address
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/** Resolved nested multisig configuration. */
|
|
220
|
-
export type ResolvedConfig = {
|
|
221
|
-
/** Current nested multisig configuration. */
|
|
222
|
-
config: MultisigConfig.Config
|
|
223
|
-
/** Current nested multisig configuration version. */
|
|
224
|
-
version: bigint
|
|
225
203
|
}
|
|
226
204
|
|
|
227
205
|
/** Result of validating and selecting approvals. */
|
|
@@ -339,10 +317,6 @@ export function from<const operation extends Operation>(
|
|
|
339
317
|
): from.ReturnValue<operation> {
|
|
340
318
|
try {
|
|
341
319
|
const config = MultisigConfig.from(operation.config)
|
|
342
|
-
if (config.version !== operation.configVersion)
|
|
343
|
-
throw new InvalidOperationError({
|
|
344
|
-
reason: 'config.version must equal configVersion',
|
|
345
|
-
})
|
|
346
320
|
if (
|
|
347
321
|
typeof config.threshold !== 'number' ||
|
|
348
322
|
config.owners.some((owner) => typeof owner.weight !== 'number')
|
|
@@ -392,22 +366,19 @@ export function fromRpc<const operation extends Rpc>(
|
|
|
392
366
|
operation: operation,
|
|
393
367
|
): fromRpc.ReturnValue<operation> {
|
|
394
368
|
try {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
!Hex.validate(operation.configVersion)
|
|
398
|
-
)
|
|
369
|
+
const version = operation.config?.version
|
|
370
|
+
if (typeof version !== 'string' || !Hex.validate(version))
|
|
399
371
|
throw new InvalidOperationError({
|
|
400
|
-
reason: '
|
|
372
|
+
reason: 'config.version must be a hexadecimal quantity',
|
|
401
373
|
})
|
|
402
|
-
const
|
|
403
|
-
if (Hex.fromNumber(
|
|
374
|
+
const version_ = Hex.toBigInt(version)
|
|
375
|
+
if (Hex.fromNumber(version_) !== version)
|
|
404
376
|
throw new InvalidOperationError({
|
|
405
|
-
reason: '
|
|
377
|
+
reason: 'config.version must use canonical quantity encoding',
|
|
406
378
|
})
|
|
407
379
|
return from({
|
|
408
380
|
...operation,
|
|
409
381
|
config: MultisigConfig.fromRpc(operation.config),
|
|
410
|
-
configVersion,
|
|
411
382
|
} as Operation) as never
|
|
412
383
|
} catch (cause) {
|
|
413
384
|
if (cause instanceof InvalidOperationError) throw cause
|
|
@@ -447,7 +418,6 @@ export function toRpc<const operation extends Operation>(
|
|
|
447
418
|
return {
|
|
448
419
|
...value,
|
|
449
420
|
config: MultisigConfig.toRpc(value.config),
|
|
450
|
-
configVersion: Hex.fromNumber(value.configVersion),
|
|
451
421
|
} as never
|
|
452
422
|
}
|
|
453
423
|
|
|
@@ -459,7 +429,7 @@ export declare namespace toRpc {
|
|
|
459
429
|
: KeyAuthorizationRpc
|
|
460
430
|
|
|
461
431
|
/** Error type for `toRpc`. */
|
|
462
|
-
export type ErrorType = from.ErrorType |
|
|
432
|
+
export type ErrorType = from.ErrorType | MultisigConfig.toRpc.ErrorType
|
|
463
433
|
}
|
|
464
434
|
|
|
465
435
|
/**
|
|
@@ -525,15 +495,17 @@ async function selectApprovals_internal(
|
|
|
525
495
|
throw new InvalidApprovalError({
|
|
526
496
|
reason: `nested multisig owner ${group.address} is invalid`,
|
|
527
497
|
})
|
|
528
|
-
|
|
498
|
+
const config = MultisigConfig.from(nested[0]!.config)
|
|
499
|
+
if (nested.some((signature) => !sameConfig(signature.config, config)))
|
|
529
500
|
throw new InvalidApprovalError({
|
|
530
|
-
reason: `nested multisig owner ${group.address}
|
|
501
|
+
reason: `nested multisig owner ${group.address} has conflicting config witnesses`,
|
|
531
502
|
})
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
503
|
+
if (
|
|
504
|
+
config.version === 0n &&
|
|
505
|
+
!Address.isEqual(MultisigConfig.getAddress(config), group.address)
|
|
506
|
+
)
|
|
535
507
|
throw new InvalidApprovalError({
|
|
536
|
-
reason: `
|
|
508
|
+
reason: `initial config does not derive nested multisig owner ${group.address}`,
|
|
537
509
|
})
|
|
538
510
|
const selected = await selectApprovals_internal(
|
|
539
511
|
{
|
|
@@ -549,7 +521,6 @@ async function selectApprovals_internal(
|
|
|
549
521
|
config,
|
|
550
522
|
payload: options.hash,
|
|
551
523
|
}),
|
|
552
|
-
resolveConfig: options.resolveConfig,
|
|
553
524
|
},
|
|
554
525
|
[...path, group.address.toLowerCase()],
|
|
555
526
|
)
|
|
@@ -691,16 +662,6 @@ function assertBase(operation: Operation, config: MultisigConfig.Config): void {
|
|
|
691
662
|
throw new InvalidOperationError({ reason: 'account cannot be zero' })
|
|
692
663
|
if (!Hash.validate(operation.hash))
|
|
693
664
|
throw new InvalidOperationError({ reason: 'hash is invalid' })
|
|
694
|
-
if (typeof operation.init !== 'boolean')
|
|
695
|
-
throw new InvalidOperationError({ reason: 'init must be a boolean' })
|
|
696
|
-
if (
|
|
697
|
-
typeof operation.configVersion !== 'bigint' ||
|
|
698
|
-
operation.configVersion < 0n ||
|
|
699
|
-
operation.configVersion > maxConfigVersion
|
|
700
|
-
)
|
|
701
|
-
throw new InvalidOperationError({
|
|
702
|
-
reason: 'configVersion must be an unsigned 64-bit integer',
|
|
703
|
-
})
|
|
704
665
|
assertInteger(operation.createdAt, 'createdAt')
|
|
705
666
|
assertInteger(operation.updatedAt, 'updatedAt')
|
|
706
667
|
if (operation.updatedAt < operation.createdAt)
|
|
@@ -780,19 +741,13 @@ function assertBase(operation: Operation, config: MultisigConfig.Config): void {
|
|
|
780
741
|
reason:
|
|
781
742
|
'weight is not reachable by signatureCount retained owner approvals',
|
|
782
743
|
})
|
|
783
|
-
if (
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
operation.account.toLowerCase()
|
|
791
|
-
)
|
|
792
|
-
throw new InvalidOperationError({
|
|
793
|
-
reason: 'bootstrap config does not derive the operation account',
|
|
794
|
-
})
|
|
795
|
-
}
|
|
744
|
+
if (
|
|
745
|
+
config.version === 0n &&
|
|
746
|
+
!Address.isEqual(MultisigConfig.getAddress(config), operation.account)
|
|
747
|
+
)
|
|
748
|
+
throw new InvalidOperationError({
|
|
749
|
+
reason: 'initial config does not derive the operation account',
|
|
750
|
+
})
|
|
796
751
|
}
|
|
797
752
|
|
|
798
753
|
/**
|
|
@@ -37,11 +37,11 @@ test('toRpc preserves the signature type', () => {
|
|
|
37
37
|
test('MultisigRpc carries one complete witness shape', () => {
|
|
38
38
|
const rpc = {
|
|
39
39
|
account: '0x1111111111111111111111111111111111111111',
|
|
40
|
-
config:
|
|
40
|
+
config: { ...config, version: 0 },
|
|
41
41
|
signatures: [signatureRpc],
|
|
42
42
|
} as const satisfies SignatureEnvelope.MultisigRpc
|
|
43
43
|
|
|
44
|
-
expectTypeOf(rpc.config).toMatchTypeOf<MultisigConfig.
|
|
44
|
+
expectTypeOf(rpc.config).toMatchTypeOf<MultisigConfig.Config<number>>()
|
|
45
45
|
expectTypeOf(rpc.signatures).toMatchTypeOf<
|
|
46
46
|
readonly SignatureEnvelope.SignatureEnvelopeRpc[]
|
|
47
47
|
>()
|
|
@@ -92,7 +92,7 @@ test('MultisigRpc rejects old witness shapes', () => {
|
|
|
92
92
|
|
|
93
93
|
const serialized = {
|
|
94
94
|
account: '0x1111111111111111111111111111111111111111',
|
|
95
|
-
config:
|
|
95
|
+
config: { ...config, version: 0 },
|
|
96
96
|
signatures: ['0x1234'],
|
|
97
97
|
} as const
|
|
98
98
|
// @ts-expect-error Owner approvals use structured RPC envelopes.
|
|
@@ -100,7 +100,7 @@ test('MultisigRpc rejects old witness shapes', () => {
|
|
|
100
100
|
|
|
101
101
|
const tagged = {
|
|
102
102
|
account: '0x1111111111111111111111111111111111111111',
|
|
103
|
-
config:
|
|
103
|
+
config: { ...config, version: 0 },
|
|
104
104
|
signatures: [signatureRpc],
|
|
105
105
|
type: 'multisig',
|
|
106
106
|
} as const
|
|
@@ -3035,7 +3035,7 @@ describe('multisig', () => {
|
|
|
3035
3035
|
],
|
|
3036
3036
|
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
3037
3037
|
"threshold": 1,
|
|
3038
|
-
"version":
|
|
3038
|
+
"version": 1,
|
|
3039
3039
|
},
|
|
3040
3040
|
"signatures": [
|
|
3041
3041
|
{
|
|
@@ -3057,7 +3057,7 @@ describe('multisig', () => {
|
|
|
3057
3057
|
],
|
|
3058
3058
|
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
3059
3059
|
"threshold": 1,
|
|
3060
|
-
"version":
|
|
3060
|
+
"version": 0,
|
|
3061
3061
|
},
|
|
3062
3062
|
"signatures": [
|
|
3063
3063
|
{
|
|
@@ -245,7 +245,7 @@ export type MultisigRpc = {
|
|
|
245
245
|
/** Native multisig account address. */
|
|
246
246
|
account: Address.Address
|
|
247
247
|
/** Complete applicable multisig configuration witness. */
|
|
248
|
-
config: MultisigConfig.
|
|
248
|
+
config: MultisigConfig.Config<number>
|
|
249
249
|
/** Structured owner approvals. */
|
|
250
250
|
signatures: readonly SignatureEnvelopeRpc[]
|
|
251
251
|
/** Multisig RPC signatures are untagged. */
|
|
@@ -1229,7 +1229,7 @@ export function fromRpc(envelope: SignatureEnvelopeRpc): SignatureEnvelope {
|
|
|
1229
1229
|
const multisig = envelope as MultisigRpc
|
|
1230
1230
|
const result = {
|
|
1231
1231
|
account: multisig.account,
|
|
1232
|
-
config: MultisigConfig.
|
|
1232
|
+
config: MultisigConfig.from(multisig.config),
|
|
1233
1233
|
signatures: multisig.signatures.map((signature) => fromRpc(signature)),
|
|
1234
1234
|
type: 'multisig',
|
|
1235
1235
|
} satisfies Multisig
|
|
@@ -1245,7 +1245,7 @@ export declare namespace fromRpc {
|
|
|
1245
1245
|
| assert.ErrorType
|
|
1246
1246
|
| CoercionError
|
|
1247
1247
|
| InvalidSerializedError
|
|
1248
|
-
| MultisigConfig.
|
|
1248
|
+
| MultisigConfig.assert.ErrorType
|
|
1249
1249
|
| Signature.fromRpc.ErrorType
|
|
1250
1250
|
| Errors.GlobalErrorType
|
|
1251
1251
|
}
|
|
@@ -1614,7 +1614,10 @@ export function toRpc<const envelope extends toRpc.Input>(
|
|
|
1614
1614
|
assert(multisig)
|
|
1615
1615
|
return {
|
|
1616
1616
|
account: multisig.account,
|
|
1617
|
-
config:
|
|
1617
|
+
config: {
|
|
1618
|
+
...multisig.config,
|
|
1619
|
+
version: Hex.toNumber(Hex.fromNumber(multisig.config.version)),
|
|
1620
|
+
},
|
|
1618
1621
|
signatures: multisig.signatures.map((signature) => toRpc(signature)),
|
|
1619
1622
|
} as never
|
|
1620
1623
|
}
|
|
@@ -1643,7 +1646,8 @@ export declare namespace toRpc {
|
|
|
1643
1646
|
type ErrorType =
|
|
1644
1647
|
| assert.ErrorType
|
|
1645
1648
|
| CoercionError
|
|
1646
|
-
|
|
|
1649
|
+
| Hex.fromNumber.ErrorType
|
|
1650
|
+
| Hex.toNumber.ErrorType
|
|
1647
1651
|
| Signature.toRpc.ErrorType
|
|
1648
1652
|
| Errors.GlobalErrorType
|
|
1649
1653
|
}
|
package/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** @internal */
|
|
2
|
-
export const version = '0.14.
|
|
2
|
+
export const version = '0.14.41'
|