Skip to content

Commit 1b640a2

Browse files
authored
defines MultisigHardwareSigner for Ledger multisig keys (#5366)
a multisig account generated using a Ledger device will have a access to the participant identity, but not the secret or keyPackage uses a separate interface for MultisigHardwareSigner to cover this case and expands the MultisigKeys type to cover this interface the distinct interface allows us to store multisig keys for the Ledger case without a database migration for existing multisig keys
1 parent 18f1bea commit 1b640a2

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

ironfish/src/wallet/interfaces/multisigKeys.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@ export interface MultisigSigner {
88
publicKeyPackage: string
99
}
1010

11+
export interface MultisigHardwareSigner {
12+
identity: string
13+
publicKeyPackage: string
14+
}
15+
1116
export interface MultisigCoordinator {
1217
publicKeyPackage: string
1318
}
1419

15-
export type MultisigKeys = MultisigSigner | MultisigCoordinator
20+
export type MultisigKeys = MultisigSigner | MultisigHardwareSigner | MultisigCoordinator

ironfish/src/wallet/walletdb/multiSigKeys.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
/* This Source Code Form is subject to the terms of the Mozilla Public
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4-
import { MultisigCoordinator, MultisigSigner } from '../interfaces/multisigKeys'
4+
import {
5+
MultisigCoordinator,
6+
MultisigHardwareSigner,
7+
MultisigSigner,
8+
} from '../interfaces/multisigKeys'
59
import { MultisigKeysEncoding } from './multisigKeys'
610

711
describe('multisigKeys encoder', () => {
@@ -32,4 +36,18 @@ describe('multisigKeys encoder', () => {
3236
expect(deserializedValue).toEqual(value)
3337
})
3438
})
39+
40+
describe('with a hardware multisig', () => {
41+
it('serializes the value into a buffer and deserialized to the original value', () => {
42+
const encoder = new MultisigKeysEncoding()
43+
44+
const value: MultisigHardwareSigner = {
45+
publicKeyPackage: 'aaaa',
46+
identity: 'c0ffee',
47+
}
48+
const buffer = encoder.serialize(value)
49+
const deserializedValue = encoder.deserialize(buffer)
50+
expect(deserializedValue).toEqual(value)
51+
})
52+
})
3553
})

ironfish/src/wallet/walletdb/multisigKeys.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,27 @@
44
import bufio from 'bufio'
55
import { Assert } from '../../assert'
66
import { IDatabaseEncoding } from '../../storage'
7-
import { MultisigKeys, MultisigSigner } from '../interfaces/multisigKeys'
7+
import {
8+
MultisigHardwareSigner,
9+
MultisigKeys,
10+
MultisigSigner,
11+
} from '../interfaces/multisigKeys'
812

913
export class MultisigKeysEncoding implements IDatabaseEncoding<MultisigKeys> {
1014
serialize(value: MultisigKeys): Buffer {
1115
const bw = bufio.write(this.getSize(value))
1216

1317
let flags = 0
1418
flags |= Number(!!isSignerMultisig(value)) << 0
19+
flags |= Number(!!isHardwareSignerMultisig(value)) << 1
1520
bw.writeU8(flags)
1621

1722
bw.writeVarBytes(Buffer.from(value.publicKeyPackage, 'hex'))
1823
if (isSignerMultisig(value)) {
1924
bw.writeVarBytes(Buffer.from(value.secret, 'hex'))
2025
bw.writeVarBytes(Buffer.from(value.keyPackage, 'hex'))
26+
} else if (isHardwareSignerMultisig(value)) {
27+
bw.writeVarBytes(Buffer.from(value.identity, 'hex'))
2128
}
2229

2330
return bw.render()
@@ -28,6 +35,7 @@ export class MultisigKeysEncoding implements IDatabaseEncoding<MultisigKeys> {
2835

2936
const flags = reader.readU8()
3037
const isSigner = flags & (1 << 0)
38+
const isHardwareSigner = flags & (1 << 1)
3139

3240
const publicKeyPackage = reader.readVarBytes().toString('hex')
3341
if (isSigner) {
@@ -38,6 +46,12 @@ export class MultisigKeysEncoding implements IDatabaseEncoding<MultisigKeys> {
3846
secret,
3947
keyPackage,
4048
}
49+
} else if (isHardwareSigner) {
50+
const identity = reader.readVarBytes().toString('hex')
51+
return {
52+
publicKeyPackage,
53+
identity,
54+
}
4155
}
4256

4357
return {
@@ -53,6 +67,8 @@ export class MultisigKeysEncoding implements IDatabaseEncoding<MultisigKeys> {
5367
if (isSignerMultisig(value)) {
5468
size += bufio.sizeVarString(value.secret, 'hex')
5569
size += bufio.sizeVarString(value.keyPackage, 'hex')
70+
} else if (isHardwareSignerMultisig(value)) {
71+
size += bufio.sizeVarString(value.identity, 'hex')
5672
}
5773

5874
return size
@@ -63,6 +79,12 @@ export function isSignerMultisig(multisigKeys: MultisigKeys): multisigKeys is Mu
6379
return 'keyPackage' in multisigKeys && 'secret' in multisigKeys
6480
}
6581

82+
export function isHardwareSignerMultisig(
83+
multisigKeys: MultisigKeys,
84+
): multisigKeys is MultisigHardwareSigner {
85+
return 'identity' in multisigKeys
86+
}
87+
6688
export function AssertIsSignerMultisig(
6789
multisigKeys: MultisigKeys,
6890
): asserts multisigKeys is MultisigSigner {

0 commit comments

Comments
 (0)