Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/abstract-lightning/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
]
},
"dependencies": {
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-core": "^38.10.0",
"@bitgo/statics": "^59.9.0",
"@bitgo/utxo-lib": "^11.24.2",
Expand Down
2 changes: 1 addition & 1 deletion modules/bitgo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
"superagent": "^9.0.1"
},
"devDependencies": {
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-opensslbytes": "^2.1.0",
"@bitgo/sdk-test": "^9.1.70",
"@openpgp/web-stream-tools": "0.0.14",
Expand Down
2 changes: 1 addition & 1 deletion modules/express/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"superagent": "^9.0.1"
},
"devDependencies": {
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-lib-mpc": "^10.17.0",
"@bitgo/sdk-test": "^9.1.70",
"@types/argparse": "^1.0.36",
Expand Down
2 changes: 1 addition & 1 deletion modules/passkey-crypto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"access": "public"
},
"dependencies": {
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-core": "^38.10.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion modules/sdk-coin-flrp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"nock": "^13.3.1"
},
"dependencies": {
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-core": "^38.10.0",
"@bitgo/secp256k1": "^1.11.0",
"@bitgo/statics": "^59.9.0",
Expand Down
2 changes: 1 addition & 1 deletion modules/sdk-coin-sol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
},
"dependencies": {
"@bitgo/logger": "^1.4.0",
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-core": "^38.10.0",
"@bitgo/sdk-lib-mpc": "^10.17.0",
"@bitgo/statics": "^59.9.0",
Expand Down
2 changes: 1 addition & 1 deletion modules/sdk-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
]
},
"dependencies": {
"@bitgo/public-types": "6.58.0",
"@bitgo/public-types": "6.63.0",
"@bitgo/sdk-lib-mpc": "^10.17.0",
"@bitgo/secp256k1": "^1.11.0",
"@bitgo/sjcl": "^1.1.0",
Expand Down
9 changes: 8 additions & 1 deletion modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,14 @@ export interface MessagePrep {
encodeMessage(message: string): string;
}

export type MPCAlgorithm = 'ecdsa' | 'eddsa';
/**
* 'redpallas' is a DKG-only MPC algorithm (no signing support in this SDK) used for the
* Zcash Orchard shielded pool. It is additive: existing coins never return it from
* `getMPCAlgorithm()` unless explicitly implemented to do so, so this does not change
* behavior for any existing ECDSA/EdDSA coin or for ZEC's existing transparent
* (secp256k1) multisig/TSS flows.
*/
export type MPCAlgorithm = 'ecdsa' | 'eddsa' | 'redpallas';

export type NFTTransferOptions = {
tokenContractAddress: string;
Expand Down
24 changes: 22 additions & 2 deletions modules/sdk-core/src/bitgo/tss/bitgoPubKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,32 @@ export const bitgoMpcGpgPubKeys = {
prod: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxjMEafDHRxYJKwYBBAHaRw8BAQdA4veo9hvphbH0gq+YFo8AwdtTR6SQN4tJ\nOWiA++eBqMvNBUJpdEdvwoQEExYKADYFgmnwx1UCCwkJkM4UKK9zJ+KPAhUK\nAhYAApsDAh4BFiEEB3Cyce1GqKAWbPdJzhQor3Mn4o8AAKS2AQDSo5ubHHyx\nvlAyRUgiyzVvupK8x1Jl/fPf54CHsWlIfgD+OIi8v+73cUoHTW3YxC3B9aPO\nqzAEV58w76dgZ2qeTgjChAQQEwgANgWCafDHVgILCQmQjcXpcUn3c9gCFQoC\nFgACmwMCHgEWIQS4vN2O383+kvuFGdaNxelxSfdz2AAAoVUA/A6NI89QMuvO\ngtX65BnmHP+D8vBJbwTwazDHpS0H62/SAPwJVaRXrRNkOTzc6bcAxg97sFBw\nhxJFzcFpAY0BaT5ods44BGnwx0gSCisGAQQBl1UBBQEBB0DZ18qpCkv6tiua\nCCf4Ct9Yfas7EilWG8LPNevujNh7EAMBCAfChQQYFgoANwWCafDHVgILCQmQ\nzhQor3Mn4o8CFQoCFgADmwQIAh4BFiEEB3Cyce1GqKAWbPdJzhQor3Mn4o8A\nAPBxAQD9MYbwZ6NxRabvF1lFMOAofAM4N8htqy6T0ZItfIt6KgEA9K3sycqT\nnWEFPCkJ1hl6QeCnp0qjGcbLxLRVGTWwxwrOMwRp8MdIFgkrBgEEAdpHDwEB\nB0DYMGRlbkTErdLqeeroxGghkYpoTNPHmgb5barxfnu2oMLASgQYFgoAvAWC\nafDHVgILCQmQzhQor3Mn4o8CFQoCFgACmwICHgGFoAQYFgoANgWCafDHVgIL\nCQmQU3o2I0o7U2YCFQoCFgACmwICHgEWIQRREfH7DgNjyYJM1c9TejYjSjtT\nZgAAa4ABAIPcFd0PzHQIQiMW/mvk57vQeOTSJmnY+/aXZ58ba3ykAP4oC5Mv\nRlTjUAmQdd67FX/Kmm49ayKKExrbUxMCHopGDBYhBAdwsnHtRqigFmz3Sc4U\nKK9zJ+KPAACetAEA0KpGMATxFZto3zinmPaHJAmc33RShm9mQJ7XkN8eIPMB\nAMK9J0qdW9jR7iOmJvLmULqUEAYWHAKJ1Ey9PWDSmUwM\n=REv+\n-----END PGP PUBLIC KEY BLOCK-----\n',
},
},
// NOTE: RedPallas DKG uses the same GPG key type as EdDSA MPCv2 (an ed25519-identity GPG key
// with an X25519 encryption subkey - see `RedPallasDKG` in `@bitgo/sdk-lib-mpc`), so as an
// interim measure this reuses the `eddsaMpcv2` key material verbatim rather than fabricating
// new key material. BitGo's platform/security team should provision dedicated RedPallas
// MPCv2 GPG keys (distinct key pairs held by the nitro/onprem HSM infra) before this is used
// for a production ceremony; swap the values below for the dedicated keys once available.
redpallasMpcv2: {
nitro: {
test: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxjMEae9GZBYJKwYBBAHaRw8BAQdASKNi5MpJRAvINROrOEYFGmJcYKzW3WM7\nkIPow2z0P/bNGGhzbSA8aHNtQHRlc3QuYml0Z28uY29tPsKEBBMWCgA2BYJp\n70Z8AgsJCZDqsFQZg1ASRAIVCgIWAAKbAwIeARYhBLHdfJtdM3kc4o7/wuqw\nVBmDUBJEAAB6WgD/XYI8GR6BZl32N4fu6VZiJ4Ean7ahPCZ+eKYuc8qnJeMB\nAIYqc0Tw9QcqvgrrZtqizUfbYzJDZjNY2R51LrszLFAOwoQEEBMIADYFgmnv\nRnwCCwkJkJsMk/69BgLvAhUKAhYAApsDAh4BFiEE1QB10qpW/55I4JfamwyT\n/r0GAu8AAGVbAP9l4Ffwk1MRYwMSgsXQdJIY8srwSrWaJqFavRZi2tl0iwD+\nJaJdr2DcPP6Pb/zq4kh7YnhjrEgHv2Ta4qTTJtEEq+bOOARp70ZkEgorBgEE\nAZdVAQUBAQdA7gOSvYvpCo8TmgPBHeTqlPDJpohcuPXYMRQ5g228WRgDAQgH\nwoUEGBYKADcFgmnvRnwCCwkJkOqwVBmDUBJEAhUKAhYAA5sECAIeARYhBLHd\nfJtdM3kc4o7/wuqwVBmDUBJEAADrrQD+N+V+lJLtaC3W6E1pHQhr9I+0FsdJ\n5+dQFcacKPls3k0A/0Jp6WA+BUcErw4ahkm4hkbbjbuwRLG9H4PSJfoFgccH\nzjMEae9GZBYJKwYBBAHaRw8BAQdAa3z6M5sueZ+yaWp6jQ5GCqo53k4dkGxg\npj1kB9XTYvTCwEoEGBYKALwFgmnvRnwCCwkJkOqwVBmDUBJEAhUKAhYAApsC\nAh4BhaAEGBYKADYFgmnvRnwCCwkJkA35LiZC8HBmAhUKAhYAApsCAh4BFiEE\n0Xa0VhKDLiNQVIiaDfkuJkLwcGYAAIODAQD+YEcJeL0Wi8jY5bdJXzE8lRkE\noikaQMn3pR6dPtL9SwD/eXJamcMAS6L59dawdD0gwCZn9GlKXmj6FFXEJdcd\nOQoWIQSx3XybXTN5HOKO/8LqsFQZg1ASRAAAiU4A/ji0YOT8ceTgDQn3a5P4\nRz9Fv+OUZxj9hMc8K1lB0N/FAQDgv6gXtzEnpGOjtiwPNuuRynnh9OeXzhgL\nPcQIOmW6DA==\n=FAug\n-----END PGP PUBLIC KEY BLOCK-----\n',
prod: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxjMEae97HxYJKwYBBAHaRw8BAQdAkqY/gBSnHQ0bJv6Yik473lXLulCWdhW2\nyEjNq+YEf1bNC0JpdEdvIE5pdHJvwoQEExYKADYFgmnveyICCwkJkKw4yRSD\nFu2mAhUKAhYAApsDAh4BFiEEropjTBjLvFsKdb8ErDjJFIMW7aYAACjjAQC7\n5Sc9kjLdScHTbzsM4l90i9lyHFdTVbruSYvmZrHQAAEAusZMX2qpIJdOdtB7\nyiXeCEMxBm1PcdfdvDSGnUruRQ7ChAQQEwgANgWCae97IgILCQmQtCPvhcuG\nfK8CFQoCFgACmwMCHgEWIQSH0CHgaKWZ1TGhqs+0I++Fy4Z8rwAAM9QA/Ap9\n6YjnvCrv1nO0XT/mqUgSMirGzF6AIk//AfqC8kKHAPsH5I9fKTz8i8vWo6ES\nDSVilnIaEyV6sczxZ2drsLV0Ms44BGnvex8SCisGAQQBl1UBBQEBB0DzGVFB\n74c3y9lShX5DG8or1nJoyjpmb7+aZ710EO7YQwMBCAfChQQYFgoANwWCae97\nIgILCQmQrDjJFIMW7aYCFQoCFgADmwQIAh4BFiEEropjTBjLvFsKdb8ErDjJ\nFIMW7aYAAHthAQCPwozH6edvb4G6JRLFrX8i0rEqCje1yty9sXcwI6XQdwD/\nTm38FbU3qGPop4tePWBTEQYEhE5ams9MIWyvX5P0TA7OMwRp73sfFgkrBgEE\nAdpHDwEBB0AMfvO8IOn4Y9TEtx7IQeutQkgFKapa+jZlVcSmGm8yBsLASgQY\nFgoAvAWCae97IgILCQmQrDjJFIMW7aYCFQoCFgACmwICHgGFoAQYFgoANgWC\nae97IgILCQmQVobXdL8ULVQCFQoCFgACmwICHgEWIQQ+ApqjNkpq4BvXiLdW\nhtd0vxQtVAAAzL8A/2ZASI7HhAAYTmNXvTBRSkfGlgPrurY9cXnwvaUN3Mss\nAP9dCqsaPx6XY5z4GGpGMLVJx4gOu9kpLIonHnZVI6idDhYhBK6KY0wYy7xb\nCnW/BKw4yRSDFu2mAACiPAEA1lDVNbiG0nZFbgatcFF5xKd0urF0f9CpOfpB\ntrIGGbUBAOD7FkKLVXWGFYICYipOUzzGzpFiMNaJl1qbCpa9m1kN\n=R6r4\n-----END PGP PUBLIC KEY BLOCK-----\n',
},
onprem: {
test: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxjMEad+QCxYJKwYBBAHaRw8BAQdAG0FBM/1JRvo7KlLvhp1Mwi6IWmV3V9xy\nZZcByg0fDQ3NGGhzbSA8aHNtQHRlc3QuYml0Z28uY29tPsKEBBMWCgA2BYJp\n35AMAgsJCZCuV6d9sal31QIVCgIWAAKbAwIeARYhBKSiXcKo4xMT5wwfh65X\np32xqXfVAAA2sAEAgmk543UetoUoOoOvEAhOrRBbF4h6VwcH9cyR9UGSwygA\n/2KJJadiAvaepqFZxyE77rFM7ZfqhRMsoAc2MfslvuQMwoQEEBMIADYFgmnf\nkA0CCwkJkN2vJwOOuE03AhUKAhYAApsDAh4BFiEEjMSQwTRbUtG1fSvR3a8n\nA464TTcAANNVAQD1RTu/bJmPBRvWbvuIiuT1WUxYsSuoXWwki1YImN1gMAD+\nOPU+v056hkdoD8Rcd8D+HhoNlJAbRbZWg/qjxr+S6lLOOARp35AMEgorBgEE\nAZdVAQUBAQdAgqwA9UhQGuseztLr2ZM189pBjrW6sAJ5m6icDYOWMHEDAQgH\nwoUEGBYKADcFgmnfkAwCCwkJkK5Xp32xqXfVAhUKAhYAA5sECAIeARYhBKSi\nXcKo4xMT5wwfh65Xp32xqXfVAAC4uwEAlkVzGDPJYETIV4pXYpCdaeGLBjm9\ny1sRb2nx9ET7m+4BANpb0vKKBrKZTAx/+rINgWoxKPnKPsycOE8bYHY3zKAN\nzjMEad+QDBYJKwYBBAHaRw8BAQdAanwKEY5QEAPafbhM5/BIJZRyLmyNpBTo\ntntTIq0nOt/CwEoEGBYKALwFgmnfkA0CCwkJkK5Xp32xqXfVAhUKAhYAApsC\nAh4BhaAEGBYKADYFgmnfkA0CCwkJkAuXAU6A6KYvAhUKAhYAApsCAh4BFiEE\neaGtxZYsjWFFYrD6C5cBToDopi8AAEp3AQCP4bCSYbhjNJfGnCCOq24DaozR\nUFg0hNlpfSA9NYZ3bwD/fdtV5m5a1QyvcyGEnv37l1H7UGbQlG1Zp8roqZh3\nqwMWIQSkol3CqOMTE+cMH4euV6d9sal31QAAMegA/i3sBuAwvrBsp8ozp7O2\nzQlIbjuvDBMomIXj1rRmgoOkAQDRqsQpAvITd0LMFN2dCqCBIGAeIqznFX0C\nyqvU0m8sCQ==\n=/R3k\n-----END PGP PUBLIC KEY BLOCK-----\n',
prod: '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxjMEafDHRxYJKwYBBAHaRw8BAQdA4veo9hvphbH0gq+YFo8AwdtTR6SQN4tJ\nOWiA++eBqMvNBUJpdEdvwoQEExYKADYFgmnwx1UCCwkJkM4UKK9zJ+KPAhUK\nAhYAApsDAh4BFiEEB3Cyce1GqKAWbPdJzhQor3Mn4o8AAKS2AQDSo5ubHHyx\nvlAyRUgiyzVvupK8x1Jl/fPf54CHsWlIfgD+OIi8v+73cUoHTW3YxC3B9aPO\nqzAEV58w76dgZ2qeTgjChAQQEwgANgWCafDHVgILCQmQjcXpcUn3c9gCFQoC\nFgACmwMCHgEWIQS4vN2O383+kvuFGdaNxelxSfdz2AAAoVUA/A6NI89QMuvO\ngtX65BnmHP+D8vBJbwTwazDHpS0H62/SAPwJVaRXrRNkOTzc6bcAxg97sFBw\nhxJFzcFpAY0BaT5ods44BGnwx0gSCisGAQQBl1UBBQEBB0DZ18qpCkv6tiua\nCCf4Ct9Yfas7EilWG8LPNevujNh7EAMBCAfChQQYFgoANwWCafDHVgILCQmQ\nzhQor3Mn4o8CFQoCFgADmwQIAh4BFiEEB3Cyce1GqKAWbPdJzhQor3Mn4o8A\nAPBxAQD9MYbwZ6NxRabvF1lFMOAofAM4N8htqy6T0ZItfIt6KgEA9K3sycqT\nnWEFPCkJ1hl6QeCnp0qjGcbLxLRVGTWwxwrOMwRp8MdIFgkrBgEEAdpHDwEB\nB0DYMGRlbkTErdLqeeroxGghkYpoTNPHmgb5barxfnu2oMLASgQYFgoAvAWC\nafDHVgILCQmQzhQor3Mn4o8CFQoCFgACmwICHgGFoAQYFgoANgWCafDHVgIL\nCQmQU3o2I0o7U2YCFQoCFgACmwICHgEWIQRREfH7DgNjyYJM1c9TejYjSjtT\nZgAAa4ABAIPcFd0PzHQIQiMW/mvk57vQeOTSJmnY+/aXZ58ba3ykAP4oC5Mv\nRlTjUAmQdd67FX/Kmm49ayKKExrbUxMCHopGDBYhBAdwsnHtRqigFmz3Sc4U\nKK9zJ+KPAACetAEA0KpGMATxFZto3zinmPaHJAmc33RShm9mQJ7XkN8eIPMB\nAMK9J0qdW9jR7iOmJvLmULqUEAYWHAKJ1Ey9PWDSmUwM\n=REv+\n-----END PGP PUBLIC KEY BLOCK-----\n',
},
},
};

