PHP WebShell
Текущая директория: /opt/BitGoJS/modules/bitgo/test/v2/unit/tss
Просмотр файла: eddsa.ts
import {
encryptYShare,
createCombinedKey,
createUserSignShare,
sendSignatureShare,
getBitgoToUserRShare,
getTxRequest,
offerUserToBitgoRShare,
createUserToBitGoGShare,
sendUserToBitgoGShare,
readSignedMessage,
RequestType,
SignatureShareRecord,
Wallet,
KeyShare,
Ed25519BIP32,
Eddsa,
SignShare,
CommitmentShareRecord,
CommitmentType,
SignatureShareType,
RequestTracer,
} from '@bitgo/sdk-core';
import * as openpgp from 'openpgp';
import * as should from 'should';
import * as _ from 'lodash';
import { TestBitGo } from '@bitgo/sdk-test';
import { BitGo } from '../../../../src/bitgo';
import { nockGetTxRequest, nockSendSignatureShare } from './helpers';
import * as sinon from 'sinon';
import nock = require('nock');
describe('test tss helper functions', function () {
let mpc: Eddsa;
let userKeyShare: KeyShare;
let backupKeyShare: KeyShare;
let bitgoKeyShare: KeyShare;
let userKey;
let backupKey;
let bitgoKey;
let userGpgKeypair: { publicKey: string; privateKey: string };
let backupGpgKeypair: { publicKey: string; privateKey: string };
let bitgoGpgKeypair: { publicKey: string; privateKey: string };
let commonKeychain: string;
before(async function () {
const hdTree = await Ed25519BIP32.initialize();
mpc = await Eddsa.initialize(hdTree);
userKeyShare = mpc.keyShare(1, 2, 3);
backupKeyShare = mpc.keyShare(2, 2, 3);
bitgoKeyShare = mpc.keyShare(3, 2, 3);
userKey = mpc.keyCombine(userKeyShare.uShare, [backupKeyShare.yShares[1], bitgoKeyShare.yShares[1]]);
backupKey = mpc.keyCombine(backupKeyShare.uShare, [userKeyShare.yShares[2], bitgoKeyShare.yShares[2]]);
bitgoKey = mpc.keyCombine(bitgoKeyShare.uShare, [backupKeyShare.yShares[3], userKeyShare.yShares[3]]);
(userKey.pShare.y + userKey.pShare.chaincode).should.equal(backupKey.pShare.y + backupKey.pShare.chaincode);
(userKey.pShare.y + userKey.pShare.chaincode).should.equal(bitgoKey.pShare.y + bitgoKey.pShare.chaincode);
commonKeychain = userKey.pShare.y + userKey.pShare.chaincode;
userGpgKeypair = await openpgp.generateKey({
userIDs: [
{
name: 'user',
email: 'user@bitgo.com',
},
],
});
backupGpgKeypair = await openpgp.generateKey({
userIDs: [
{
name: 'backup',
email: 'backup@bitgo.com',
},
],
});
bitgoGpgKeypair = await openpgp.generateKey({
userIDs: [
{
name: 'bitgo',
email: 'bitgo@bitgo.com',
},
],
});
});
after(function () {
nock.cleanAll();
});
describe('encryptYShare', function () {
it('should encrypt y share', async function () {
for (let i = 2; i <= 3; i++) {
const encryptedYShare = await encryptYShare({
keyShare: userKeyShare,
recipientIndex: i,
senderGpgPrivateArmor: userGpgKeypair.privateKey,
recipientGpgPublicArmor: bitgoGpgKeypair.publicKey,
});
const decryptedMessage = await readSignedMessage(
encryptedYShare.encryptedPrivateShare,
userGpgKeypair.publicKey,
bitgoGpgKeypair.privateKey
);
decryptedMessage.should.equal(userKeyShare.yShares[i].u + userKeyShare.yShares[i].chaincode);
encryptedYShare.i.should.equal(i);
encryptedYShare.j.should.equal(1);
encryptedYShare.publicShare.should.equal(
userKeyShare.uShare.y + userKeyShare.yShares[3].v + userKeyShare.uShare.chaincode
);
}
});
it('should error for invalid recipient index', async function () {
await encryptYShare({
keyShare: userKeyShare,
recipientIndex: 1,
senderGpgPrivateArmor: userGpgKeypair.privateKey,
recipientGpgPublicArmor: bitgoGpgKeypair.publicKey,
}).should.be.rejectedWith('Invalid recipient');
await encryptYShare({
keyShare: backupKeyShare,
recipientIndex: 2,
senderGpgPrivateArmor: userGpgKeypair.privateKey,
recipientGpgPublicArmor: bitgoGpgKeypair.publicKey,
}).should.be.rejectedWith('Invalid recipient');
await encryptYShare({
keyShare: bitgoKeyShare,
recipientIndex: 3,
senderGpgPrivateArmor: userGpgKeypair.privateKey,
recipientGpgPublicArmor: bitgoGpgKeypair.publicKey,
}).should.be.rejectedWith('Invalid recipient');
});
});
describe('createCombinedKey', function () {
it('should create combined user key', async function () {
const bitgoToUserShare = await encryptYShare({
keyShare: bitgoKeyShare,
recipientIndex: 1,
recipientGpgPublicArmor: userGpgKeypair.publicKey,
senderGpgPrivateArmor: bitgoGpgKeypair.privateKey,
});
const backupToUserShare = await encryptYShare({
keyShare: backupKeyShare,
recipientIndex: 1,
recipientGpgPublicArmor: userGpgKeypair.publicKey,
senderGpgPrivateArmor: backupGpgKeypair.privateKey,
});
const combinedUserKey = await createCombinedKey({
keyShare: userKeyShare,
commonKeychain,
encryptedYShares: [
{
yShare: bitgoToUserShare,
recipientPrivateArmor: userGpgKeypair.privateKey,
senderPublicArmor: bitgoGpgKeypair.publicKey,
},
{
yShare: backupToUserShare,
recipientPrivateArmor: userGpgKeypair.privateKey,
senderPublicArmor: backupGpgKeypair.publicKey,
},
],
});
combinedUserKey.commonKeychain.should.equal(commonKeychain);
combinedUserKey.signingMaterial.uShare.should.deepEqual(userKeyShare.uShare);
combinedUserKey.signingMaterial.backupYShare!.should.deepEqual(backupKeyShare.yShares[1]);
combinedUserKey.signingMaterial.bitgoYShare.should.deepEqual(bitgoKeyShare.yShares[1]);
should.not.exist(combinedUserKey.signingMaterial.userYShare);
});
it('should create combined backup key', async function () {
const bitgoToBackupShare = await encryptYShare({
keyShare: bitgoKeyShare,
recipientIndex: 2,
recipientGpgPublicArmor: backupGpgKeypair.publicKey,
senderGpgPrivateArmor: bitgoGpgKeypair.privateKey,
});
const userToBackupShare = await encryptYShare({
keyShare: userKeyShare,
recipientIndex: 2,
recipientGpgPublicArmor: backupGpgKeypair.publicKey,
senderGpgPrivateArmor: userGpgKeypair.privateKey,
});
const combinedBackupKey = await createCombinedKey({
keyShare: backupKeyShare,
commonKeychain,
encryptedYShares: [
{
yShare: bitgoToBackupShare,
recipientPrivateArmor: backupGpgKeypair.privateKey,
senderPublicArmor: bitgoGpgKeypair.publicKey,
},
{
yShare: userToBackupShare,
recipientPrivateArmor: backupGpgKeypair.privateKey,
senderPublicArmor: userGpgKeypair.publicKey,
},
],
});
combinedBackupKey.commonKeychain.should.equal(commonKeychain);
combinedBackupKey.signingMaterial.uShare.should.deepEqual(backupKeyShare.uShare);
combinedBackupKey.signingMaterial.userYShare!.should.deepEqual(userKeyShare.yShares[2]);
combinedBackupKey.signingMaterial.bitgoYShare.should.deepEqual(bitgoKeyShare.yShares[2]);
should.not.exist(combinedBackupKey.signingMaterial.backupYShare);
});
it('should fail if common keychains do not match', async function () {
const bitgoToUserShare = await encryptYShare({
keyShare: bitgoKeyShare,
recipientIndex: 1,
recipientGpgPublicArmor: userGpgKeypair.publicKey,
senderGpgPrivateArmor: bitgoGpgKeypair.privateKey,
});
const backupToUserShare = await encryptYShare({
keyShare: backupKeyShare,
recipientIndex: 1,
recipientGpgPublicArmor: userGpgKeypair.publicKey,
senderGpgPrivateArmor: backupGpgKeypair.privateKey,
});
await createCombinedKey({
keyShare: userKeyShare,
commonKeychain: 'nottherightkeychain',
encryptedYShares: [
{
yShare: bitgoToUserShare,
recipientPrivateArmor: userGpgKeypair.privateKey,
senderPublicArmor: bitgoGpgKeypair.publicKey,
},
{
yShare: backupToUserShare,
recipientPrivateArmor: userGpgKeypair.privateKey,
senderPublicArmor: backupGpgKeypair.publicKey,
},
],
}).should.be.rejectedWith('Common keychains do not match');
});
it('should fail if gpg keys are mismatched', async function () {
const bitgoToUserShare = await encryptYShare({
keyShare: bitgoKeyShare,
recipientIndex: 1,
recipientGpgPublicArmor: userGpgKeypair.publicKey,
senderGpgPrivateArmor: bitgoGpgKeypair.privateKey,
});
const backupToUserShare = await encryptYShare({
keyShare: backupKeyShare,
recipientIndex: 1,
recipientGpgPublicArmor: userGpgKeypair.publicKey,
senderGpgPrivateArmor: backupGpgKeypair.privateKey,
});
await createCombinedKey({
keyShare: userKeyShare,
commonKeychain: 'nottherightkeychain',
encryptedYShares: [
{
yShare: bitgoToUserShare,
recipientPrivateArmor: backupGpgKeypair.privateKey,
senderPublicArmor: bitgoGpgKeypair.publicKey,
},
{
yShare: backupToUserShare,
recipientPrivateArmor: userGpgKeypair.privateKey,
senderPublicArmor: backupGpgKeypair.publicKey,
},
],
}).should.be.rejectedWith('Error decrypting message: Session key decryption failed.');
});
});
describe('Eddsa tss signing helper function', async function () {
const bitgo = TestBitGo.decorate(BitGo, { env: 'mock' });
bitgo.initializeTestVars();
let wallet: Wallet;
const path = 'm/0';
const validUserSigningMaterial = {
uShare: {
i: 1,
t: 2,
n: 3,
y: '093c8603ad86c41d5ee25a814b88185b435dd3a9ceccf9c9fd691a465ac4a8b0',
seed: 'ca40c789813250c334ddd2ba19050f6ed20b5a08853ceca492358f2711ad4b15',
chaincode: '596d5404a7eb918ee78247b952d06539619884091fdd9e0ff5a665f349e32fca',
},
commonChaincode: '596d5404a7eb918ee78247b952d06539619884091fdd9e0ff5a665f349e32fca',
bitgoYShare: {
i: 1,
j: 3,
y: '59d8000ba5e85fa402f39382960e7d5ede82b1b6e22b146a18b7df238c3a3225',
v: '01ea3f425b1adf8aec6cfe4fc8f9b94755c34657965f32397655dcd784f1b517',
u: '9ce3204a8c9757738967f3f81b463d87267bf6f2c0e5eaf2843167537b872b0b',
chaincode: 'd21dbd8eae5d4789292ecea2efa53e0165b2439d57f5158eb4dd57dc26b59236',
},
backupYShare: {
i: 1,
j: 2,
y: 'e0ae75077715686a121acb41b29a55bde426971154f40a41fc317f7f774a9424',
v: 'f76ef629dfc15ab5e4531e532b5d67f2176637ca752b195876b7e3172459c969',
u: 'fe6b89fb6acfcd7392c35c084f58bde0846b888c4df57e466caf0a3271b06a05',
chaincode: '1c34e5dfbbd4a870f4479caaa5e6a46e3438f976ad5aefd4905b8fe8bca1101e',
},
};
const validUserSignShare: SignShare = {
xShare: {
i: 1,
y: '4d9343988e68191aac945a6963031dddde3490f9020d0571a6e6c6e15cca0296',
u: '1e159d6a0ae3a8dccc74615113e7c3e25d3080e5e0ffeb0ae04dd6a967268102',
r: 'c8f64cc48926216c3f60e1d8ff1e24eba060d7c1ff020d0fc1d735d4564efd03',
R: '9be2208ee28cd4b2577a9a66f6aab1ed8b08a300969eeb9b203a52aa54d2c23c',
},
rShares: {
3: {
i: 3,
j: 1,
u: 'd675f9099fbef03aa9fcdca4009286f435e56369c374d0042f03cc60b49e690a',
v: '3c090e88ed42da0dd0bade35c8d6b88bc050284536b98e5b27d33ff45da9755b',
r: '7f16224dbf5b02adb6c21380fcb2a8ee00323daae62cac3575a4d328fd23a905',
R: '9be2208ee28cd4b2577a9a66f6aab1ed8b08a300969eeb9b203a52aa54d2c23c',
commitment: '445c8cb1dee0166b6bdd5ad1d0a53fbfe86c4d3a470f184745530a863eedff28',
},
},
};
const validUserToBitgoGShare = {
i: 1,
y: '4d9343988e68191aac945a6963031dddde3490f9020d0571a6e6c6e15cca0296',
gamma: 'ce87a00d17e52b91bc5bb6e275983b84fc1998b2b37f7166c671a019c33d3905',
R: 'aa6e5bad24ad4131b8793dcb95c72e03c5426456ab0b52fc99d61d7103c2f01b',
};
const validBitgoToUserSignShare: SignShare = {
xShare: {
i: 3,
y: '4d9343988e68191aac945a6963031dddde3490f9020d0571a6e6c6e15cca0296',
u: '1315dbe18069825b4a27188b813eae7ff2917a614499ed553e70d65d4fa4820b',
r: 'd0539375e6566f2fe540cba48c5e56bd1cdf68cfe1f0d527d2b730fe4e879809',
R: 'c883fe2ae9b8da1764cc36a526cfa1a21f81d604320b209867f8de9223f1de32',
},
rShares: {
1: {
i: 1,
j: 3,
u: '9ce3204a8c9757738967f3f81b463d87267bf6f2c0e5eaf2843167537b872b0b',
v: '01ea3f425b1adf8aec6cfe4fc8f9b94755c34657965f32397655dcd784f1b517',
r: '0375e8c5a5691a73c21df00d49d423e3f83fe08d7b5d5af33c5c6aa9cae59d0a',
R: 'c883fe2ae9b8da1764cc36a526cfa1a21f81d604320b209867f8de9223f1de32',
commitment: '62b21f98bf885841ad469145192d4df0697b3f42c581e3e926394eae0b101ecb',
},
},
};
const txRequest = {
txRequestId: 'randomId',
unsignedTxs: [{ signableHex: 'MPC on a Friday night', serializedTxHex: 'MPC on a Friday night' }],
signatureShares: [
{
from: 'bitgo',
to: 'user',
share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R,
},
],
};
const signablePayload = Buffer.from(txRequest.unsignedTxs[0].signableHex);
const bitgoToUserCommitment: CommitmentShareRecord = {
from: SignatureShareType.BITGO,
to: SignatureShareType.USER,
share: validBitgoToUserSignShare.rShares[1].commitment!,
type: CommitmentType.COMMITMENT,
};
let MPC: Eddsa;
before('initializes', async function () {
const hdTree = await Ed25519BIP32.initialize();
MPC = await Eddsa.initialize(hdTree);
const baseCoin = bitgo.coin('tsol');
const walletData = {
id: '5b34252f1bf349930e34020a00000000',
coin: 'tsol',
keys: [
'5b3424f91bf349930e34017500000000',
'5b3424f91bf349930e34017600000000',
'5b3424f91bf349930e34017700000000',
],
coinSpecific: {},
};
wallet = new Wallet(bitgo, baseCoin, walletData);
});
describe('createUserSignShare:', async function () {
it('should succeed to create User SignShare', async function () {
const signingKey = MPC.keyDerive(
validUserSigningMaterial.uShare,
[validUserSigningMaterial.bitgoYShare, validUserSigningMaterial.backupYShare],
path
);
const userSignShare = await createUserSignShare(signablePayload, signingKey.pShare);
userSignShare.should.have.properties(['xShare', 'rShares']);
const { xShare, rShares } = userSignShare;
xShare.should.have.property('i').and.be.a.Number();
xShare.should.have.property('y').and.be.a.String();
xShare.should.have.property('u').and.be.a.String();
xShare.should.have.property('r').and.be.a.String();
xShare.should.have.property('R').and.be.a.String();
rShares.should.have.property('3').and.be.an.Object();
rShares[3].should.have.property('i').and.be.a.Number();
rShares[3].should.have.property('j').and.be.a.Number();
rShares[3].should.have.property('r').and.be.a.String();
rShares[3].should.have.property('R').and.be.a.String();
});
it('should fail if the Pshare doesnt belong to the User', async function () {
const invalidUserSigningMaterial = JSON.parse(
'{"uShare":{"i":2,"t":2,"n":3,"y":"e2b844934b56f278b4a8a3665d43d14de80732241622ec7a8bd6cffc0f74452a","seed":"5259ee23a364429919f969247323eee2f4af5786457b4af67d423f8944d3a691","chaincode":"7460de17d732969c3bc9bddbac1055aff168fad5668917b8ed3fd9628fc6e4f8"},"bitgoYShare":{"i":2,"j":3,"y":"141fd5cbb901d46b8c2c783f3d4ee968ae91c38f71aba05146b3ba8bd4309596","u":"581cfacb3de956cc434a35a3ac927f7d0a4daaef48a95c162cadb7878ef2270b","chaincode":"67d33063052606f341cae40877709de725abda41f2df7f4765e3f58ce5030e1a"},"backupYShare":{"i":2,"j":1,"y":"9e69e3e92978896e872d71ff7a9e63a963ab0f59583d4fcbe79f82cde9ea6bf9","u":"52a539f79df448a2f5108a5e410377cbd1574b7c3d9864bb310ebf7beb13460d","chaincode":"bda980c34aa06916f25c4c7934ea09a928bff7730a100902f4d53bb9236771a7"}}'
);
const signingKey = MPC.keyDerive(
invalidUserSigningMaterial.uShare,
[invalidUserSigningMaterial.bitgoYShare, invalidUserSigningMaterial.backupYShare],
path
);
await createUserSignShare(signablePayload, signingKey.pShare).should.be.rejectedWith(
'Invalid PShare, PShare doesnt belong to the User'
);
});
});
describe('sendSignatureShare:', async function () {
it('should succeed to send Signature Share', async function () {
const signatureShare = { from: 'user', to: 'bitgo', share: '128bytestring' } as SignatureShareRecord;
await nockSendSignatureShare({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare,
signerShare: 'signerShare',
});
const response = await sendSignatureShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
signatureShare,
RequestType.tx,
'signerShare'
);
response.should.deepEqual(signatureShare);
});
it('should fail to send Signature Share', async function () {
const invalidSignatureShare = { from: 'bitgo', to: 'user', share: '128bytestring' } as SignatureShareRecord;
const nock = await nockSendSignatureShare(
{
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare: invalidSignatureShare,
signerShare: 'signerShare',
},
400
);
await sendSignatureShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
invalidSignatureShare,
RequestType.tx,
'signerShare'
).should.be.rejectedWith('some error');
nock.isDone().should.equal(true);
});
});
describe('offerUserToBitgoRShare:', async function () {
it('should succeed to send Signature Share', async function () {
const signatureShare = {
from: 'user',
to: 'bitgo',
share: validUserSignShare.rShares[3].r + validUserSignShare.rShares[3].R,
} as SignatureShareRecord;
const nock = await nockSendSignatureShare({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare,
signerShare: 'signerShare',
});
await offerUserToBitgoRShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
validUserSignShare,
'signerShare'
).should.be.fulfilled();
nock.isDone().should.equal(true);
});
it('should fail if no rShare is found', async function () {
const invalidUserSignShare = _.cloneDeep(validUserSignShare) as any;
delete invalidUserSignShare.rShares[3];
await offerUserToBitgoRShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
invalidUserSignShare,
'signerShare'
).should.be.rejectedWith('userToBitgo RShare not found');
});
it('should fail if the rShare found is invalid', async function () {
const invalidUserSignShare = _.cloneDeep(validUserSignShare) as any;
invalidUserSignShare.rShares[3].i = 1;
await offerUserToBitgoRShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
invalidUserSignShare,
'signerShare'
).should.be.rejectedWith('Invalid RShare, is not from User to Bitgo');
const invalidUserSignShare2 = _.cloneDeep(validUserSignShare) as any;
invalidUserSignShare2.rShares[3].j = 3;
await offerUserToBitgoRShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
invalidUserSignShare2,
'signerShare'
).should.be.rejectedWith('Invalid RShare, is not from User to Bitgo');
});
it('should call setRequestTracer', async function () {
const signatureShare = {
from: 'user',
to: 'bitgo',
share: validUserSignShare.rShares[3].r + validUserSignShare.rShares[3].R,
} as SignatureShareRecord;
const nock = await nockSendSignatureShare({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare,
signerShare: 'signerShare',
});
const reqId = new RequestTracer();
const setRequestTracerSpy = sinon.spy(bitgo, 'setRequestTracer');
setRequestTracerSpy.withArgs(reqId);
await offerUserToBitgoRShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
validUserSignShare,
'signerShare',
undefined,
reqId
).should.be.fulfilled();
nock.isDone().should.equal(true);
sinon.assert.calledOnce(setRequestTracerSpy);
setRequestTracerSpy.restore();
});
});
describe('getBitgoToUserRShare:', async function () {
it('should succeed to get the Bitgo to User RShare', async function () {
const response = { txRequests: [txRequest] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
const bitgoToUserRShare = await getBitgoToUserRShare(bitgo, wallet.id(), txRequest.txRequestId);
bitgoToUserRShare.should.deepEqual(txRequest.signatureShares[0]);
nock.isDone().should.equal(true);
});
it('should fail if there is no bitgo to user RShare', async function () {
const invalidTxRequest = _.cloneDeep(txRequest);
invalidTxRequest.signatureShares[0].to = 'bitgo';
invalidTxRequest.signatureShares[0].from = 'user';
const response = { txRequests: [invalidTxRequest] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
await getBitgoToUserRShare(bitgo, wallet.id(), txRequest.txRequestId).should.be.rejectedWith(
'Bitgo to User RShare not found for id: ' + txRequest.txRequestId
);
nock.isDone().should.equal(true);
});
it('should fail if there is no signaturesShares', async function () {
const invalidTxRequest = _.cloneDeep(txRequest);
invalidTxRequest.signatureShares = [];
const response = { txRequests: [invalidTxRequest] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
await getBitgoToUserRShare(bitgo, wallet.id(), txRequest.txRequestId).should.be.rejectedWith(
'No signatures shares found for id: ' + txRequest.txRequestId
);
nock.isDone().should.equal(true);
});
it('should call setRequestTracer', async function () {
const response = { txRequests: [txRequest] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
const reqId = new RequestTracer();
const setRequestTracerSpy = sinon.spy(bitgo, 'setRequestTracer');
setRequestTracerSpy.withArgs(reqId);
const bitgoToUserRShare = await getBitgoToUserRShare(bitgo, wallet.id(), txRequest.txRequestId, reqId);
bitgoToUserRShare.should.deepEqual(txRequest.signatureShares[0]);
nock.isDone().should.equal(true);
sinon.assert.calledOnce(setRequestTracerSpy);
setRequestTracerSpy.restore();
});
});
describe('sendUserToBitgoGShare:', async function () {
it('should succeed to send User to Bitgo GShare', async function () {
const signatureShare = {
from: 'user',
to: 'bitgo',
share: validUserToBitgoGShare.R + validUserToBitgoGShare.gamma,
} as SignatureShareRecord;
const nock = await nockSendSignatureShare({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare,
});
await sendUserToBitgoGShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
validUserToBitgoGShare
).should.be.fulfilled();
nock.isDone().should.equal(true);
});
it('should fail when the GShare is not from the User', async function () {
const invalidUserToBitgoGShare = _.cloneDeep(validUserToBitgoGShare);
invalidUserToBitgoGShare.i = 3;
await sendUserToBitgoGShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
invalidUserToBitgoGShare
).should.be.rejectedWith('Invalid GShare, doesnt belong to the User');
});
it('should call setRequestTracer', async function () {
const signatureShare = {
from: 'user',
to: 'bitgo',
share: validUserToBitgoGShare.R + validUserToBitgoGShare.gamma,
} as SignatureShareRecord;
const nock = await nockSendSignatureShare({
walletId: wallet.id(),
txRequestId: txRequest.txRequestId,
signatureShare,
});
const reqId = new RequestTracer();
const setRequestTracerSpy = sinon.spy(bitgo, 'setRequestTracer');
setRequestTracerSpy.withArgs(reqId);
await sendUserToBitgoGShare(
bitgo,
wallet.id(),
txRequest.txRequestId,
validUserToBitgoGShare,
undefined,
reqId
).should.be.fulfilled();
nock.isDone().should.equal(true);
sinon.assert.calledOnce(setRequestTracerSpy);
setRequestTracerSpy.restore();
});
});
describe('getTxRequest:', async function () {
it('should succeed to get txRequest by id', async function () {
const response = { txRequests: [txRequest] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
const txReq = await getTxRequest(bitgo, wallet.id(), txRequest.txRequestId);
txReq.should.deepEqual(txRequest);
nock.isDone().should.equal(true);
});
it('should fail if there are no txRequests', async function () {
const response = { txRequests: [] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
await getTxRequest(bitgo, wallet.id(), txRequest.txRequestId).should.be.rejectedWith(
'Unable to find TxRequest with id randomId'
);
nock.isDone().should.equal(true);
});
it('should call setRequestTracer', async function () {
const response = { txRequests: [txRequest] };
const nock = await nockGetTxRequest({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
const reqId = new RequestTracer();
const setRequestTracerSpy = sinon.spy(bitgo, 'setRequestTracer');
setRequestTracerSpy.withArgs(reqId);
const txReq = await getTxRequest(bitgo, wallet.id(), txRequest.txRequestId, reqId);
txReq.should.deepEqual(txRequest);
nock.isDone().should.equal(true);
sinon.assert.calledOnce(setRequestTracerSpy);
setRequestTracerSpy.restore();
});
});
describe('createUserToBitGoGShare:', async function () {
it('should succeed to create a UserToBitGo GShare', async function () {
const userToBitgoGShare = await createUserToBitGoGShare(
validUserSignShare,
txRequest.signatureShares[0] as SignatureShareRecord,
validUserSigningMaterial.backupYShare,
validUserSigningMaterial.bitgoYShare,
signablePayload,
bitgoToUserCommitment
);
userToBitgoGShare.should.deepEqual(validUserToBitgoGShare);
});
it('should fail when XShare doesnt belong to the user', async function () {
const invalidUserSignShare = _.cloneDeep(validUserSignShare);
invalidUserSignShare.xShare.i = 3;
await createUserToBitGoGShare(
invalidUserSignShare,
txRequest.signatureShares[0] as SignatureShareRecord,
validUserSigningMaterial.backupYShare,
validUserSigningMaterial.bitgoYShare,
signablePayload,
bitgoToUserCommitment
).should.be.rejectedWith('Invalid XShare, doesnt belong to the User');
});
it('should fail when commitment is invalid', async function () {
const invalidBitgoToUserCommitment = _.cloneDeep(bitgoToUserCommitment);
invalidBitgoToUserCommitment.share = 'deadbeef';
await createUserToBitGoGShare(
validUserSignShare,
txRequest.signatureShares[0] as SignatureShareRecord,
validUserSigningMaterial.backupYShare,
validUserSigningMaterial.bitgoYShare,
signablePayload,
invalidBitgoToUserCommitment
).should.be.rejectedWith('Could not verify other player share');
});
it('should fail when RShare doesnt belong to Bitgo', async function () {
const invalidBitgoRShare = _.cloneDeep(txRequest.signatureShares[0]);
invalidBitgoRShare.from = 'user';
await createUserToBitGoGShare(
validUserSignShare,
invalidBitgoRShare as SignatureShareRecord,
validUserSigningMaterial.backupYShare,
validUserSigningMaterial.bitgoYShare,
signablePayload,
bitgoToUserCommitment
).should.be.rejectedWith('Invalid RShare, is not from Bitgo to User');
const invalidBitgoRShare2 = _.cloneDeep(txRequest.signatureShares[0]);
invalidBitgoRShare2.to = 'bitgo';
await createUserToBitGoGShare(
validUserSignShare,
invalidBitgoRShare2 as SignatureShareRecord,
validUserSigningMaterial.backupYShare,
validUserSigningMaterial.bitgoYShare,
signablePayload,
bitgoToUserCommitment
).should.be.rejectedWith('Invalid RShare, is not from Bitgo to User');
});
});
});
});
Выполнить команду
Для локальной разработки. Не используйте в интернете!