Skip to content

Commit 82b7cd2

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

File tree

3 files changed

+348
-121
lines changed

3 files changed

+348
-121
lines changed
Lines changed: 164 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,196 @@
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,
28+
6429
recoveryMode: true,
6530
};
6631

67-
// app setup
68-
app = expressApp(cfg);
32+
const app = expressApp(config);
6933
agent = request.agent(app);
7034
});
7135

7236
afterEach(() => {
7337
nock.cleanAll();
7438
});
7539

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);
40+
after(() => {
41+
nock.enableNetConnect();
42+
});
43+
44+
describe('ECDSA sol recovery', () => {
45+
it('should successfully generate MPC solana transactions', async () => {
46+
const mockKmsUserResponse = {
47+
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"}}',
48+
pub: 'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
49+
source: 'user',
50+
type: 'tss',
51+
};
52+
53+
const mockKmsBackupResponse = {
54+
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"}}',
55+
pub: 'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
56+
source: 'backup',
57+
type: 'tss',
58+
};
59+
60+
nock(kmsUrl)
61+
.get(`/key/${mockKmsUserResponse.pub}`)
62+
.query({ source: 'user' })
63+
.reply(200, mockKmsUserResponse)
64+
.persist();
65+
66+
nock(kmsUrl)
67+
.get(`/key/${mockKmsBackupResponse.pub}`)
68+
.query({ source: 'backup' })
69+
.reply(200, mockKmsBackupResponse)
70+
.persist();
71+
72+
const input = {
73+
commonKeychain:
74+
'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
75+
unsignedSweepPrebuildTx: {
76+
txRequests: [
77+
{
78+
unsignedTx: '',
79+
signableHex:
80+
'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECvoOqYkvCPusjYyhX4GdUtzSeVIcx6GkwdpSk8SkU0/cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQtFGO2YBsrubq15CKqJLwXG3VEF1aEs36Rao6EaJDLAQECAAAMAgAAALhJxgAAAAAA',
81+
derivationPath: 'm/0',
82+
},
83+
],
84+
},
85+
};
86+
87+
const eddsaSignatureResponse = await agent
88+
.post(`/api/${sol}/mpc/recovery`)
89+
.set('Authorization', `Bearer ${accessToken}`)
90+
.send(input);
91+
92+
eddsaSignatureResponse.status.should.equal(200);
93+
eddsaSignatureResponse.body.should.have.property('txHex');
94+
95+
nock.cleanAll();
96+
});
97+
98+
it('should throw 500 Internal Server Error if KMS cannot find user or backup keys', async () => {
99+
const commonKeychain =
100+
'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174';
101+
const mockKmsUserResponse = {};
102+
const mockKmsBackupResponse = {};
103+
104+
nock(kmsUrl)
105+
.get(`/key/${commonKeychain}`)
106+
.query({ source: 'user' })
107+
.reply(200, mockKmsUserResponse)
108+
.persist();
109+
110+
nock(kmsUrl)
111+
.get(`/key/${commonKeychain}`)
112+
.query({ source: 'backup' })
113+
.reply(200, mockKmsBackupResponse)
114+
.persist();
115+
116+
const input = {
117+
commonKeychain:
118+
'b6f5fb808f538a32735a89609e98fab75690a2c79b26f50a54c4cbf0fbca287138b733783f1590e12b4916ef0f6053b22044860117274bda44bd5d711855f174',
119+
unsignedSweepPrebuildTx: {
120+
txRequests: [
121+
{
122+
unsignedTx: '',
123+
signableHex:
124+
'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAECvoOqYkvCPusjYyhX4GdUtzSeVIcx6GkwdpSk8SkU0/cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIQtFGO2YBsrubq15CKqJLwXG3VEF1aEs36Rao6EaJDLAQECAAAMAgAAALhJxgAAAAAA',
125+
derivationPath: 'm/0',
126+
},
127+
],
128+
},
129+
};
130+
131+
const eddsaSignatureResponse = await agent
132+
.post(`/api/${sol}/mpc/recovery`)
133+
.set('Authorization', `Bearer ${accessToken}`)
134+
.send(input);
135+
136+
eddsaSignatureResponse.status.should.equal(500);
137+
eddsaSignatureResponse.body.should.have.property('error');
138+
eddsaSignatureResponse.body.error.should.equal('Internal Server Error');
139+
140+
nock.cleanAll();
141+
});
142+
});
143+
144+
describe('ECDSA sui recovery', () => {
145+
it('should successfully generate MPC sui transactions', async () => {
146+
const mockKmsUserResponse = {
147+
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"}}',
148+
pub: 'f2b50b246be21f9819cdf08c721cd5d2dfb01efed33c65abd9030703609eef4c4ae3bd47ae726a5216f4f544daf76d1ddf3cdf769df7249284964ca35f33d001',
149+
source: 'user',
150+
type: 'tss',
151+
};
152+
153+
const mockKmsBackupResponse = {
154+
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"}}',
155+
pub: 'f2b50b246be21f9819cdf08c721cd5d2dfb01efed33c65abd9030703609eef4c4ae3bd47ae726a5216f4f544daf76d1ddf3cdf769df7249284964ca35f33d001',
156+
source: 'backup',
157+
type: 'tss',
158+
};
159+
160+
nock(kmsUrl)
161+
.get(`/key/${mockKmsUserResponse.pub}`)
162+
.query({ source: 'user' })
163+
.reply(200, mockKmsUserResponse)
164+
.persist();
165+
166+
nock(kmsUrl)
167+
.get(`/key/${mockKmsBackupResponse.pub}`)
168+
.query({ source: 'backup' })
169+
.reply(200, mockKmsBackupResponse)
170+
.persist();
171+
172+
const input = {
173+
commonKeychain:
174+
'f2b50b246be21f9819cdf08c721cd5d2dfb01efed33c65abd9030703609eef4c4ae3bd47ae726a5216f4f544daf76d1ddf3cdf769df7249284964ca35f33d001',
175+
unsignedSweepPrebuildTx: {
176+
txRequests: [
177+
{
178+
unsignedTx: '',
179+
signableHex:
180+
'00000200085c41793b000000000020cc1d71fdfab20a29d084030623a682e86f254f3e6a08134cc037de37fea94b21020200010100000101020000010100cc1d71fdfab20a29d084030623a682e86f254f3e6a08134cc037de37fea94b21011a4951d0006f16326d5b74df71b5c81450b4cc74d9f1c357e6e1665d5ca9a067a711d0140000000020d0402c106771059acc3246a145a7baccd512f499f086976fe768569d751bb00dcc1d71fdfab20a29d084030623a682e86f254f3e6a08134cc037de37fea94b21e803000000000000a48821000000000000',
181+
derivationPath: 'm/0',
182+
},
183+
],
184+
},
185+
};
186+
187+
const eddsaSignatureResponse = await agent
188+
.post(`/api/${sui}/mpc/recovery`)
189+
.set('Authorization', `Bearer ${accessToken}`)
190+
.send(input);
191+
192+
eddsaSignatureResponse.status.should.equal(200);
193+
eddsaSignatureResponse.body.should.have.property('txHex');
194+
});
98195
});
99196
});

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

Whitespace-only changes.

0 commit comments

Comments
 (0)