Skip to content

Commit 1ab8142

Browse files
committed
fix(redpallas): adapt DKG to wasm-mps 1.15.0 API
wasm-mps 1.15.0 changed the RedPallas DKG bindings: - redpallas_dkg_round2_process no longer takes a derivationSeed and returns RedPallasShare directly (MsgDerivationInit removed) - handleIncomingMessages drops the derivationSeed param - generateRedPallasDKGKeyShares drops its derivationSeed param Update dkg.ts, util.ts, and tests accordingly; remove the obsolete 'derivationSeed required for round 2' test. Ticket: WCI-1614
1 parent 1b35954 commit 1ab8142

4 files changed

Lines changed: 23 additions & 86 deletions

File tree

modules/sdk-lib-mpc/src/tss/redpallas-mps/dkg.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { MsgDerivationInit, MsgState } from '@bitgo/wasm-mps';
1+
import type { MsgState } from '@bitgo/wasm-mps';
22
import { encode } from 'cbor-x';
33
import crypto from 'crypto';
44
import { DeserializedMessage, DeserializedMessages, RedPallasDkgState, RedPallasReducedKeyShare } from './types';
@@ -149,10 +149,8 @@ export class RedPallasDKG {
149149
* matching the ordering expected by @bitgo/wasm-mps.
150150
*
151151
* @param messagesForIthRound - All n messages for this round (including own).
152-
* @param derivationSeed - Required only when advancing WaitMsg2 -> Complete (round2): a
153-
* 32-byte seed consumed by the subsequent, platform-side-only derivation process.
154152
*/
155-
handleIncomingMessages(messagesForIthRound: DeserializedMessages, derivationSeed?: Buffer): DeserializedMessages {
153+
handleIncomingMessages(messagesForIthRound: DeserializedMessages): DeserializedMessages {
156154
if (this.dkgState === RedPallasDkgState.Complete) {
157155
throw Error('DKG session already completed');
158156
}
@@ -190,12 +188,9 @@ export class RedPallasDKG {
190188
}
191189

192190
if (this.dkgState === RedPallasDkgState.WaitMsg2) {
193-
if (!derivationSeed || derivationSeed.length !== 32) {
194-
throw Error('Missing or invalid derivationSeed: must be 32 bytes (required for round2)');
195-
}
196-
let result: MsgDerivationInit;
191+
let result;
197192
try {
198-
result = wasm.redpallas_dkg_round2_process(otherMsgs, this.dkgStateBytes!, derivationSeed);
193+
result = wasm.redpallas_dkg_round2_process(otherMsgs, this.dkgStateBytes!);
199194
} catch (err) {
200195
throw new Error(`Error while creating messages from party ${this.partyIdx}, round ${this.dkgState}: ${err}`);
201196
}

modules/sdk-lib-mpc/src/tss/redpallas-mps/util.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,8 @@ function validateSeed(seed?: RedPallasDKGPartySeed): RedPallasDKGPartySeed {
2929
/**
3030
* Runs a full 3-party (2-of-3) RedPallas DKG in-process. See `RedPallasDKGPartySeed`.
3131
* Mirrors `generateEdDsaDKGKeyShares` in `../eddsa-mps/util.ts`.
32-
*
33-
* @param derivationSeed - 32-byte seed consumed by round2 for the (platform-side-only)
34-
* subsequent derivation process. Must be the same value across all three parties.
3532
*/
3633
export async function generateRedPallasDKGKeyShares(
37-
derivationSeed: Buffer,
3834
seedUser?: RedPallasDKGPartySeed,
3935
seedBackup?: RedPallasDKGPartySeed,
4036
seedBitgo?: RedPallasDKGPartySeed
@@ -67,10 +63,9 @@ export async function generateRedPallasDKGKeyShares(
6763
...bitgo.handleIncomingMessages(r1Messages),
6864
];
6965

70-
user.handleIncomingMessages(r2Messages, derivationSeed);
71-
backup.handleIncomingMessages(r2Messages, derivationSeed);
72-
bitgo.handleIncomingMessages(r2Messages, derivationSeed);
73-
66+
user.handleIncomingMessages(r2Messages);
67+
backup.handleIncomingMessages(r2Messages);
68+
bitgo.handleIncomingMessages(r2Messages);
7469
return [user, backup, bitgo];
7570
}
7671

modules/sdk-lib-mpc/test/unit/tss/redpallas/dkg.ts

Lines changed: 11 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,21 @@ function makeKeypair(seed?: Buffer) {
1111
return { privKey, pubKey };
1212
}
1313

14-
function makeDerivationSeed(): Buffer {
15-
return crypto.randomBytes(32);
16-
}
17-
1814
describe('RedPallas MPS DKG', function () {
1915
let user: RedPallasMPSDkg.RedPallasDKG;
2016
let backup: RedPallasMPSDkg.RedPallasDKG;
2117
let bitgo: RedPallasMPSDkg.RedPallasDKG;
2218
let userKP: { privKey: Buffer; pubKey: Buffer };
2319
let backupKP: { privKey: Buffer; pubKey: Buffer };
2420
let bitgoKP: { privKey: Buffer; pubKey: Buffer };
25-
let derivationSeed: Buffer;
2621

2722
beforeEach(function () {
2823
user = new RedPallasMPSDkg.RedPallasDKG(3, 2, 0);
2924
backup = new RedPallasMPSDkg.RedPallasDKG(3, 2, 1);
3025
bitgo = new RedPallasMPSDkg.RedPallasDKG(3, 2, 2);
31-
3226
userKP = makeKeypair();
3327
backupKP = makeKeypair();
3428
bitgoKP = makeKeypair();
35-
derivationSeed = makeDerivationSeed();
3629
});
3730

3831
describe('DKG Initialization', function () {
@@ -131,9 +124,9 @@ describe('RedPallas MPS DKG', function () {
131124
});
132125

133126
const r3Messages = [
134-
...user.handleIncomingMessages(r2Messages, derivationSeed),
135-
...backup.handleIncomingMessages(r2Messages, derivationSeed),
136-
...bitgo.handleIncomingMessages(r2Messages, derivationSeed),
127+
...user.handleIncomingMessages(r2Messages),
128+
...backup.handleIncomingMessages(r2Messages),
129+
...bitgo.handleIncomingMessages(r2Messages),
137130
];
138131

139132
assert.strictEqual(user.getState(), RedPallasDkgState.Complete);
@@ -154,38 +147,16 @@ describe('RedPallas MPS DKG', function () {
154147
assert(Buffer.isBuffer(bitgoKeyShare) && bitgoKeyShare.length > 0, 'BitGo key share should be non-empty Buffer');
155148
});
156149

157-
it('should require a 32-byte derivationSeed for round 2', async function () {
158-
const r1Messages = [user.getFirstMessage(), backup.getFirstMessage(), bitgo.getFirstMessage()];
159-
const r2Messages = [
160-
...user.handleIncomingMessages(r1Messages),
161-
...backup.handleIncomingMessages(r1Messages),
162-
...bitgo.handleIncomingMessages(r1Messages),
163-
];
164-
165-
assert.strictEqual(user.getState(), RedPallasDkgState.WaitMsg2);
166-
167-
assert.throws(() => {
168-
user.handleIncomingMessages(r2Messages);
169-
}, /Missing or invalid derivationSeed/);
170-
171-
assert.throws(() => {
172-
user.handleIncomingMessages(r2Messages, Buffer.alloc(31));
173-
}, /Missing or invalid derivationSeed/);
174-
175-
// Failed round2 must leave the session in WaitMsg2
176-
assert.strictEqual(user.getState(), RedPallasDkgState.WaitMsg2);
177-
});
178-
179150
it('should generate consistent public keys across all parties', async function () {
180151
const r1Messages = [user.getFirstMessage(), backup.getFirstMessage(), bitgo.getFirstMessage()];
181152
const r2Messages = [
182153
...user.handleIncomingMessages(r1Messages),
183154
...backup.handleIncomingMessages(r1Messages),
184155
...bitgo.handleIncomingMessages(r1Messages),
185156
];
186-
user.handleIncomingMessages(r2Messages, derivationSeed);
187-
backup.handleIncomingMessages(r2Messages, derivationSeed);
188-
bitgo.handleIncomingMessages(r2Messages, derivationSeed);
157+
user.handleIncomingMessages(r2Messages);
158+
backup.handleIncomingMessages(r2Messages);
159+
bitgo.handleIncomingMessages(r2Messages);
189160

190161
const userPk = user.getSharePublicKey().toString('hex');
191162
const backupPk = backup.getSharePublicKey().toString('hex');
@@ -200,27 +171,21 @@ describe('RedPallas MPS DKG', function () {
200171
const seedUser = Buffer.from('a304733c16cc821fe171d5c7dbd7276fd90deae808b7553d17a1e55e4a76b270', 'hex');
201172
const seedBackup = Buffer.from('9d91c2e6353202cf61f8f275158b3468e9a00f7872fc2fd310b72cd026e2e2f9', 'hex');
202173
const seedBitgo = Buffer.from('33c749b635cdba7f9fbf51ad0387431cde47e20d8dc13acd1f51a9a0ad06ebfe', 'hex');
203-
const fixedDerivationSeed = Buffer.from('c526955e37be0a0c8b77a831eb615948772b38df9f04d8c5a2e0e1f1d0c9b8a7', 'hex');
204174

205175
it('should create key shares with deterministic seeds', async function () {
206176
const userParty = { encKey: seedUser, dkgSeed: seedUser };
207177
const backupParty = { encKey: seedBackup, dkgSeed: seedBackup };
208178
const bitgoParty = { encKey: seedBitgo, dkgSeed: seedBitgo };
209179

210-
const [user1, backup1, bitgo1] = await generateRedPallasDKGKeyShares(
211-
fixedDerivationSeed,
212-
userParty,
213-
backupParty,
214-
bitgoParty
215-
);
180+
const [user1, backup1, bitgo1] = await generateRedPallasDKGKeyShares(userParty, backupParty, bitgoParty);
216181

217182
const pk0 = user1.getSharePublicKey().toString('hex');
218183
const pk1 = backup1.getSharePublicKey().toString('hex');
219184
const pk2 = bitgo1.getSharePublicKey().toString('hex');
220185
assert.strictEqual(pk0, pk1, 'User and backup should have same public key');
221186
assert.strictEqual(pk1, pk2, 'Backup and BitGo should have same public key');
222187

223-
const [user2] = await generateRedPallasDKGKeyShares(fixedDerivationSeed, userParty, backupParty, bitgoParty);
188+
const [user2] = await generateRedPallasDKGKeyShares(userParty, backupParty, bitgoParty);
224189
assert.strictEqual(
225190
user1.getSharePublicKey().toString('hex'),
226191
user2.getSharePublicKey().toString('hex'),
@@ -237,13 +202,11 @@ describe('RedPallas MPS DKG', function () {
237202
const seedBBitgo = Buffer.from('44d85ab746decb8f0f0c62be0498542ddf58f31d9ed24bd1f62b1b1be17fce0f', 'hex');
238203

239204
const [user1] = await generateRedPallasDKGKeyShares(
240-
fixedDerivationSeed,
241205
{ encKey: seedAUser, dkgSeed: seedAUser },
242206
{ encKey: seedABackup, dkgSeed: seedABackup },
243207
{ encKey: seedABitgo, dkgSeed: seedABitgo }
244208
);
245209
const [user2] = await generateRedPallasDKGKeyShares(
246-
fixedDerivationSeed,
247210
{ encKey: seedBUser, dkgSeed: seedBUser },
248211
{ encKey: seedBBackup, dkgSeed: seedBBackup },
249212
{ encKey: seedBBitgo, dkgSeed: seedBBitgo }
@@ -257,7 +220,7 @@ describe('RedPallas MPS DKG', function () {
257220
});
258221

259222
it('should create key shares without party seeds (random)', async function () {
260-
const [userDkg, backupDkg, bitgoDkg] = await generateRedPallasDKGKeyShares(derivationSeed);
223+
const [userDkg, backupDkg, bitgoDkg] = await generateRedPallasDKGKeyShares();
261224

262225
const userPk = userDkg.getSharePublicKey().toString('hex');
263226
const backupPk = backupDkg.getSharePublicKey().toString('hex');
@@ -268,7 +231,7 @@ describe('RedPallas MPS DKG', function () {
268231
});
269232

270233
it('should generate valid reduced key shares', async function () {
271-
const [userDkg, backupDkg, bitgoDkg] = await generateRedPallasDKGKeyShares(derivationSeed);
234+
const [userDkg, backupDkg, bitgoDkg] = await generateRedPallasDKGKeyShares();
272235

273236
const userReduced = userDkg.getReducedKeyShare();
274237
const backupReduced = backupDkg.getReducedKeyShare();
@@ -361,7 +324,7 @@ describe('RedPallas MPS DKG', function () {
361324
});
362325

363326
it('should throw error when trying to export session after completion', async function () {
364-
const [userDkg, backupDkg, bitgoDkg] = await generateRedPallasDKGKeyShares(derivationSeed);
327+
const [userDkg, backupDkg, bitgoDkg] = await generateRedPallasDKGKeyShares();
365328

366329
assert.throws(() => {
367330
userDkg.getSession();

modules/sdk-lib-mpc/test/unit/tss/redpallas/redpallas-utils.ts

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,15 @@ describe('RedPallas Utility Functions', function () {
99
const dkgSeedUser = Buffer.from('b415844d27dd9320f282d6d8ecd8387f0e9fbf9198664e28a2f66e6f5b87c381', 'hex');
1010
const dkgSeedBackup = Buffer.from('ae02d3f7464313d0f72f9f3862694579fa11f8983fc3fe42183cd137e3f3f30a', 'hex');
1111
const dkgSeedBitgo = Buffer.from('44d85ab746decb8f0f0c62be0498542ddf58f31d9ed24bd1f62b1b1be17fce0f', 'hex');
12-
const derivationSeed = Buffer.from('c526955e37be0a0c8b77a831eb615948772b38df9f04d8c5a2e0e1f1d0c9b8a7', 'hex');
1312

1413
it('should be deterministic with split encKey and dkgSeed', async function () {
1514
const split = {
1615
user: { encKey: seedUser, dkgSeed: dkgSeedUser },
1716
backup: { encKey: seedBackup, dkgSeed: dkgSeedBackup },
1817
bitgo: { encKey: seedBitgo, dkgSeed: dkgSeedBitgo },
1918
};
20-
const [user, backup, bitgo] = await generateRedPallasDKGKeyShares(
21-
derivationSeed,
22-
split.user,
23-
split.backup,
24-
split.bitgo
25-
);
26-
const [repeatUser] = await generateRedPallasDKGKeyShares(derivationSeed, split.user, split.backup, split.bitgo);
19+
const [user, backup, bitgo] = await generateRedPallasDKGKeyShares(split.user, split.backup, split.bitgo);
20+
const [repeatUser] = await generateRedPallasDKGKeyShares(split.user, split.backup, split.bitgo);
2721

2822
const userPublicKey = user.getSharePublicKey().toString('hex');
2923
assert.strictEqual(userPublicKey, backup.getSharePublicKey().toString('hex'));
@@ -35,27 +29,17 @@ describe('RedPallas Utility Functions', function () {
3529
const okBackup = { encKey: seedBackup, dkgSeed: dkgSeedBackup };
3630
const okBitgo = { encKey: seedBitgo, dkgSeed: dkgSeedBitgo };
3731
await assert.rejects(
38-
generateRedPallasDKGKeyShares(
39-
derivationSeed,
40-
{ encKey: Buffer.alloc(31), dkgSeed: dkgSeedUser },
41-
okBackup,
42-
okBitgo
43-
),
32+
generateRedPallasDKGKeyShares({ encKey: Buffer.alloc(31), dkgSeed: dkgSeedUser }, okBackup, okBitgo),
4433
/encKey must be at least 32 bytes/
4534
);
4635
await assert.rejects(
47-
generateRedPallasDKGKeyShares(
48-
derivationSeed,
49-
{ encKey: seedUser, dkgSeed: Buffer.alloc(31) },
50-
okBackup,
51-
okBitgo
52-
),
36+
generateRedPallasDKGKeyShares({ encKey: seedUser, dkgSeed: Buffer.alloc(31) }, okBackup, okBitgo),
5337
/dkgSeed must be at least 32 bytes/
5438
);
5539
});
5640

5741
it('should produce distinct key shares per party with a shared public key', async function () {
58-
const [user, backup, bitgo] = await generateRedPallasDKGKeyShares(derivationSeed);
42+
const [user, backup, bitgo] = await generateRedPallasDKGKeyShares();
5943

6044
const userShare = user.getKeyShare();
6145
const backupShare = backup.getKeyShare();

0 commit comments

Comments
 (0)