export function getBitgoMpcGpgPubKey(
env: EnvironmentName,
pubKeyType: 'nitro' | 'onprem',
mpcVersion: 'mpcv1' | 'mpcv2' | 'eddsaMpcv2'
mpcVersion: 'mpcv1' | 'mpcv2' | 'eddsaMpcv2' | 'redpallasMpcv2'
): string {
assert(
mpcVersion in bitgoMpcGpgPubKeys,
`Invalid mpcVersion in getBitgoMpcGpgPubKey, got: ${mpcVersion}, expected: mpcv1, mpcv2, or eddsaMpcv2`
`Invalid mpcVersion in getBitgoMpcGpgPubKey, got: ${mpcVersion}, expected: mpcv1, mpcv2, eddsaMpcv2, or redpallasMpcv2`
);
assert(
pubKeyType in bitgoMpcGpgPubKeys[mpcVersion],
Expand Down Expand Up @@ -72,6 +88,10 @@ export function isBitgoEddsaMpcv2PubKey(key: string): boolean {
return Object.values(bitgoMpcGpgPubKeys.eddsaMpcv2).some((envKeys) => Object.values(envKeys).includes(key));
}

export function isBitgoRedpallasMpcv2PubKey(key: string): boolean {
return Object.values(bitgoMpcGpgPubKeys.redpallasMpcv2).some((envKeys) => Object.values(envKeys).includes(key));
}

export function envRequiresBitgoPubGpgKeyConfig(env: EnvironmentName): boolean {
return env === 'prod' || env === 'test' || env === 'staging' || env === 'adminProd' || env === 'adminTest';
}
3 changes: 2 additions & 1 deletion modules/sdk-core/src/bitgo/tss/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import openpgp from 'openpgp';
import { MPCv2SigningState } from '@bitgo/public-types';
import { BitGoBase } from '../bitgoBase';
import { TxRequestChallengeResponse } from './types';
import { MPCAlgorithm } from '../baseCoin';
import {
RequestType,
TxRequest,
Expand Down Expand Up @@ -144,7 +145,7 @@ export async function sendSignatureShareV2(
txRequestId: string,
signatureShares: SignatureShareRecord[],
requestType: RequestType,
mpcAlgorithm: 'eddsa' | 'ecdsa',
mpcAlgorithm: MPCAlgorithm,
signerGpgPublicKey: string,
signerShare?: string,
multisigTypeVersion?: 'MPCv2' | undefined,
Expand Down
13 changes: 10 additions & 3 deletions modules/sdk-core/src/bitgo/utils/opengpgUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ export type AuthEncMessage = {
* @param {BitGoBase} bitgo BitGo object
* @return {Key} public gpg key
*/
export async function getBitgoGpgPubKey(
bitgo: BitGoBase
): Promise<{ mpcV1: Key; mpcV2: Key | undefined; eddsaMpcV2: Key | undefined }> {
export async function getBitgoGpgPubKey(bitgo: BitGoBase): Promise<{
mpcV1: Key;
mpcV2: Key | undefined;
eddsaMpcV2: Key | undefined;
redpallasMpcV2: Key | undefined;
}> {
const constants = await bitgo.fetchConstants();
if (!constants.mpc || !constants.mpc.bitgoPublicKey) {
throw new Error('Unable to create MPC keys - bitgoPublicKey is missing from constants');
Expand All @@ -50,10 +53,14 @@ export async function getBitgoGpgPubKey(
const bitgoEddsaMpcv2PublicKeyStr = constants.mpc.bitgoEddsaMpcv2PublicKey
? await readKey({ armoredKey: constants.mpc.bitgoEddsaMpcv2PublicKey as string })
: undefined;
const bitgoRedpallasMpcv2PublicKeyStr = constants.mpc.bitgoRedpallasMpcv2PublicKey
? await readKey({ armoredKey: constants.mpc.bitgoRedpallasMpcv2PublicKey as string })
: undefined;
return {
mpcV1: await readKey({ armoredKey: bitgoPublicKeyStr }),
mpcV2: bitgoMPCv2PublicKeyStr,
eddsaMpcV2: bitgoEddsaMpcv2PublicKeyStr,
redpallasMpcV2: bitgoRedpallasMpcv2PublicKeyStr,
};
}

Expand Down
42 changes: 35 additions & 7 deletions modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
protected bitgoPublicGpgKey: openpgp.Key;
protected bitgoMPCv2PublicGpgKey: openpgp.Key | undefined;
protected bitgoEddsaMpcv2PublicGpgKey: openpgp.Key | undefined;
protected bitgoRedpallasMpcv2PublicGpgKey: openpgp.Key | undefined;

constructor(bitgo: BitGoBase, baseCoin: IBaseCoin, wallet?: IWallet) {
super(bitgo, baseCoin);
Expand All @@ -71,7 +72,7 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
}

protected async setBitgoGpgPubKey(bitgo) {
const { mpcV1, mpcV2, eddsaMpcV2 } = await getBitgoGpgPubKey(bitgo);
const { mpcV1, mpcV2, eddsaMpcV2, redpallasMpcV2 } = await getBitgoGpgPubKey(bitgo);
// Do not unset the MPCv1 key if it is already set. This is to avoid unsetting if extra constants api calls fail.
if (mpcV1 !== undefined) {
this.bitgoPublicGpgKey = mpcV1;
Expand All @@ -84,13 +85,18 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
if (eddsaMpcV2 !== undefined) {
this.bitgoEddsaMpcv2PublicGpgKey = eddsaMpcV2;
}
// Do not unset the RedPallas MPCv2 key if it is already set
if (redpallasMpcV2 !== undefined) {
this.bitgoRedpallasMpcv2PublicGpgKey = redpallasMpcV2;
}
}

public async pickBitgoPubGpgKeyForSigning(
isMpcv2: boolean,
reqId?: IRequestTracer,
enterpriseId?: string,
isEddsaMpcv2?: boolean
isEddsaMpcv2?: boolean,
isRedpallasMpcv2?: boolean
): Promise<openpgp.Key> {
let bitgoGpgPubKey;
try {
Expand All @@ -102,7 +108,7 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
armoredKey: getBitgoMpcGpgPubKey(
this.bitgo.getEnv(),
bitgoKeyChain.hsmType === 'nitro' ? 'nitro' : 'onprem',
isEddsaMpcv2 ? 'eddsaMpcv2' : isMpcv2 ? 'mpcv2' : 'mpcv1'
isRedpallasMpcv2 ? 'redpallasMpcv2' : isEddsaMpcv2 ? 'eddsaMpcv2' : isMpcv2 ? 'mpcv2' : 'mpcv1'
),
});
} catch (e) {
Expand All @@ -112,7 +118,10 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
);
// First try to get the key based on feature flags, if that fails, fallback to the default key from constants api.
bitgoGpgPubKey = await this.getBitgoGpgPubkeyBasedOnFeatureFlags(enterpriseId, isMpcv2, reqId)
.then(async ({ mpcv2PublicKey, eddsaMpcv2PublicKey }) => {
.then(async ({ mpcv2PublicKey, eddsaMpcv2PublicKey, redpallasMpcv2PublicKey }) => {
if (isRedpallasMpcv2) {
return redpallasMpcv2PublicKey ?? (await this.getBitgoRedpallasMpcv2PublicGpgKey());
}
if (isEddsaMpcv2) {
return eddsaMpcv2PublicKey ?? (await this.getBitgoEddsaMpcv2PublicGpgKey());
}
Expand All @@ -121,6 +130,9 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
);
})
.catch(async () => {
if (isRedpallasMpcv2) {
return this.getBitgoRedpallasMpcv2PublicGpgKey();
}
if (isEddsaMpcv2) {
return this.getBitgoEddsaMpcv2PublicGpgKey();
}
Expand Down Expand Up @@ -171,6 +183,18 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
return this.bitgoEddsaMpcv2PublicGpgKey;
}

async getBitgoRedpallasMpcv2PublicGpgKey(): Promise<openpgp.Key> {
if (!this.bitgoRedpallasMpcv2PublicGpgKey) {
// retry getting bitgo's gpg key
await this.setBitgoGpgPubKey(this.bitgo);
if (!this.bitgoRedpallasMpcv2PublicGpgKey) {
throw new Error("Failed to get Bitgo's RedPallas MPCv2 gpg key");
}
}

return this.bitgoRedpallasMpcv2PublicGpgKey;
}

async createBitgoHeldBackupKeyShare(
userGpgKey: SerializedKeyPair<string>,
enterprise: string | undefined
Expand Down Expand Up @@ -598,7 +622,8 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
/**
* It gets the appropriate BitGo GPG public keys for key creation based on a
* combination of coin and the feature flags on the user and their enterprise if set.
* Returns both the default MPCv2 key and the EdDSA-specific MPCv2 key (if present).
* Returns the default MPCv2 key, the EdDSA-specific MPCv2 key, and the RedPallas-specific
* MPCv2 key (each if present).
* @param enterpriseId - enterprise under which user wants to create the wallet
* @param isMPCv2 - true to get the MPCv2 GPG public key, defaults to false
* @param reqId - request tracer request id
Expand All @@ -607,7 +632,7 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
enterpriseId: string | undefined,
isMPCv2 = false,
reqId?: IRequestTracer
): Promise<{ mpcv2PublicKey: Key; eddsaMpcv2PublicKey: Key | undefined }> {
): Promise<{ mpcv2PublicKey: Key; eddsaMpcv2PublicKey: Key | undefined; redpallasMpcv2PublicKey: Key | undefined }> {
const reqTracer = reqId || new RequestTracer();
this.bitgo.setRequestTracer(reqTracer);
const response: BitgoGPGPublicKey = await this.bitgo
Expand All @@ -621,7 +646,10 @@ export default class BaseTssUtils<KeyShare> extends MpcUtils implements ITssUtil
const eddsaMpcv2PublicKey = response.eddsaMpcv2PublicKey
? await readKey({ armoredKey: response.eddsaMpcv2PublicKey })
: undefined;
return { mpcv2PublicKey, eddsaMpcv2PublicKey };
const redpallasMpcv2PublicKey = response.redpallasMpcv2PublicKey
? await readKey({ armoredKey: response.redpallasMpcv2PublicKey })
: undefined;
return { mpcv2PublicKey, eddsaMpcv2PublicKey, redpallasMpcv2PublicKey };
}

/**
Expand Down
1 change: 1 addition & 0 deletions modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,7 @@ export interface BitgoGPGPublicKey {
publicKey: string;
mpcv2PublicKey?: string;
eddsaMpcv2PublicKey?: string;
redpallasMpcv2PublicKey?: string;
enterpriseId: string;
}

Expand Down
1 change: 1 addition & 0 deletions modules/sdk-core/src/bitgo/utils/tss/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import TssUtils, { TssUtilsTypes, EddsaUtilsTypes } from './eddsa';
export * as ECDSAUtils from './ecdsa';
export * as EDDSAUtils from './eddsa';
export * as RedpallasUtils from './redpallas';

/** @deprecated use EDDSAUtils */
export { TssUtils };
Expand Down
Loading
Loading