PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-core/src/bitgo/utils/tss/ecdsa/SMC
Просмотр файла: utils.ts
import assert from 'assert';
import {
BitgoToOVC1Round1Response,
BitgoToOVC1Round2Response,
BitgoToOVC1Round3Response,
KeyCreationMPCv2StateEnum,
MPCv2KeyGenRound1Response,
MPCv2KeyGenRound2Response,
MPCv2KeyGenRound3Response,
OVC1ToBitgoRound3Payload,
OVC2ToBitgoRound1Payload,
OVC2ToBitgoRound2Payload,
OVCIndexEnum,
} from '@bitgo/public-types';
import { IBaseCoin } from '../../../../baseCoin';
import { BitGoBase } from '../../../../bitgoBase';
import { EcdsaMPCv2Utils } from '../ecdsaMPCv2';
import { decodeOrElse, Keychain } from '../../../..';
import { EcdsaMPCv2KeyGenSendFn, KeyGenSenderForEnterprise } from '../ecdsaMPCv2KeyGenSender';
export class MPCv2SMCUtils {
private MPCv2Utils: EcdsaMPCv2Utils;
constructor(private bitgo: BitGoBase, private baseCoin: IBaseCoin) {
this.MPCv2Utils = new EcdsaMPCv2Utils(bitgo, baseCoin);
}
public async keyGenRound1(enterprise: string, payload: OVC2ToBitgoRound1Payload): Promise<BitgoToOVC1Round1Response> {
return this.keyGenRound1BySender(KeyGenSenderForEnterprise(this.bitgo, enterprise), payload);
}
public async keyGenRound2(enterprise: string, payload: OVC2ToBitgoRound2Payload): Promise<BitgoToOVC1Round2Response> {
return this.keyGenRound2BySender(KeyGenSenderForEnterprise(this.bitgo, enterprise), payload);
}
public async keyGenRound3(enterprise: string, payload: OVC1ToBitgoRound3Payload): Promise<BitgoToOVC1Round3Response> {
return this.keyGenRound3BySender(KeyGenSenderForEnterprise(this.bitgo, enterprise), payload);
}
public async keyGenRound1BySender(
senderFn: EcdsaMPCv2KeyGenSendFn<MPCv2KeyGenRound1Response>,
payload: OVC2ToBitgoRound1Payload
): Promise<BitgoToOVC1Round1Response> {
assert(
payload.state === KeyCreationMPCv2StateEnum.WaitingForBitgoRound1Data,
`Invalid state for round 1, expected: ${KeyCreationMPCv2StateEnum.WaitingForBitgoRound1Data}, got: ${payload.state}`
);
decodeOrElse(OVC2ToBitgoRound1Payload.name, OVC2ToBitgoRound1Payload, payload, (errors) => {
throw new Error(`error(s) parsing payload: ${errors}`);
});
const ovc1 = payload.ovc[OVCIndexEnum.ONE];
const ovc2 = payload.ovc[OVCIndexEnum.TWO];
const userGpgPublicKey = ovc1.gpgPubKey;
const backupGpgPublicKey = ovc2.gpgPubKey;
const messages = { p2pMessages: [], broadcastMessages: [ovc1.ovcMsg1, ovc2.ovcMsg1] };
const result = await this.MPCv2Utils.sendKeyGenerationRound1BySender(
senderFn,
userGpgPublicKey,
backupGpgPublicKey,
messages
);
const response = {
state: KeyCreationMPCv2StateEnum.WaitingForOVC1Round2Data,
tssVersion: payload.tssVersion,
walletType: payload.walletType,
coin: payload.coin,
ovc: payload.ovc,
platform: {
walletGpgPubKeySigs: result.walletGpgPubKeySigs,
sessionId: result.sessionId,
bitgoMsg1: this.MPCv2Utils.formatBitgoBroadcastMessage(result.bitgoMsg1),
ovc: {
[OVCIndexEnum.ONE]: { bitgoToOvcMsg2: this.MPCv2Utils.formatP2PMessage(result.bitgoToUserMsg2) },
[OVCIndexEnum.TWO]: { bitgoToOvcMsg2: this.MPCv2Utils.formatP2PMessage(result.bitgoToBackupMsg2) },
},
},
};
return decodeOrElse(BitgoToOVC1Round1Response.name, BitgoToOVC1Round1Response, response, (errors) => {
throw new Error(`error(s) parsing response: ${errors}`);
});
}
public async keyGenRound2BySender(
senderFn: EcdsaMPCv2KeyGenSendFn<MPCv2KeyGenRound2Response>,
payload: OVC2ToBitgoRound2Payload
): Promise<BitgoToOVC1Round2Response> {
assert(
payload.state === KeyCreationMPCv2StateEnum.WaitingForBitgoRound2Data,
`Invalid state for round 2, expected: ${KeyCreationMPCv2StateEnum.WaitingForBitgoRound2Data}, got: ${payload.state}`
);
decodeOrElse(OVC2ToBitgoRound2Payload.name, OVC2ToBitgoRound2Payload, payload, (errors) => {
throw new Error(`error(s) parsing payload: ${errors}`);
});
const ovc1 = payload.ovc[OVCIndexEnum.ONE];
const ovc2 = payload.ovc[OVCIndexEnum.TWO];
const sessionId = payload.platform.sessionId;
const messages = { p2pMessages: [ovc1.ovcToBitgoMsg2, ovc2.ovcToBitgoMsg2], broadcastMessages: [] };
const result = await this.MPCv2Utils.sendKeyGenerationRound2BySender(senderFn, sessionId, messages);
const response = {
state: KeyCreationMPCv2StateEnum.WaitingForOVC1Round3aData,
tssVersion: payload.tssVersion,
walletType: payload.walletType,
coin: payload.coin,
ovc: payload.ovc,
platform: {
...payload.platform,
sessionId: result.sessionId,
bitgoCommitment2: result.bitgoCommitment2,
ovc: {
[OVCIndexEnum.ONE]: {
...payload.platform.ovc[OVCIndexEnum.ONE],
bitgoToOvcMsg3: this.MPCv2Utils.formatP2PMessage(result.bitgoToUserMsg3),
},
[OVCIndexEnum.TWO]: {
...payload.platform.ovc[OVCIndexEnum.TWO],
bitgoToOvcMsg3: this.MPCv2Utils.formatP2PMessage(result.bitgoToBackupMsg3),
},
},
},
};
return decodeOrElse(BitgoToOVC1Round2Response.name, BitgoToOVC1Round2Response, response, (errors) => {
throw new Error(`error(s) parsing response: ${errors}`);
});
}
public async keyGenRound3BySender(
senderFn: EcdsaMPCv2KeyGenSendFn<MPCv2KeyGenRound3Response>,
payload: OVC1ToBitgoRound3Payload
): Promise<BitgoToOVC1Round3Response> {
assert(
payload.state === KeyCreationMPCv2StateEnum.WaitingForBitgoRound3Data,
`Invalid state for round 3, expected: ${KeyCreationMPCv2StateEnum.WaitingForBitgoRound3Data}, got: ${payload.state}`
);
decodeOrElse(OVC1ToBitgoRound3Payload.name, OVC1ToBitgoRound3Payload, payload, (errors) => {
throw new Error(`error(s) parsing payload: ${errors}`);
});
const ovc1 = payload.ovc[OVCIndexEnum.ONE];
const ovc2 = payload.ovc[OVCIndexEnum.TWO];
const sessionId = payload.platform.sessionId;
const messages = {
p2pMessages: [ovc1.ovcToBitgoMsg3, ovc2.ovcToBitgoMsg3],
broadcastMessages: [ovc1.ovcMsg4, ovc2.ovcMsg4],
};
const result = await this.MPCv2Utils.sendKeyGenerationRound3BySender(senderFn, sessionId, messages);
const keychains = this.baseCoin.keychains();
const bitgoKeychain = await keychains.add({
source: 'bitgo',
keyType: 'tss',
commonKeychain: result.commonKeychain,
isMPCv2: true,
});
const response = {
state: KeyCreationMPCv2StateEnum.WaitingForOVC1GenerateKey,
bitGoKeyId: bitgoKeychain.id,
tssVersion: payload.tssVersion,
walletType: payload.walletType,
coin: payload.coin,
ovc: payload.ovc,
platform: {
...payload.platform,
commonKeychain: result.commonKeychain,
bitgoMsg4: this.MPCv2Utils.formatBitgoBroadcastMessage(result.bitgoMsg4),
},
};
return decodeOrElse(BitgoToOVC1Round3Response.name, BitgoToOVC1Round3Response, response, (errors) => {
throw new Error(`error(s) parsing response: ${errors}`);
});
}
public async uploadClientKeys(
bitgoKeyId: string,
userCommonKeychain: string,
backupCommonKeychain: string
): Promise<{ userKeychain: Keychain; backupKeychain: Keychain; bitgoKeychain: Keychain }> {
assert(
userCommonKeychain === backupCommonKeychain,
'Common keychain mismatch between the user and backup keychains'
);
const keychains = this.baseCoin.keychains();
const bitgoKeychain = await keychains.get({ id: bitgoKeyId });
assert(bitgoKeychain, 'Keychain not found');
assert(bitgoKeychain.source === 'bitgo', 'The keychain is not a BitGo keychain');
assert(bitgoKeychain.type === 'tss', 'BitGo keychain is not a TSS keychain');
assert(bitgoKeychain.commonKeychain, 'BitGo keychain does not have a common keychain');
assert(bitgoKeychain.commonKeychain === userCommonKeychain, 'Common keychain mismatch between the OVCs and BitGo');
const userKeychainPromise = keychains.add({
source: 'user',
keyType: 'tss',
commonKeychain: userCommonKeychain,
isMPCv2: true,
});
const backupKeychainPromise = keychains.add({
source: 'backup',
keyType: 'tss',
commonKeychain: backupCommonKeychain,
isMPCv2: true,
});
const [userKeychain, backupKeychain] = await Promise.all([userKeychainPromise, backupKeychainPromise]);
return { userKeychain, backupKeychain, bitgoKeychain };
}
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!