Skip to content

Commit 35c71ca

Browse files
committed
feat(ebe, mbe): add mpcv2 recovery support for eth-like coins
Ticket: WP-5168
1 parent 3e95c57 commit 35c71ca

22 files changed

+5092
-2655
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@
2525
"@api-ts/response": "^2.1.0",
2626
"@api-ts/superagent-wrapper": "^1.3.3",
2727
"@api-ts/typed-express-router": "^1.1.13",
28-
"@bitgo/sdk-core": "^35.3.0",
2928
"@bitgo-beta/sdk-lib-mpc": "8.2.1-alpha.291",
3029
"@bitgo/sdk-coin-ada": "^4.11.5",
3130
"@bitgo/sdk-coin-dot": "^4.3.5",
3231
"@bitgo/sdk-coin-sui": "^5.15.5",
3332
"@bitgo/sdk-coin-near": "^2.7.0",
3433
"@bitgo/sdk-coin-sol": "^4.12.5",
35-
"bitgo": "^48.1.0",
3634
"@bitgo/abstract-utxo": "^9.21.4",
35+
"@bitgo/sdk-core": "^35.3.0",
3736
"@bitgo/statics": "^54.6.0",
37+
"@ethereumjs/tx": "^3.3.0",
38+
"bitgo": "^48.1.0",
3839
"body-parser": "^1.20.3",
3940
"connect-timeout": "^1.9.0",
4041
"debug": "^3.1.0",
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { AppMode, EnclavedConfig, TlsMode } from '../../../initConfig';
2+
import { app as enclavedApp } from '../../../enclavedApp';
3+
4+
import express from 'express';
5+
import nock from 'nock';
6+
import 'should';
7+
import * as request from 'supertest';
8+
import * as sinon from 'sinon';
9+
import * as configModule from '../../../initConfig';
10+
import { DklsTypes, DklsUtils } from '@bitgo-beta/sdk-lib-mpc';
11+
12+
describe('recoveryMpcV2', () => {
13+
let cfg: EnclavedConfig;
14+
let app: express.Application;
15+
let agent: request.SuperAgentTest;
16+
17+
// test config
18+
const kmsUrl = 'http://kms.invalid';
19+
const coin = 'hteth';
20+
const accessToken = 'test-token';
21+
22+
// sinon stubs
23+
let configStub: sinon.SinonStub;
24+
25+
before(async () => {
26+
// nock config
27+
nock.disableNetConnect();
28+
nock.enableNetConnect('127.0.0.1');
29+
30+
// app config
31+
cfg = {
32+
appMode: AppMode.ENCLAVED,
33+
port: 0, // Let OS assign a free port
34+
bind: 'localhost',
35+
timeout: 60000,
36+
logFile: '',
37+
kmsUrl: kmsUrl,
38+
tlsMode: TlsMode.DISABLED,
39+
mtlsRequestCert: false,
40+
allowSelfSigned: true,
41+
};
42+
43+
configStub = sinon.stub(configModule, 'initConfig').returns(cfg);
44+
45+
// app setup
46+
app = enclavedApp(cfg);
47+
agent = request.agent(app);
48+
});
49+
50+
afterEach(() => {
51+
nock.cleanAll();
52+
});
53+
54+
after(() => {
55+
configStub.restore();
56+
});
57+
58+
it('should be sign a Mpc V2 Recovery', async () => {
59+
const [userShare, backupShare] = await DklsUtils.generateDKGKeyShares();
60+
const userKeyShare = userShare.getKeyShare().toString('base64');
61+
const backupKeyShare = backupShare.getKeyShare().toString('base64');
62+
const commonKeychain = DklsTypes.getCommonKeychain(userShare.getKeyShare());
63+
64+
const mockKmsUserResponse = {
65+
prv: JSON.stringify(userKeyShare),
66+
pub: commonKeychain,
67+
source: 'user',
68+
type: 'tss',
69+
};
70+
71+
const mockKmsBackupResponse = {
72+
prv: JSON.stringify(backupKeyShare),
73+
pub: commonKeychain,
74+
source: 'backup',
75+
type: 'tss',
76+
};
77+
78+
const input = {
79+
txHex:
80+
'02f6824268018502540be4008504a817c80083030d409443442e403d64d29c4f64065d0c1a0e8edc03d6c88801550f7dca700000823078c0',
81+
pub: commonKeychain,
82+
};
83+
// nocks for KMS responses
84+
nock(kmsUrl)
85+
.get(`/key/${input.pub}`)
86+
.query({ source: 'user', useLocalEncipherment: false })
87+
.reply(200, mockKmsUserResponse);
88+
nock(kmsUrl)
89+
.get(`/key/${input.pub}`)
90+
.query({ source: 'backup', useLocalEncipherment: false })
91+
.reply(200, mockKmsBackupResponse);
92+
93+
const signatureResponse = await agent
94+
.post(`/api/${coin}/mpcv2/recovery`)
95+
.set('Authorization', `Bearer ${accessToken}`)
96+
.send(input);
97+
98+
console.log('Signature Response:', signatureResponse.body);
99+
100+
signatureResponse.status.should.equal(200);
101+
signatureResponse.body.should.have.property('signature');
102+
signatureResponse.body.signature.should.have.property('recid');
103+
signatureResponse.body.signature.should.have.property('r');
104+
signatureResponse.body.signature.should.have.property('s');
105+
signatureResponse.body.signature.should.have.property('y');
106+
signatureResponse.body.should.have.property('txHex');
107+
signatureResponse.body.txHex.should.equal(input.txHex);
108+
});
109+
});

0 commit comments

Comments
 (0)