diff --git a/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts b/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts index 42cfc5b726..c03a238e6f 100644 --- a/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts +++ b/modules/bitgo/test/v2/unit/internal/tssUtils/ecdsa.ts @@ -994,7 +994,7 @@ describe('TSS Ecdsa Utils:', async function () { }); // Seems to be flaky on CI, failed here: https://github.com/BitGo/BitGoJS/actions/runs/5902489990/job/16010623888?pr=3822 - it.skip('createOfflineMuDeltaShare should succeed', async function () { + xit('createOfflineMuDeltaShare should succeed', async function () { const mockPassword = 'password'; const alphaLength = 1536; const deltaLength = 64; diff --git a/modules/sdk-coin-algo/package.json b/modules/sdk-coin-algo/package.json index aaceb5ed30..1959fff607 100644 --- a/modules/sdk-coin-algo/package.json +++ b/modules/sdk-coin-algo/package.json @@ -42,7 +42,6 @@ "dependencies": { "@bitgo/sdk-core": "^25.1.0", "@bitgo/statics": "^46.1.0", - "@bitgo/utxo-lib": "^9.34.0", "@hashgraph/cryptography": "1.1.2", "@stablelib/hex": "^1.0.0", "algosdk": "1.14.0", diff --git a/modules/sdk-coin-algo/src/algo.ts b/modules/sdk-coin-algo/src/algo.ts index 06c28268dc..5e50e69e84 100644 --- a/modules/sdk-coin-algo/src/algo.ts +++ b/modules/sdk-coin-algo/src/algo.ts @@ -1,7 +1,6 @@ /** * @prettier */ -import * as utxolib from '@bitgo/utxo-lib'; import * as _ from 'lodash'; import { SeedValidator } from './seedValidator'; import { coins, CoinFamily } from '@bitgo/statics'; @@ -10,7 +9,6 @@ import { AddressCoinSpecific, BaseCoin, BitGoBase, - Ed25519KeyDeriver, InvalidAddressError, InvalidKey, KeyIndices, @@ -26,6 +24,7 @@ import { UnexpectedAddressError, VerifyAddressOptions, VerifyTransactionOptions, + NotSupported, } from '@bitgo/sdk-core'; import stellar from 'stellar-sdk'; @@ -169,12 +168,12 @@ export class Algo extends BaseCoin { return true; } - /** - * Generate ed25519 key pair - * - * @param seed - * @returns {Object} object with generated pub, prv - */ + /** inheritdoc */ + deriveKeyWithSeed(): { derivationPath: string; key: string } { + throw new NotSupported('method deriveKeyWithSeed not supported for eddsa curve'); + } + + /** inheritdoc */ generateKeyPair(seed?: Buffer): KeyPair { const keyPair = seed ? new AlgoLib.KeyPair({ seed }) : new AlgoLib.KeyPair(); const keys = keyPair.getKeys(); @@ -188,6 +187,16 @@ export class Algo extends BaseCoin { }; } + /** inheritdoc */ + generateRootKeyPair(seed?: Buffer): KeyPair { + const keyPair = seed ? new AlgoLib.KeyPair({ seed }) : new AlgoLib.KeyPair(); + const keys = keyPair.getKeys(); + if (!keys.prv) { + throw new Error('Missing prv in key generation.'); + } + return { prv: keys.prv + keys.pub, pub: keys.pub }; + } + /** * Return boolean indicating whether input is valid public key for the coin. * @@ -195,7 +204,7 @@ export class Algo extends BaseCoin { * @returns {Boolean} is it valid? */ isValidPub(pub: string): boolean { - return AlgoLib.algoUtils.isValidAddress(pub); + return AlgoLib.algoUtils.isValidAddress(pub) || AlgoLib.algoUtils.isValidPublicKey(pub); } /** @@ -207,7 +216,7 @@ export class Algo extends BaseCoin { * @returns {Boolean} is it valid? */ isValidPrv(prv: string): boolean { - return AlgoLib.algoUtils.isValidSeed(prv); + return AlgoLib.algoUtils.isValidSeed(prv) || AlgoLib.algoUtils.isValidPrivateKey(prv); } /** @@ -504,23 +513,6 @@ export class Algo extends BaseCoin { return true; } - /** @inheritDoc */ - deriveKeyWithSeed({ key, seed }: { key: string; seed: string }): { derivationPath: string; key: string } { - const derivationPathInput = utxolib.crypto.hash256(Buffer.from(seed, 'utf8')).toString('hex'); - const derivationPathParts = [ - 999999, - parseInt(derivationPathInput.slice(0, 7), 16), - parseInt(derivationPathInput.slice(7, 14), 16), - ]; - const derivationPath = 'm/' + derivationPathParts.map((part) => `${part}'`).join('/'); - const derivedKey = Ed25519KeyDeriver.derivePath(derivationPath, key).key; - const keypair = new AlgoLib.KeyPair({ seed: derivedKey }); - return { - key: keypair.getAddress(), - derivationPath, - }; - } - decodeTx(txn: Buffer): unknown { return AlgoLib.algoUtils.decodeAlgoTxn(txn); } diff --git a/modules/sdk-coin-algo/src/lib/transactionBuilder.ts b/modules/sdk-coin-algo/src/lib/transactionBuilder.ts index 5f9858bfaa..d5b43a21f6 100644 --- a/modules/sdk-coin-algo/src/lib/transactionBuilder.ts +++ b/modules/sdk-coin-algo/src/lib/transactionBuilder.ts @@ -14,9 +14,11 @@ import { BaseTransactionBuilder, BuildTransactionError, InvalidTransactionError, + isValidEd25519SecretKey, isValidEd25519Seed, TransactionType, } from '@bitgo/sdk-core'; +import { algoUtils } from '.'; const MIN_FEE = 1000; // in microalgos @@ -325,9 +327,18 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder { /** @inheritdoc */ protected signImplementation({ key }: BaseKey): Transaction { - const buffKey = Utils.decodeSeed(key); - const keypair = new KeyPair({ prv: Buffer.from(buffKey.seed).toString('hex') }); - this._keyPairs.push(keypair); + try { + const buffKey = Utils.decodeSeed(key); + const keypair = new KeyPair({ prv: Buffer.from(buffKey.seed).toString('hex') }); + this._keyPairs.push(keypair); + } catch (e) { + if (algoUtils.isValidPrivateKey(key)) { + const keypair = new KeyPair({ prv: key }); + this._keyPairs.push(keypair); + } else { + throw e; + } + } return this._transaction; } @@ -371,6 +382,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder { let isValidPrivateKeyFromBytes; const isValidPrivateKeyFromHex = isValidEd25519Seed(key); const isValidPrivateKeyFromBase64 = isValidEd25519Seed(Buffer.from(key, 'base64').toString('hex')); + const isValidRootPrvKey = isValidEd25519SecretKey(key); try { const decodedSeed = Utils.decodeSeed(key); isValidPrivateKeyFromBytes = isValidEd25519Seed(Buffer.from(decodedSeed.seed).toString('hex')); @@ -378,7 +390,12 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder { isValidPrivateKeyFromBytes = false; } - if (!isValidPrivateKeyFromBytes && !isValidPrivateKeyFromHex && !isValidPrivateKeyFromBase64) { + if ( + !isValidPrivateKeyFromBytes && + !isValidPrivateKeyFromHex && + !isValidPrivateKeyFromBase64 && + !isValidRootPrvKey + ) { throw new BuildTransactionError(`Key validation failed`); } } diff --git a/modules/sdk-coin-algo/test/unit/algo.ts b/modules/sdk-coin-algo/test/unit/algo.ts index da0307c1a1..04c47dba6e 100644 --- a/modules/sdk-coin-algo/test/unit/algo.ts +++ b/modules/sdk-coin-algo/test/unit/algo.ts @@ -536,6 +536,20 @@ describe('ALGO:', function () { signed.txHex.should.equal(AlgoResources.rawTx.transfer.signed); }); + it('should sign transaction with root key', async function () { + const keypair = basecoin.generateRootKeyPair(AlgoResources.accounts.account1.secretKey); + + const signed = await basecoin.signTransaction({ + txPrebuild: { + txHex: AlgoResources.rawTx.transfer.unsigned, + keys: [keypair.pub], + addressVersion: 1, + }, + prv: keypair.prv, + }); + signed.txHex.should.equal(AlgoResources.rawTx.transfer.signed); + }); + it('should sign half signed transaction', async function () { const signed = await basecoin.signTransaction({ txPrebuild: { @@ -553,6 +567,22 @@ describe('ALGO:', function () { signed.txHex.should.equal(AlgoResources.rawTx.transfer.multisig); }); + it('should sign half signed transaction with root key', async function () { + const keypair = basecoin.generateRootKeyPair(AlgoResources.accounts.account3.secretKey); + + const signed = await basecoin.signTransaction({ + txPrebuild: { + halfSigned: { + txHex: AlgoResources.rawTx.transfer.halfSigned, + }, + keys: [AlgoResources.accounts.account1.pubKey.toString('hex'), keypair.pub], + addressVersion: 1, + }, + prv: keypair.prv, + }); + signed.txHex.should.equal(AlgoResources.rawTx.transfer.multisig); + }); + it('should verify sign params if the key array contains addresses', function () { const keys = [ AlgoResources.accounts.account1.address, @@ -620,19 +650,24 @@ describe('ALGO:', function () { basecoin.isValidPub(kp.pub).should.equal(true); basecoin.isValidPrv(kp.prv).should.equal(true); }); + }); - it('should deterministically derive keypair with seed', () => { - const derivedKeypair = basecoin.deriveKeyWithSeed({ - key: 'UBI2KNGT742KGIPHMZDJHHSADIT56HRDPVOOCCRYIETD4BAJLCBMQNSCNE', - seed: 'cold derivation seed', - }); - console.log(JSON.stringify(derivedKeypair)); + describe('Generate wallet Root key pair: ', () => { + it('should generate key pair', () => { + const kp = basecoin.generateRootKeyPair(); + basecoin.isValidPub(kp.pub).should.equal(true); + basecoin.isValidPrv(kp.prv).should.equal(true); + }); - basecoin.isValidPub(derivedKeypair.key).should.be.true(); - derivedKeypair.should.deepEqual({ - key: 'NAYUBR4HQKJBBTNNKXQIY7GMHUCHVAUH5DQ4ZVHVL67CUQLGHRWDKQAHYU', - derivationPath: "m/999999'/25725073'/5121434'", - }); + it('should generate key pair from seed', () => { + const seed = Buffer.from('9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60', 'hex'); + const kp = basecoin.generateRootKeyPair(seed); + basecoin.isValidPub(kp.pub).should.equal(true); + kp.pub.should.equal('d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a'); + basecoin.isValidPrv(kp.prv).should.equal(true); + kp.prv.should.equal( + '9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a' + ); }); }); @@ -702,4 +737,12 @@ describe('ALGO:', function () { explain.operations[0].coin.should.equals('talgo:USDC-10458941'); }); }); + + describe('deriveKeyWithSeed', function () { + it('should derive key with seed', function () { + (() => { + basecoin.deriveKeyWithSeed('test'); + }).should.throw('method deriveKeyWithSeed not supported for eddsa curve'); + }); + }); }); diff --git a/modules/sdk-coin-dot/test/unit/keypair.ts b/modules/sdk-coin-dot/test/unit/keypair.ts index 3620661cd0..e783dceab0 100644 --- a/modules/sdk-coin-dot/test/unit/keypair.ts +++ b/modules/sdk-coin-dot/test/unit/keypair.ts @@ -42,23 +42,6 @@ describe('Dot KeyPair', () => { const keyPair = new KeyPair({ pub: bs58Account.publicKey }); should.equal(keyPair.getKeys().pub, publicKeyHexString); }); - - it('should be able to derive keypair with hardened derivation', () => { - // using ed25519 (polkadot.js uses sr25519) - const keyPair = new KeyPair({ - prv: account1.secretKey, - }); - const derivationIndex = 0; - const derived = keyPair.deriveHardened(`m/0'/0'/0'/${derivationIndex}'`); - const derivedKeyPair = new KeyPair({ - prv: derived.prv || '', - }); - should.exists(derivedKeyPair.getAddress(DotAddressFormat.substrate)); - should.exists(derivedKeyPair.getKeys().prv); - should.exists(derivedKeyPair.getKeys().pub); - should.equal(derivedKeyPair.getKeys().prv?.length, 64); - should.equal(derivedKeyPair.getKeys().pub?.length, 64); - }); }); describe('KeyPair validation', () => { diff --git a/modules/sdk-coin-hbar/src/hbar.ts b/modules/sdk-coin-hbar/src/hbar.ts index a1df0cfeec..81bf8e9538 100644 --- a/modules/sdk-coin-hbar/src/hbar.ts +++ b/modules/sdk-coin-hbar/src/hbar.ts @@ -20,6 +20,7 @@ import { TokenEnablementConfig, BaseBroadcastTransactionOptions, BaseBroadcastTransactionResult, + NotSupported, } from '@bitgo/sdk-core'; import { BigNumber } from 'bignumber.js'; import * as stellar from 'stellar-sdk'; @@ -174,12 +175,12 @@ export class Hbar extends BaseCoin { } } - /** - * Generate Hedera Hashgraph key pair - * - * @param seed - * @returns {Object} object with generated pub, prv - */ + /** inheritdoc */ + deriveKeyWithSeed(): { derivationPath: string; key: string } { + throw new NotSupported('method deriveKeyWithSeed not supported for eddsa curve'); + } + + /** inheritdoc */ generateKeyPair(seed?: Buffer): KeyPair { const keyPair = seed ? new HbarKeyPair({ seed }) : new HbarKeyPair(); const keys = keyPair.getKeys(); @@ -194,6 +195,21 @@ export class Hbar extends BaseCoin { }; } + /** inheritdoc */ + async generateKeyPairAsync(seed?: Buffer): Promise { + const keyPair = seed ? new HbarKeyPair({ seed }) : new HbarKeyPair(); + const keys = keyPair.getKeys(true); + + if (!keys.prv) { + throw new Error('Keypair generation failed to generate a prv'); + } + + return { + pub: keys.pub, + prv: keys.prv, + }; + } + async parseTransaction(params: ParseTransactionOptions): Promise { return {}; } diff --git a/modules/sdk-coin-sol/test/unit/keyPair.ts b/modules/sdk-coin-sol/test/unit/keyPair.ts index 612814db6c..5d3330c786 100644 --- a/modules/sdk-coin-sol/test/unit/keyPair.ts +++ b/modules/sdk-coin-sol/test/unit/keyPair.ts @@ -2,7 +2,7 @@ import assert from 'assert'; import { KeyPair } from '../../src'; import should from 'should'; import * as testData from '../resources/sol'; -import { isValidPublicKey, isValidAddress, isValidPrivateKey } from '../../src/lib/utils'; +import { isValidPublicKey, isValidAddress } from '../../src/lib/utils'; describe('Sol KeyPair', function () { const defaultSeed = { seed: testData.accountWithSeed.seed }; @@ -158,34 +158,4 @@ describe('Sol KeyPair', function () { keyPair.verifySignature(message, signature).should.equal(false); }); }); - - describe('deriveHardened', () => { - it('should derive child key pairs', () => { - const rootKeyPair = new KeyPair(); - for (let i = 0; i < 50; i++) { - const path = `m/0'/0'/0'/${i}'`; - const derived = new KeyPair(rootKeyPair.deriveHardened(path)); - - isValidPublicKey(derived.getKeys().pub).should.be.true(); - isValidAddress(derived.getAddress()).should.be.true(); - - const derivedPrv = derived.getKeys().prv; - should.exist(derivedPrv); - isValidPrivateKey(derivedPrv as string | Uint8Array).should.be.true(); - - const rederived = new KeyPair(rootKeyPair.deriveHardened(path)); - rederived.getKeys().should.deepEqual(derived.getKeys()); - } - }); - - it('should not be able to derive without private key', () => { - const rootKeyPair = new KeyPair({ pub: testData.accountWithSeed.publicKey }); - assert.throws(() => rootKeyPair.deriveHardened("m/0'/0'/0'/0'"), /need private key to derive hardened keypair/); - }); - - it('should throw error for non-hardened path', () => { - const rootKeyPair = new KeyPair(); - assert.throws(() => rootKeyPair.deriveHardened('m/0/0/0/0'), /Invalid derivation path/); - }); - }); }); diff --git a/modules/sdk-coin-xlm/package.json b/modules/sdk-coin-xlm/package.json index 07766ac2e1..83e8b968d9 100644 --- a/modules/sdk-coin-xlm/package.json +++ b/modules/sdk-coin-xlm/package.json @@ -42,7 +42,6 @@ "dependencies": { "@bitgo/sdk-core": "^25.1.0", "@bitgo/statics": "^46.1.0", - "@bitgo/utxo-lib": "^9.34.0", "bignumber.js": "^9.1.1", "lodash": "^4.17.14", "stellar-sdk": "^10.0.1", diff --git a/modules/sdk-coin-xlm/src/xlm.ts b/modules/sdk-coin-xlm/src/xlm.ts index b2271a1d07..31cf845c98 100644 --- a/modules/sdk-coin-xlm/src/xlm.ts +++ b/modules/sdk-coin-xlm/src/xlm.ts @@ -1,6 +1,5 @@ import assert from 'assert'; import * as _ from 'lodash'; -import * as utxolib from '@bitgo/utxo-lib'; import * as querystring from 'querystring'; import * as url from 'url'; import * as request from 'superagent'; @@ -12,7 +11,6 @@ import { BitGoBase, checkKrsProvider, common, - Ed25519KeyDeriver, ExtraPrebuildParamsOptions, InvalidAddressError, InvalidMemoIdError, @@ -33,6 +31,7 @@ import { VerifyAddressOptions as BaseVerifyAddressOptions, VerifyTransactionOptions as BaseVerifyTransactionOptions, Wallet, + NotSupported, } from '@bitgo/sdk-core'; import { toBitgoRequest } from '@bitgo/sdk-api'; import { getStellarKeys } from './getStellarKeys'; @@ -209,12 +208,8 @@ export class Xlm extends BaseCoin { return 'https://horizon.stellar.org'; } - /** - * Generate a new key pair on the ed25519 curve - * @param seed - * @returns generated pub and prv - */ - generateKeyPair(seed: Buffer): KeyPair { + /** inheritdoc */ + generateKeyPair(seed?: Buffer): KeyPair { const pair = seed ? stellar.Keypair.fromRawEd25519Seed(seed) : stellar.Keypair.random(); return { pub: pair.publicKey(), @@ -222,6 +217,15 @@ export class Xlm extends BaseCoin { }; } + /** inheritdoc */ + generateRootKeyPair(seed?: Buffer): KeyPair { + const pair = seed ? stellar.Keypair.fromRawEd25519Seed(seed) : stellar.Keypair.random(); + return { + pub: pair.rawPublicKey().toString('hex'), + prv: pair.rawSecretKey().toString('hex'), + }; + } + /** * Get decoded ed25519 public key from raw data * @@ -1112,29 +1116,9 @@ export class Xlm extends BaseCoin { return true; } - /** - * Derive a hardened child public key from a master key seed using an additional seed for randomness. - * - * Due to technical differences between keypairs on the ed25519 curve and the secp256k1 curve, - * only hardened private key derivation is supported. - * - * @param key seed for the master key. Note: Not the public key or encoded private key. This is the raw seed. - * @param entropySeed random seed which is hashed to generate the derivation path - */ - deriveKeyWithSeed({ key, seed }: { key: string; seed: string }): { derivationPath: string; key: string } { - const derivationPathInput = utxolib.crypto.hash256(Buffer.from(seed, 'utf8')).toString('hex'); - const derivationPathParts = [ - 999999, - parseInt(derivationPathInput.slice(0, 7), 16), - parseInt(derivationPathInput.slice(7, 14), 16), - ]; - const derivationPath = 'm/' + derivationPathParts.map((part) => `${part}'`).join('/'); - const derivedKey = Ed25519KeyDeriver.derivePath(derivationPath, key).key; - const keypair = stellar.Keypair.fromRawEd25519Seed(derivedKey); - return { - key: keypair.publicKey(), - derivationPath, - }; + /** inheritdoc */ + deriveKeyWithSeed(): { derivationPath: string; key: string } { + throw new NotSupported('method deriveKeyWithSeed not supported for eddsa curve'); } /** diff --git a/modules/sdk-coin-xlm/test/unit/xlm.ts b/modules/sdk-coin-xlm/test/unit/xlm.ts index 436eabda56..b097f8f29a 100644 --- a/modules/sdk-coin-xlm/test/unit/xlm.ts +++ b/modules/sdk-coin-xlm/test/unit/xlm.ts @@ -891,18 +891,6 @@ describe('XLM:', function () { stellar.StrKey.encodeEd25519SecretSeed(seed).should.equal(secret); }); - it('should deterministically derive a child key from master seed and entropy seed', () => { - const seed = Buffer.alloc(32).fill(0).toString('hex'); - const masterSeed = '0x01020304050607080910111213141516171819202122232425262728293031'; - - const derivedKey = basecoin.deriveKeyWithSeed({ key: masterSeed, seed }); - - derivedKey.should.have.properties({ - key: 'GCJR3ORBWOKGFA3FTGYDDQVFEEMCYXFHY6KAUOTU4MQMFHK4LLSWWGLW', - derivationPath: "m/999999'/230673453'/206129755'", - }); - }); - it('should validate pub key', () => { const { pub } = basecoin.keychains().create(); basecoin.isValidPub(pub).should.equal(true); diff --git a/modules/sdk-core/src/account-lib/index.ts b/modules/sdk-core/src/account-lib/index.ts index a1cdc4feaa..787f4eb21b 100644 --- a/modules/sdk-core/src/account-lib/index.ts +++ b/modules/sdk-core/src/account-lib/index.ts @@ -5,5 +5,6 @@ export * from './mpc'; export * from './util/crypto'; // Deprecated export * as acountLibCrypto from './util/crypto'; +// Deprecated export * from './util/ed25519KeyDeriver'; export * from './staking'; diff --git a/modules/sdk-core/src/account-lib/util/ed25519KeyDeriver.ts b/modules/sdk-core/src/account-lib/util/ed25519KeyDeriver.ts index acd98bf763..7ce712897b 100644 --- a/modules/sdk-core/src/account-lib/util/ed25519KeyDeriver.ts +++ b/modules/sdk-core/src/account-lib/util/ed25519KeyDeriver.ts @@ -14,6 +14,8 @@ export interface HdKeypair { * * https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md * https://github.com/satoshilabs/slips/blob/master/slip-0010.md + * + * @deprecated */ export class Ed25519KeyDeriver { /** diff --git a/modules/sdk-core/src/bitgo/baseCoin/baseCoin.ts b/modules/sdk-core/src/bitgo/baseCoin/baseCoin.ts index 3ad0ba52dc..5655092188 100644 --- a/modules/sdk-core/src/bitgo/baseCoin/baseCoin.ts +++ b/modules/sdk-core/src/bitgo/baseCoin/baseCoin.ts @@ -378,6 +378,8 @@ export abstract class BaseCoin implements IBaseCoin { * @param key * @param seed * @returns {{key: string, derivationPath: string}} + * + * @deprecated use deriveKeyWithSeedAsync instead */ deriveKeyWithSeed({ key, seed }: { key: string; seed: string }): { key: string; derivationPath: string } { function sha256(input) { @@ -397,6 +399,22 @@ export abstract class BaseCoin implements IBaseCoin { }; } + /** + * The cold wallet tool uses this function to derive an extended key that is based on the passed key and seed + * @param key + * @param seed + * @returns {{key: string, derivationPath: string}} + */ + async deriveKeyWithSeedAsync({ + key, + seed, + }: { + key: string; + seed: string; + }): Promise<{ key: string; derivationPath: string }> { + return this.deriveKeyWithSeed({ key, seed }); + } + /** * Specifies what key we will need for signing - right now we just need the * user key. @@ -429,10 +447,19 @@ export abstract class BaseCoin implements IBaseCoin { /** * Generate a key pair on the curve used by the coin + * @param seed * + */ + abstract generateKeyPair(seed?: Buffer, rootKey?: boolean): KeyPair; + + /** + * Generate a root key pair on the curve used by the coin * @param seed + * */ - abstract generateKeyPair(seed?: Buffer): KeyPair; + generateRootKeyPair(seed?: Buffer, rootKey?: boolean): KeyPair { + throw new NotImplementedError('generateRootKeyPair is not supported for this coin'); + } /** * Return boolean indicating whether input is valid public key for the coin. diff --git a/modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts b/modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts index bb1eac3df7..3b8306a2fd 100644 --- a/modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts +++ b/modules/sdk-core/src/bitgo/baseCoin/iBaseCoin.ts @@ -503,6 +503,7 @@ export interface IBaseCoin { initiateRecovery(params: InitiateRecoveryOptions): never; parseTransaction(params: ParseTransactionOptions): Promise; generateKeyPair(seed?: Buffer): KeyPair; + generateRootKeyPair(seed?: Buffer): KeyPair; isValidPub(pub: string): boolean; isValidMofNSetup(params: ValidMofNOptions): boolean; isValidAddress(address: string): boolean; diff --git a/modules/sdk-core/src/bitgo/keychain/iKeychains.ts b/modules/sdk-core/src/bitgo/keychain/iKeychains.ts index bf2b5894bd..3de3c2a648 100644 --- a/modules/sdk-core/src/bitgo/keychain/iKeychains.ts +++ b/modules/sdk-core/src/bitgo/keychain/iKeychains.ts @@ -174,7 +174,7 @@ export interface IKeychains { list(params?: ListKeychainOptions): Promise; updatePassword(params: UpdatePasswordOptions): Promise; updateSingleKeychainPassword(params?: UpdateSingleKeychainPasswordOptions): Keychain; - create(params?: { seed?: Buffer }): KeyPair; + create(params?: { seed?: Buffer; rootKey?: boolean }): KeyPair; add(params?: AddKeychainOptions): Promise; createBitGo(params?: CreateBitGoOptions): Promise; createBackup(params?: CreateBackupOptions): Promise; diff --git a/modules/sdk-core/src/bitgo/keychain/keychains.ts b/modules/sdk-core/src/bitgo/keychain/keychains.ts index 8efaf76fa1..026ada54f3 100644 --- a/modules/sdk-core/src/bitgo/keychain/keychains.ts +++ b/modules/sdk-core/src/bitgo/keychain/keychains.ts @@ -174,7 +174,10 @@ export class Keychains implements IKeychains { * Create a public/private key pair * @param params.seed */ - create(params: { seed?: Buffer } = {}): KeyPair { + create(params: { seed?: Buffer; rootKey?: boolean } = {}): KeyPair { + if (params?.rootKey) { + return this.baseCoin.generateRootKeyPair(params.seed); + } return this.baseCoin.generateKeyPair(params.seed); }