From 735dcd9cc0a00745405740d728c27da9aba993b3 Mon Sep 17 00:00:00 2001 From: Darius Parvin Date: Thu, 10 Feb 2022 13:50:17 -0800 Subject: [PATCH] feat: external signer to read private key from walletid have the external signer read the private key from the wallet id. This allows the external signer to produce signatures for multiple wallets. Ticket: BG-42962 --- modules/express/src/clientRoutes.ts | 6 +++++- modules/express/src/expressApp.ts | 5 +---- modules/express/test/unit/bitgoExpress.ts | 9 ++++----- modules/express/test/unit/clientRoutes/externalSign.ts | 7 ++++++- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/modules/express/src/clientRoutes.ts b/modules/express/src/clientRoutes.ts index 120266daa3..3b31f56605 100755 --- a/modules/express/src/clientRoutes.ts +++ b/modules/express/src/clientRoutes.ts @@ -375,14 +375,18 @@ function handleV1Sign(req: express.Request) { } export async function handleV2Sign(req: express.Request) { + const walletId = req.body.txPrebuild.walletId; const path = req.config.signerFileSystemPath; assert(typeof path === 'string'); const privKeyFile = await fs.readFile(path, { encoding: 'utf8' }); const privKey = JSON.parse(privKeyFile); + if (privKey[walletId] === undefined) { + throw new Error(`Could not find a field for walletId: ${walletId} in ${req.config.signerFileSystemPath}`); + } const bitgo = req.bitgo; const coin = bitgo.coin(req.params.coin); try { - return await coin.signTransaction({ ...req.body, ...privKey }); + return await coin.signTransaction({ ...req.body, ...{ prv: privKey[walletId] } }); } catch (error) { console.log('error while signing wallet transaction ', error); throw error; diff --git a/modules/express/src/expressApp.ts b/modules/express/src/expressApp.ts index 2cfbbf1908..0ecc89a9fc 100644 --- a/modules/express/src/expressApp.ts +++ b/modules/express/src/expressApp.ts @@ -162,10 +162,7 @@ export function createBaseUri(config: Config): string { function checkSignerPrvPath(path: string) { try { const privKeyFile = fs.readFileSync(path, { encoding: 'utf8' }); - const privKey = JSON.parse(privKeyFile); - if (privKey.prv === undefined) { - throw new Error(`required field "prv" is missing`); - } + JSON.parse(privKeyFile); } catch (e) { throw new Error(`Failed to parse ${path} - ${e.message}`); } diff --git a/modules/express/test/unit/bitgoExpress.ts b/modules/express/test/unit/bitgoExpress.ts index d0385c19b9..f5418a87d0 100644 --- a/modules/express/test/unit/bitgoExpress.ts +++ b/modules/express/test/unit/bitgoExpress.ts @@ -32,7 +32,7 @@ describe('Bitgo Express', function () { describe('server initialization', function () { const validPrvJSON = - '{"prv":"xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2"}'; + '{"61f039aad587c2000745c687373e0fa9":"xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2"}'; it('should require NODE_ENV to be production when running against prod env', function () { const envStub = sinon.stub(process, 'env').value({ NODE_ENV: 'production' }); @@ -447,7 +447,7 @@ describe('Bitgo Express', function () { (() => expressApp(args)).should.not.throw(); }); - it('should require that an signerFileSystemPath contains a json with a prv field', function () { + it('should require that an signerFileSystemPath contains a parsable json', function () { const args: any = { env: 'test', signerMode: 'signerMode', @@ -455,10 +455,9 @@ describe('Bitgo Express', function () { }; (() => expressApp(args)).should.throw(); - const invalidPrv = - '{"invalidField":"invalidPrivKey"}'; + const invalidPrv = '{"invalid json"}'; const readInvalidStub = sinon.stub(fs, 'readFileSync').returns(invalidPrv); - (() => expressApp(args)).should.throw(`Failed to parse ${args.signerFileSystemPath} - required field "prv" is missing`); + (() => expressApp(args)).should.throw(); readInvalidStub.restore(); const readValidStub = sinon.stub(fs, 'readFileSync').returns(validPrvJSON); diff --git a/modules/express/test/unit/clientRoutes/externalSign.ts b/modules/express/test/unit/clientRoutes/externalSign.ts index afbc880fbb..42c8814b33 100644 --- a/modules/express/test/unit/clientRoutes/externalSign.ts +++ b/modules/express/test/unit/clientRoutes/externalSign.ts @@ -16,12 +16,17 @@ import { BitGo } from 'bitgo'; describe('External signer', () => { it('should read prv from signerFileSystemPath and pass it to coin.signTransaction', async () => { const validPrv = - '{"prv":"xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2"}'; + '{"61f039aad587c2000745c687373e0fa9":"xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2"}'; const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv); const signTransactionStub = sinon.stub(Btc.prototype, 'signTransaction').resolves('signedTx'); const req = { bitgo: new BitGo({ env: 'test' }), + body: { + txPrebuild: { + walletId: '61f039aad587c2000745c687373e0fa9', + }, + }, params: { coin: 'tbtc', },