Skip to content

Commit df3726f

Browse files
committed
feat(awm, mbe): added test cases for eddsa recovery
Ticket: WP-5337
1 parent 18abe5c commit df3726f

3 files changed

Lines changed: 350 additions & 113 deletions

File tree

Lines changed: 162 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,194 @@
1-
import { AppMode, AdvancedWalletManagerConfig, TlsMode } from '../../../initConfig';
2-
import { app as expressApp } from '../../../advancedWalletManagerApp';
3-
4-
import express from 'express';
5-
import nock from 'nock';
61
import 'should';
72
import * as request from 'supertest';
8-
import { DklsTypes, DklsUtils } from '@bitgo-beta/sdk-lib-mpc';
3+
import nock from 'nock';
4+
import { app as expressApp } from '../../../advancedWalletManagerApp';
5+
import { AdvancedWalletManagerConfig, AppMode, TlsMode } from '../../../shared/types';
96

10-
describe('recoveryMpc', async () => {
11-
let cfg: AdvancedWalletManagerConfig;
12-
let app: express.Application;
7+
describe('recoveryMpc', () => {
138
let agent: request.SuperAgentTest;
149

1510
// test config
1611
const kmsUrl = 'http://kms.invalid';
17-
const eddsaCoin = 'tsol';
18-
const nonSol = 'tnear';
12+
const sol = 'tsol';
13+
const sui = 'tsui';
1914
const accessToken = 'test-token';
2015

21-
// sinon stubs
22-
// let configStub: sinon.SinonStub;
23-
24-
// kms nocks setup
25-
const [userShare, backupShare] = await DklsUtils.generateDKGKeyShares();
26-
const userKeyShare = userShare.getKeyShare().toString('base64');
27-
const backupKeyShare = backupShare.getKeyShare().toString('base64');
28-
const commonKeychain = DklsTypes.getCommonKeychain(userShare.getKeyShare());
29-
30-
const mockKmsUserResponse = {
31-
prv: JSON.stringify(userKeyShare),
32-
pub: commonKeychain,
33-
source: 'user',
34-
type: 'tss',
35-
};
36-
37-
const mockKmsBackupResponse = {
38-
prv: JSON.stringify(backupKeyShare),
39-
pub: commonKeychain,
40-
source: 'backup',
41-
type: 'tss',
42-
};
43-
const input = {
44-
txHex:
45-
'',
46-
pub: commonKeychain,
47-
};
48-
4916
before(async () => {
50-
// nock config
5117
nock.disableNetConnect();
5218
nock.enableNetConnect('127.0.0.1');
5319

54-
// app config
55-
cfg = {
20+
const config: AdvancedWalletManagerConfig = {
5621
appMode: AppMode.ADVANCED_WALLET_MANAGER,
5722
port: 0, // Let OS assign a free port
5823
bind: 'localhost',
5924
timeout: 60000,
6025
kmsUrl: kmsUrl,
6126
httpLoggerFile: '',
6227
tlsMode: TlsMode.DISABLED,
63-
allowSelfSigned: true,
6428
recoveryMode: true,
6529
};
6630

67-
// app setup
68-
app = expressApp(cfg);
31+
const app = expressApp(config);
6932
agent = request.agent(app);
7033
});
7134

7235
afterEach(() => {
7336
nock.cleanAll();
7437
});
7538

76-
// happy path test
77-
it('should be sign a MPC Recovery', async () => {
78-
// nocks for KMS responses
79-
const userKmsNock = nock(kmsUrl)
80-
.get(`/key/${input.pub}`)
81-
.query({ source: 'user', useLocalEncipherment: false })
82-
.reply(200, mockKmsUserResponse)
83-
.persist();
84-
const backupKmsNock = nock(kmsUrl)
85-
.get(`/key/${input.pub}`)
86-
.query({ source: 'backup', useLocalEncipherment: false })
87-
.reply(200, mockKmsBackupResponse)
88-
.persist();
89-
90-
const eddsaSignatureResponse = await agent
91-
.post(`/api/${eddsaCoin}/mpc/recovery`)
92-
.set('Authorization', `Bearer ${accessToken}`)
93-
.send(input);
94-
95-
eddsaSignatureResponse.status.should.equal(200);
96-
eddsaSignatureResponse.body.should.have.property('txHex');
97-
eddsaSignatureResponse.body.txHex.should.equal(input.txHex);
39+
after(() => {
40+
nock.enableNetConnect();
41+
});
42+
43+
describe('ECDSA sol recovery', () => {
44+
it('should successfully generate MPC solana transactions', async () => {
45+
const mockKmsUserResponse = {
46+
prv: '{"uShare":{"i":1,"t":2,"n":3,"y":"85aa6462d927329418f70f6d0863cf6cf33e7da2934f935e5927f1b13062d779","seed":"2f55c80fd6b5583dcde8037b2ee461d2e7d445a4d3e7a9b2a0d3d00b5f534169","chaincode":"66e80f2bf41a5706608352d51ceb07a5aa1729cab6c6993c124d5731546ed9a1"},"bitgoYShare":{"i":1,"j":3,"y":"483e53b72de3aa893df698d0b20b20777fb3d2716cc8483a9e9797174fd52b16","v":"e70696459e46434a2a12cc988e3ae714a61fe96da8a6764d058b849cab50d6dc","u":"49abf8144d265a77cf6d098eff784d6ce56ec77a182f6b39f47d5d8e28f2a802","chaincode":"797348468202f1d7fede0a7851f80162b02e7da306e65075dd864b6789b9bc5b"},"backupYShare":{"i":1,"j":2,"y":"249a9798d0064a989a16cd8f479edf09ffaee73f4175d2ac555ba90ff41b89da","v":"98e31d2b643e40060ba344c6a41fc096ea7e39a1ae879f65e4af645870e90ee0","u":"ac047b1bceab2e1a42d97ab540b39176e545d9c0af4a192aee8e1dae91a4240b","chaincode":"585bdc05c8f84802cbe7b9a1a07d4aa9c5fede93597a622854e9bad83a2d5b78"}}',
47+
pub: 'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
48+
source: 'user',
49+
type: 'tss',
50+
};
51+
52+
const mockKmsBackupResponse = {
53+
prv: '{"uShare":{"i":2,"t":2,"n":3,"y":"249a9798d0064a989a16cd8f479edf09ffaee73f4175d2ac555ba90ff41b89da","seed":"abab5be2b32d07cf39b2a162af0f78bad8325b2fbdc89d14fd8b4e5767b74097","chaincode":"585bdc05c8f84802cbe7b9a1a07d4aa9c5fede93597a622854e9bad83a2d5b78"},"bitgoYShare":{"i":2,"j":3,"y":"483e53b72de3aa893df698d0b20b20777fb3d2716cc8483a9e9797174fd52b16","v":"e70696459e46434a2a12cc988e3ae714a61fe96da8a6764d058b849cab50d6dc","u":"eb54da28da3da22eb3d61797a02a96264be8940b7115aefbb90b9dd044db7f06","chaincode":"797348468202f1d7fede0a7851f80162b02e7da306e65075dd864b6789b9bc5b"},"userYShare":{"i":2,"j":1,"y":"85aa6462d927329418f70f6d0863cf6cf33e7da2934f935e5927f1b13062d779","v":"76cfdcbf0f769f21c64e0faf0072ebccbcc3aaa844522336af27f8e50ed7ca5f","u":"6ce814af82683423c8d8befd13f6eeeb0cd3f7274d1ebfdd5807fd2e4eaadb08","chaincode":"66e80f2bf41a5706608352d51ceb07a5aa1729cab6c6993c124d5731546ed9a1"}}',
54+
pub: 'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
55+
source: 'backup',
56+
type: 'tss',
57+
};
58+
59+
nock(kmsUrl)
60+
.get(`/key/${mockKmsUserResponse.pub}`)
61+
.query({ source: 'user', useLocalEncipherment: false })
62+
.reply(200, mockKmsUserResponse)
63+
.persist();
64+
65+
nock(kmsUrl)
66+
.get(`/key/${mockKmsBackupResponse.pub}`)
67+
.query({ source: 'backup', useLocalEncipherment: false })
68+
.reply(200, mockKmsBackupResponse)
69+
.persist();
70+
71+
const input = {
72+
commonKeychain:
73+
'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
74+
unsignedSweepPrebuildTx: {
75+
txRequests: [
76+
{
77+
unsignedTx: '',
78+
signableHex:
79+
'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECvoOqYkvCPusjYyhX4GdUtzSeVIcx6GkwdpSk8SkU0/cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQtFGO2YBsrubq15CKqJLwXG3VEF1aEs36Rao6EaJDLAQECAAAMAgAAALhJxgAAAAAA',
80+
derivationPath: 'm/0',
81+
},
82+
],
83+
},
84+
};
85+
86+
const eddsaSignatureResponse = await agent
87+
.post(`/api/${sol}/mpc/recovery`)
88+
.set('Authorization', `Bearer ${accessToken}`)
89+
.send(input);
90+
91+
eddsaSignatureResponse.status.should.equal(200);
92+
eddsaSignatureResponse.body.should.have.property('txHex');
93+
94+
nock.cleanAll();
95+
});
96+
97+
it('should throw 500 Internal Server Error if KMS cannot find user or backup keys', async () => {
98+
const commonKeychain = 'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174';
99+
const mockKmsUserResponse = {};
100+
const mockKmsBackupResponse = {};
101+
102+
nock(kmsUrl)
103+
.get(`/key/${commonKeychain}`)
104+
.query({ source: 'user', useLocalEncipherment: false })
105+
.reply(200, mockKmsUserResponse)
106+
.persist();
107+
108+
nock(kmsUrl)
109+
.get(`/key/${commonKeychain}`)
110+
.query({ source: 'backup', useLocalEncipherment: false })
111+
.reply(200, mockKmsBackupResponse)
112+
.persist();
113+
114+
const input = {
115+
commonKeychain:
116+
'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
117+
unsignedSweepPrebuildTx: {
118+
txRequests: [
119+
{
120+
unsignedTx: '',
121+
signableHex:
122+
'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECvoOqYkvCPusjYyhX4GdUtzSeVIcx6GkwdpSk8SkU0/cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQtFGO2YBsrubq15CKqJLwXG3VEF1aEs36Rao6EaJDLAQECAAAMAgAAALhJxgAAAAAA',
123+
derivationPath: 'm/0',
124+
},
125+
],
126+
},
127+
};
128+
129+
const eddsaSignatureResponse = await agent
130+
.post(`/api/${sol}/mpc/recovery`)
131+
.set('Authorization', `Bearer ${accessToken}`)
132+
.send(input);
133+
134+
eddsaSignatureResponse.status.should.equal(500);
135+
eddsaSignatureResponse.body.should.have.property('error');
136+
eddsaSignatureResponse.body.error.should.equal('Failed to retrieve key from KMS');
137+
138+
nock.cleanAll();
139+
});
140+
});
141+
142+
describe('ECDSA sui recovery', () => {
143+
it('should successfully generate MPC sui transactions', async () => {
144+
const mockKmsUserResponse = {
145+
prv: '{"uShare":{"i":1,"t":2,"n":3,"y":"8e10c0d10fb8a5780bba0f62fb86e2a80fd6f04b348985e9174a4f4f66e1baf5","seed":"368eab02c210effbb345d8c3cbe3d00b61292071feb0eafe26d9ce6060145d7b","chaincode":"e32078c8ba161f4c6c10b01abdf8203aed06878bae6a90906be228fd1b196b18"},"bitgoYShare":{"i":1,"j":3,"y":"532ee5aa5be82b9e64c10ff98d3be21901888bbba2293f0db429b8737cbf94ca","v":"72b2a6d7243654f4e80b050f5fa0c9de505b37ebcd7803dfacf22ba8bc60716a","u":"b13b791180c1148405f2137f011831ec5ffd4dd2584f7bef4f5a174debe8df08","chaincode":"87292c10bbdfd6f15e80dd96f3b530aaf0b7b99d933b3d0b61b7a1565b0a89f9"},"backupYShare":{"i":1,"j":2,"y":"5119753ee78a9f43ed2df6bc79d1d69954ada568dce7c3de6aa031ea2f951967","v":"852459fcfe7170cb433cc98115fb2a292b3301834ce89b0e843ad952cca885d1","u":"0854f68dbf402bc928afb86448eab19fbe90fcb387103d1fff35d02af18b230d","chaincode":"e09a186e387c74144c636793294a1c38017e9e4d5c5156f6b6fc824fe90fdaf0"}}',
146+
pub: 'f2b50b246be21f9819cdf08c721cd5d2dfb01efed33c65abd9030703609eef4c4ae3bd47ae726a5216f4f544daf76d1ddf3cdf769df7249284964ca35f33d001',
147+
source: 'user',
148+
type: 'tss',
149+
};
150+
151+
const mockKmsBackupResponse = {
152+
prv: '{"uShare":{"i":2,"t":2,"n":3,"y":"5119753ee78a9f43ed2df6bc79d1d69954ada568dce7c3de6aa031ea2f951967","seed":"e70e6fd6f914b7b854e7b5ab46fff52a530dc3d10aa5a71c2b32559ea349ac4e","chaincode":"e09a186e387c74144c636793294a1c38017e9e4d5c5156f6b6fc824fe90fdaf0"},"bitgoYShare":{"i":2,"j":3,"y":"532ee5aa5be82b9e64c10ff98d3be21901888bbba2293f0db429b8737cbf94ca","v":"72b2a6d7243654f4e80b050f5fa0c9de505b37ebcd7803dfacf22ba8bc60716a","u":"709cfacb0bfa99c38ff319d16e4e2b34ecd8e40025496d21d2932204b785e80d","chaincode":"87292c10bbdfd6f15e80dd96f3b530aaf0b7b99d933b3d0b61b7a1565b0a89f9"},"userYShare":{"i":2,"j":1,"y":"8e10c0d10fb8a5780bba0f62fb86e2a80fd6f04b348985e9174a4f4f66e1baf5","v":"a81795570884a88dc7586c9a49a632a2aea0859eae622c51617387b85e8b5b0a","u":"0857dfc00a1fe3a4a41a752e933788becc6b23c2f5637393906f79b89aa50d0d","chaincode":"e32078c8ba161f4c6c10b01abdf8203aed06878bae6a90906be228fd1b196b18"}}',
153+
pub: 'f2b50b246be21f9819cdf08c721cd5d2dfb01efed33c65abd9030703609eef4c4ae3bd47ae726a5216f4f544daf76d1ddf3cdf769df7249284964ca35f33d001',
154+
source: 'backup',
155+
type: 'tss',
156+
};
157+
158+
nock(kmsUrl)
159+
.get(`/key/${mockKmsUserResponse.pub}`)
160+
.query({ source: 'user', useLocalEncipherment: false })
161+
.reply(200, mockKmsUserResponse)
162+
.persist();
163+
164+
nock(kmsUrl)
165+
.get(`/key/${mockKmsBackupResponse.pub}`)
166+
.query({ source: 'backup', useLocalEncipherment: false })
167+
.reply(200, mockKmsBackupResponse)
168+
.persist();
169+
170+
const input = {
171+
commonKeychain:
172+
'f2b50b246be21f9819cdf08c721cd5d2dfb01efed33c65abd9030703609eef4c4ae3bd47ae726a5216f4f544daf76d1ddf3cdf769df7249284964ca35f33d001',
173+
unsignedSweepPrebuildTx: {
174+
txRequests: [
175+
{
176+
unsignedTx: '',
177+
signableHex:
178+
'00000200085c41793b000000000020cc1d71fdfab20a29d084030623a682e86f254f3e6a08134cc037de37fea94b21020200010100000101020000010100cc1d71fdfab20a29d084030623a682e86f254f3e6a08134cc037de37fea94b21011a4951d0006f16326d5b74df71b5c81450b4cc74d9f1c357e6e1665d5ca9a067a711d0140000000020d0402c106771059acc3246a145a7baccd512f499f086976fe768569d751bb00dcc1d71fdfab20a29d084030623a682e86f254f3e6a08134cc037de37fea94b21e803000000000000a48821000000000000',
179+
derivationPath: 'm/0',
180+
},
181+
],
182+
},
183+
};
184+
185+
const eddsaSignatureResponse = await agent
186+
.post(`/api/${sui}/mpc/recovery`)
187+
.set('Authorization', `Bearer ${accessToken}`)
188+
.send(input);
189+
190+
eddsaSignatureResponse.status.should.equal(200);
191+
eddsaSignatureResponse.body.should.have.property('txHex');
192+
});
98193
});
99194
});

src/__tests__/api/enclaved/kmsClient.test.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)