Skip to content

Commit c107cb0

Browse files
committed
feat(ebe, mbe): add mpcv2 recovery support for eth-like coins
Ticket: WP-5168
1 parent 58428fe commit c107cb0

21 files changed

Lines changed: 5107 additions & 2661 deletions

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: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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 * as bitgoSdk from '@bitgo/sdk-core';
11+
12+
describe('recoveryMpcV2', () => {
13+
let cfg: EnclavedConfig;
14+
let app: express.Application;
15+
let agent: request.SuperAgentTest;
16+
17+
let MPC: bitgoSdk.Ecdsa;
18+
19+
// test config
20+
const kmsUrl = 'http://kms.invalid';
21+
const coin = 'tsol';
22+
const accessToken = 'test-token';
23+
24+
// sinon stubs
25+
let configStub: sinon.SinonStub;
26+
27+
before(async () => {
28+
// nock config
29+
nock.disableNetConnect();
30+
nock.enableNetConnect('127.0.0.1');
31+
32+
// app config
33+
cfg = {
34+
appMode: AppMode.ENCLAVED,
35+
port: 0, // Let OS assign a free port
36+
bind: 'localhost',
37+
timeout: 60000,
38+
logFile: '',
39+
kmsUrl: kmsUrl,
40+
tlsMode: TlsMode.DISABLED,
41+
mtlsRequestCert: false,
42+
allowSelfSigned: true,
43+
};
44+
45+
configStub = sinon.stub(configModule, 'initConfig').returns(cfg);
46+
47+
// app setup
48+
app = enclavedApp(cfg);
49+
agent = request.agent(app);
50+
51+
MPC = new bitgoSdk.Ecdsa();
52+
});
53+
54+
afterEach(() => {
55+
nock.cleanAll();
56+
});
57+
58+
after(() => {
59+
configStub.restore();
60+
});
61+
62+
it('should be sign a Mpc V2 Recovery', async () => {
63+
const user = await MPC.keyShare(1, 2, 3);
64+
const backup = await MPC.keyShare(2, 2, 3);
65+
const bitgo = await MPC.keyShare(3, 2, 3);
66+
67+
const userSigningMaterial = {
68+
uShare: user.pShare,
69+
bitgoYShare: bitgo.nShares[1],
70+
backupYShare: backup.nShares[1],
71+
};
72+
73+
const backupSigningMaterial = {
74+
uShare: backup.pShare,
75+
bitgoYShare: bitgo.nShares[2],
76+
userYShare: user.nShares[2],
77+
};
78+
79+
const mockKmsUserResponse = {
80+
prv: JSON.stringify(userSigningMaterial),
81+
pub: '030030196a0a8559459029725c5494d4f7110746b27c94d3cd91ff84085ec15f50166f045f5eb1776c65ef7e9c4ffd9979b6bdc6f19e35110c8223b0bac9c0b074',
82+
source: 'user',
83+
type: 'tss',
84+
};
85+
86+
const mockKmsBackupResponse = {
87+
prv: JSON.stringify(backupSigningMaterial),
88+
pub: '030030196a0a8559459029725c5494d4f7110746b27c94d3cd91ff84085ec15f50166f045f5eb1776c65ef7e9c4ffd9979b6bdc6f19e35110c8223b0bac9c0b074',
89+
source: 'backup',
90+
type: 'tss',
91+
};
92+
93+
const input = {
94+
txHex:
95+
'02f839824268018502540be4008504a817c8008307a12094a94584f774b9b3e932fd4f1802f3b9aa292bd17188013fbe85edc90000823078c0808080',
96+
pub: '030030196a0a8559459029725c5494d4f7110746b27c94d3cd91ff84085ec15f50166f045f5eb1776c65ef7e9c4ffd9979b6bdc6f19e35110c8223b0bac9c0b074',
97+
};
98+
// nocks for KMS responses
99+
nock(kmsUrl).get(`/key/${input}`).query({ source: 'user' }).reply(200, mockKmsUserResponse);
100+
101+
nock(kmsUrl).get(`/key/${input}`).query({ source: 'backup' }).reply(200, mockKmsBackupResponse);
102+
103+
const signatureResponse = await agent
104+
.post(`/api/${coin}/mpcv2/recovery/signature`)
105+
.set('Authorization', `Bearer ${accessToken}`)
106+
.send(input);
107+
108+
signatureResponse.status.should.equal(200);
109+
signatureResponse.body.should.have.property('signature');
110+
signatureResponse.body.signature.should.have.property('recid');
111+
signatureResponse.body.signature.should.have.property('r');
112+
signatureResponse.body.signature.should.have.property('s');
113+
signatureResponse.body.signature.should.have.property('y');
114+
signatureResponse.body.should.have.property('txHex');
115+
signatureResponse.body.txHex.should.equal(input.txHex);
116+
});
117+
});

0 commit comments

Comments
 (0)