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' ;
61import 'should' ;
72import * 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' ;
1913 const accessToken = 'test-token' ;
2014
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-
4915 before ( async ( ) => {
50- // nock config
5116 nock . disableNetConnect ( ) ;
5217 nock . enableNetConnect ( '127.0.0.1' ) ;
5318
54- // app config
55- cfg = {
19+ const config : AdvancedWalletManagerConfig = {
5620 appMode : AppMode . ADVANCED_WALLET_MANAGER ,
5721 port : 0 , // Let OS assign a free port
5822 bind : 'localhost' ,
@@ -64,36 +28,114 @@ describe('recoveryMpc', async () => {
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 MPC 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+ } ) ;
98140 } ) ;
99141} ) ;
0 commit comments