Skip to content

Commit

Permalink
feat(abstract-utxo): move keysSignatures test to separate file
Browse files Browse the repository at this point in the history
Loop over all utxo coins

BG-79423
  • Loading branch information
rushilbg committed Jun 30, 2023
1 parent d530c20 commit 99a1ff7
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 23 deletions.
26 changes: 20 additions & 6 deletions modules/abstract-utxo/src/abstractUtxoCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,9 @@ export interface RecoverFromWrongChainOptions {
}

export interface VerifyKeySignaturesOptions {
userKeychain?: Keychain;
keychainToVerify?: Keychain;
keySignature?: string;
userKeychain: { pub?: string };
keychainToVerify: { pub?: string };
keySignature: string;
}

export interface VerifyUserPublicKeyOptions {
Expand Down Expand Up @@ -744,7 +744,13 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
if (!keySignature) {
throw new Error(`missing required custom change ${KeyIndices[keyIndex].toLowerCase()} keychain signature`);
}
if (!this.verifyKeySignature({ userKeychain, keychainToVerify, keySignature })) {
if (
!this.verifyKeySignature({
userKeychain: userKeychain as { pub: string },
keychainToVerify: keychainToVerify as { pub: string },
keySignature,
})
) {
debug('failed to verify custom change %s key signature!', KeyIndices[keyIndex].toLowerCase());
return false;
}
Expand Down Expand Up @@ -814,8 +820,16 @@ export abstract class AbstractUtxoCoin extends BaseCoin {
// let's verify these keychains
const keySignatures = parsedTransaction.keySignatures;
if (!_.isEmpty(keySignatures)) {
const verify = (key, pub) =>
this.verifyKeySignature({ userKeychain: keychains.user, keychainToVerify: key, keySignature: pub });
const verify = (key, pub) => {
if (!keychains.user || !keychains.user.pub) {
throw new Error('missing user keychain');
}
return this.verifyKeySignature({
userKeychain: keychains.user as { pub: string },
keychainToVerify: key,
keySignature: pub,
});
};
const isBackupKeySignatureValid = verify(keychains.backup, keySignatures.backupPub);
const isBitgoKeySignatureValid = verify(keychains.bitgo, keySignatures.bitgoPub);
if (!isBackupKeySignatureValid || !isBitgoKeySignatureValid) {
Expand Down
19 changes: 2 additions & 17 deletions modules/bitgo/test/v2/unit/coins/abstractUtxoCoin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as utxolib from '@bitgo/utxo-lib';
import * as should from 'should';
import * as sinon from 'sinon';
import { Keychain, UnexpectedAddressError, VerificationOptions } from '@bitgo/sdk-core';
import { UnexpectedAddressError, VerificationOptions } from '@bitgo/sdk-core';
import { TestBitGo } from '@bitgo/sdk-test';
import { BitGo } from '../../../../src/bitgo';
import {
Expand Down Expand Up @@ -261,8 +261,7 @@ describe('Abstract UTXO Coin:', () => {
};

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const sign = async (key, keychain, coinToSignFor = coin) =>
(await coinToSignFor.signMessage(keychain, key.pub!)).toString('hex');
const sign = async (key, keychain) => (await coin.signMessage(keychain, key.pub!)).toString('hex');
const signUser = (key) => sign(key, userKeychain);
const signOther = (key) => sign(key, otherKeychain);
const passphrase = 'test_passphrase';
Expand Down Expand Up @@ -582,19 +581,5 @@ describe('Abstract UTXO Coin:', () => {
coinMock.restore();
bitcoinMock.restore();
});

it('should verify key signature of ZEC', async () => {
const zecCoin = bitgo.coin('tzec') as AbstractUtxoCoin;
const userKeychain = await zecCoin.keychains().create();
const otherKeychain = await zecCoin.keychains().create();

await zecCoin
.verifyKeySignature({
userKeychain: userKeychain as unknown as Keychain,
keychainToVerify: otherKeychain as unknown as Keychain,
keySignature: await sign(userKeychain, otherKeychain, zecCoin),
})
.should.be.true();
});
});
});
31 changes: 31 additions & 0 deletions modules/bitgo/test/v2/unit/coins/utxo/keySignatures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as assert from 'assert';
import { AbstractUtxoCoin } from '@bitgo/abstract-utxo';
import { Keychain } from '@bitgo/sdk-core';

import { utxoCoins } from './util';

function describeWithCoin(coin: AbstractUtxoCoin) {
describe(`verifyKeySignatures for ${coin.getChain()}`, function () {
it('should verify key signature of ZEC', async () => {
const userKeychain = await coin.keychains().create();
const backupKeychain = await coin.keychains().create();
const bitgoKeychain = await coin.keychains().create();

const signatures = await coin.createKeySignatures(
userKeychain.prv,
{ pub: backupKeychain.pub as string },
{ pub: bitgoKeychain.pub as string },
);

assert.ok(
await coin.verifyKeySignature({
userKeychain: (userKeychain as unknown) as Keychain,
keychainToVerify: (backupKeychain as unknown) as Keychain,
keySignature: signatures.backup,
}));
});
});
}

utxoCoins.forEach(coin => describeWithCoin(coin));

15 changes: 15 additions & 0 deletions modules/sdk-core/src/bitgo/baseCoin/baseCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,4 +471,19 @@ export abstract class BaseCoin implements IBaseCoin {
getHashFunction(): Hash {
throw new NotImplementedError('getHashFunction is not supported for this coin');
}

// `AbstractUtxoCoin` implements and uses the complementary `verifyKeySignature` method.
public async createKeySignatures(
prv: string,
backupKeychain: { pub: string },
bitgoKeychain: { pub: string }
): Promise<{
backup: string;
bitgo: string;
}> {
return {
backup: (await this.signMessage({ prv }, backupKeychain.pub)).toString('hex'),
bitgo: (await this.signMessage({ prv }, bitgoKeychain.pub)).toString('hex'),
};
}
}
8 changes: 8 additions & 0 deletions modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,12 @@ export interface IBaseCoin {
recoverToken(params: RecoverWalletTokenOptions): Promise<RecoverTokenTransaction>;
getInscriptionBuilder(wallet: Wallet): IInscriptionBuilder;
getHashFunction(): Hash;
createKeySignatures(
prv: string,
backupKeychain: { pub: string },
bitgoKeychain: { pub: string }
): Promise<{
backup: string;
bitgo: string;
}>;
}

0 comments on commit 99a1ff7

Please sign in to comment.