Skip to content

Commit 2b75146

Browse files
authored
Merge pull request #106 from BitGo/WP-5337
Wp 5337
2 parents 9a7d8c3 + 82b7cd2 commit 2b75146

File tree

2 files changed

+380
-54
lines changed

2 files changed

+380
-54
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import 'should';
2+
import * as request from 'supertest';
3+
import nock from 'nock';
4+
import { app as expressApp } from '../../../advancedWalletManagerApp';
5+
import { AdvancedWalletManagerConfig, AppMode, TlsMode } from '../../../shared/types';
6+
7+
describe('recoveryMpc', () => {
8+
let agent: request.SuperAgentTest;
9+
10+
// test config
11+
const kmsUrl = 'http://kms.invalid';
12+
const sol = 'tsol';
13+
const sui = 'tsui';
14+
const accessToken = 'test-token';
15+
16+
before(async () => {
17+
nock.disableNetConnect();
18+
nock.enableNetConnect('127.0.0.1');
19+
20+
const config: AdvancedWalletManagerConfig = {
21+
appMode: AppMode.ADVANCED_WALLET_MANAGER,
22+
port: 0, // Let OS assign a free port
23+
bind: 'localhost',
24+
timeout: 60000,
25+
kmsUrl: kmsUrl,
26+
httpLoggerFile: '',
27+
tlsMode: TlsMode.DISABLED,
28+
29+
recoveryMode: true,
30+
};
31+
32+
const app = expressApp(config);
33+
agent = request.agent(app);
34+
});
35+
36+
afterEach(() => {
37+
nock.cleanAll();
38+
});
39+
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+
});
195+
});
196+
});

0 commit comments

Comments
 (0)