|
| 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