Skip to content
Merged
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: 0 additions & 2 deletions modules/abstract-utxo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,13 @@
"@bitgo/blockapis": "^1.13.0",
"@bitgo/sdk-api": "^1.74.1",
"@bitgo/sdk-core": "^36.31.1",
"@bitgo/secp256k1": "^1.10.0",
"@bitgo/utxo-core": "^1.33.0",
"@bitgo/utxo-lib": "^11.21.0",
"@bitgo/utxo-ord": "^1.26.0",
"@bitgo/wasm-utxo": "^1.36.0",
"@types/lodash": "^4.14.121",
"@types/superagent": "4.1.15",
"bignumber.js": "^9.0.2",
"bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3",
"debug": "^3.1.0",
"io-ts": "npm:@bitgo-forks/io-ts@2.1.4",
"lodash": "^4.17.14",
Expand Down
9 changes: 4 additions & 5 deletions modules/abstract-utxo/src/abstractUtxoCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { randomBytes } from 'crypto';

import _ from 'lodash';
import * as utxolib from '@bitgo/utxo-lib';
import { bip32 } from '@bitgo/secp256k1';
import { BIP32, fixedScriptWallet } from '@bitgo/wasm-utxo';
import { bitgo, getMainnet } from '@bitgo/utxo-lib';
import {
AddressCoinSpecific,
Expand Down Expand Up @@ -42,7 +42,6 @@ import {
isValidPrv,
isValidXprv,
} from '@bitgo/sdk-core';
import { fixedScriptWallet } from '@bitgo/wasm-utxo';

import {
backupKeyRecovery,
Expand Down Expand Up @@ -496,7 +495,7 @@ export abstract class AbstractUtxoCoin
*/
isValidPub(pub: string): boolean {
try {
return bip32.fromBase58(pub).isNeutered();
return BIP32.fromBase58(pub).isNeutered();
} catch (e) {
return false;
}
Expand Down Expand Up @@ -978,7 +977,7 @@ export abstract class AbstractUtxoCoin
// maximum entropy and gives us maximum security against cracking.
seed = randomBytes(512 / 8);
}
const extendedKey = bip32.fromSeed(seed);
const extendedKey = BIP32.fromSeed(seed);
return {
pub: extendedKey.neutered().toBase58(),
prv: extendedKey.toBase58(),
Expand Down Expand Up @@ -1084,7 +1083,7 @@ export abstract class AbstractUtxoCoin
throw new Error('invalid private key');
}
if (publicKey) {
const genPubKey = bip32.fromBase58(prv).neutered().toBase58();
const genPubKey = BIP32.fromBase58(prv).neutered().toBase58();
if (genPubKey !== publicKey) {
throw new Error('public key does not match private key');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BitGoAPI } from '@bitgo/sdk-api';
import { bip32 } from '@bitgo/secp256k1';
import { BIP32 } from '@bitgo/wasm-utxo';
import { Wallet } from '@bitgo/sdk-core';

import { AbstractUtxoCoin } from '../../abstractUtxoCoin';
Expand Down Expand Up @@ -56,12 +56,12 @@ export async function createDescriptorWalletWithWalletPassphrase(
if (!userKeychain.prv) {
throw new Error('Missing private key');
}
const userKey = bip32.fromBase58(userKeychain.prv);
const userKey = BIP32.fromBase58(userKeychain.prv);
const cosigners = [backupKeychain, bitgoKeychain].map((keychain) => {
if (!keychain.pub) {
throw new Error('Missing public key');
}
return bip32.fromBase58(keychain.pub);
return BIP32.fromBase58(keychain.pub);
});
return createDescriptorWallet(bitgo, coin, {
...params,
Expand Down
6 changes: 3 additions & 3 deletions modules/abstract-utxo/src/impl/btc/inscriptionBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
Triple,
xprvToRawPrv,
} from '@bitgo/sdk-core';
import { bip32 } from '@bitgo/secp256k1';
import {
createPsbtForSingleInscriptionPassingTransaction,
DefaultInscriptionConstraints,
Expand All @@ -27,10 +26,11 @@ import {
WalletUnspent,
type TapLeafScript,
} from '@bitgo/utxo-ord';
import { fixedScriptWallet } from '@bitgo/wasm-utxo';
import { BIP32, fixedScriptWallet } from '@bitgo/wasm-utxo';

import { AbstractUtxoCoin } from '../../abstractUtxoCoin';
import { fetchKeychains } from '../../keychains';
import { toUtxolibBIP32 } from '../../wasmUtil';

/** Key identifier for signing */
type SignerKey = 'user' | 'backup' | 'bitgo';
Expand Down Expand Up @@ -58,7 +58,7 @@ export class InscriptionBuilder implements IInscriptionBuilder {
const user = await this.wallet.baseCoin.keychains().get({ id: this.wallet.keyIds()[KeyIndices.USER] });
assert(user.pub);

const userKey = bip32.fromBase58(user.pub);
const userKey = toUtxolibBIP32(BIP32.fromBase58(user.pub));
const { key: derivedKey } = BaseCoin.deriveKeyWithSeedBip32(userKey, inscriptionData.toString());

const result = inscriptions.createInscriptionRevealData(
Expand Down
15 changes: 7 additions & 8 deletions modules/abstract-utxo/src/keychains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import assert from 'assert';

import * as t from 'io-ts';
import { bitgo } from '@bitgo/utxo-lib';
import { BIP32Interface, bip32 } from '@bitgo/secp256k1';
import { IRequestTracer, IWallet, KeyIndices, promiseProps, Triple } from '@bitgo/sdk-core';
import { fixedScriptWallet } from '@bitgo/wasm-utxo';
import { BIP32, bip32, fixedScriptWallet } from '@bitgo/wasm-utxo';

import { AbstractUtxoCoin } from './abstractUtxoCoin';
import { UtxoWallet } from './wallet';
Expand Down Expand Up @@ -50,24 +49,24 @@ export function toKeychainTriple(keychains: UtxoNamedKeychains): Triple<UtxoKeyc

export function toBip32Triple(
keychains: bitgo.RootWalletKeys | UtxoNamedKeychains | Triple<{ pub: string }> | string[]
): Triple<BIP32Interface> {
): Triple<BIP32> {
if (keychains instanceof bitgo.RootWalletKeys) {
return keychains.triple;
return keychains.triple.map((k) => BIP32.fromBase58(k.toBase58())) as Triple<BIP32>;
}
if (Array.isArray(keychains)) {
if (keychains.length !== 3) {
throw new Error('expected 3 keychains');
}
return keychains.map((keychain: { pub: string } | string) => {
const v = typeof keychain === 'string' ? keychain : keychain.pub;
return bip32.fromBase58(v);
}) as Triple<BIP32Interface>;
return BIP32.fromBase58(v);
}) as Triple<BIP32>;
}

return toBip32Triple(toKeychainTriple(keychains));
}

function toXpub(keychain: { pub: string } | string | BIP32Interface): string {
function toXpub(keychain: { pub: string } | string | bip32.BIP32Interface): string {
if (typeof keychain === 'string') {
if (keychain.startsWith('xpub')) {
return keychain;
Expand All @@ -84,7 +83,7 @@ function toXpub(keychain: { pub: string } | string | BIP32Interface): string {
}

export function toXpubTriple(
keychains: UtxoNamedKeychains | Triple<{ pub: string }> | Triple<string> | Triple<BIP32Interface>
keychains: UtxoNamedKeychains | Triple<{ pub: string }> | Triple<string> | Triple<bip32.BIP32Interface>
): Triple<string> {
if (Array.isArray(keychains)) {
if (keychains.length !== 3) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { BIP32Interface, bip32 } from '@bitgo/secp256k1';
import { Psbt } from '@bitgo/wasm-utxo';
import { BIP32, bip32, Psbt } from '@bitgo/wasm-utxo';
import { BaseCoin } from '@bitgo/sdk-core';

import { UtxoCoinName } from '../names';
import { toUtxolibBIP32 } from '../wasmUtil';

import { OfflineVaultSignable } from './OfflineVaultSignable';
import { DescriptorTransaction, getHalfSignedPsbt } from './descriptor';
Expand All @@ -17,19 +17,17 @@ function createHalfSignedFromPsbt(psbt: Psbt): OfflineVaultHalfSigned {

export function createHalfSigned(
coinName: UtxoCoinName,
prv: string | BIP32Interface,
prv: string | bip32.BIP32Interface,
derivationId: string,
tx: unknown
): OfflineVaultHalfSigned {
if (typeof prv === 'string') {
prv = bip32.fromBase58(prv);
}
prv = BaseCoin.deriveKeyWithSeedBip32(prv, derivationId).key;
const key = typeof prv === 'string' ? BIP32.fromBase58(prv) : prv;
const derivedKey = BaseCoin.deriveKeyWithSeedBip32(toUtxolibBIP32(key), derivationId).key;
if (!OfflineVaultSignable.is(tx)) {
throw new Error('unsupported transaction type');
}
if (DescriptorTransaction.is(tx)) {
return createHalfSignedFromPsbt(getHalfSignedPsbt(tx, prv, coinName));
return createHalfSignedFromPsbt(getHalfSignedPsbt(tx, derivedKey, coinName));
}
throw new Error('unsupported transaction type');
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BIP32Interface, bip32 } from '@bitgo/secp256k1';
import { BIP32 } from '@bitgo/wasm-utxo';
import { Triple } from '@bitgo/sdk-core';
import * as t from 'io-ts';

Expand Down Expand Up @@ -28,8 +28,6 @@ export type OfflineVaultUnsigned = t.TypeOf<typeof OfflineVaultSignable>;

type WithXpub = { xpub: string };
type NamedKeys = { user: WithXpub; backup: WithXpub; bitgo: WithXpub };
export function toKeyTriple(xpubs: NamedKeys): Triple<BIP32Interface> {
return [xpubs.user.xpub, xpubs.backup.xpub, xpubs.bitgo.xpub].map((xpub) =>
bip32.fromBase58(xpub)
) as Triple<BIP32Interface>;
export function toKeyTriple(xpubs: NamedKeys): Triple<BIP32> {
return [BIP32.fromBase58(xpubs.user.xpub), BIP32.fromBase58(xpubs.backup.xpub), BIP32.fromBase58(xpubs.bitgo.xpub)];
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as t from 'io-ts';
import { Psbt } from '@bitgo/wasm-utxo';
import type { BIP32Interface } from '@bitgo/utxo-lib';
import { bip32, Psbt } from '@bitgo/wasm-utxo';

import { DescriptorMap, NamedDescriptor } from '../../descriptor';
import { OfflineVaultSignable, toKeyTriple } from '../OfflineVaultSignable';
Expand Down Expand Up @@ -34,7 +33,7 @@ export function getDescriptorsFromDescriptorTransaction(tx: DescriptorTransactio
return toDescriptorMapValidate(descriptors, pubkeys, policy);
}

export function getHalfSignedPsbt(tx: DescriptorTransaction, prv: BIP32Interface, coinName: UtxoCoinName): Psbt {
export function getHalfSignedPsbt(tx: DescriptorTransaction, prv: bip32.BIP32Interface, coinName: UtxoCoinName): Psbt {
const psbt = toWasmPsbt(Buffer.from(tx.coinSpecific.txHex, 'hex'));
const descriptorMap = getDescriptorsFromDescriptorTransaction(tx);
signPsbt(psbt, descriptorMap, prv, { onUnknownInput: 'throw' });
Expand Down
7 changes: 3 additions & 4 deletions modules/abstract-utxo/src/recovery/crossChainRecovery.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { BIP32Interface, bip32 } from '@bitgo/secp256k1';
import { CoinName, fixedScriptWallet, address as wasmAddress } from '@bitgo/wasm-utxo';
import { BIP32, CoinName, fixedScriptWallet, address as wasmAddress } from '@bitgo/wasm-utxo';
import { BitGoBase, IWallet, Keychain, Triple, Wallet } from '@bitgo/sdk-core';
import { decrypt } from '@bitgo/sdk-api';

Expand Down Expand Up @@ -294,9 +293,9 @@ async function getFeeRateSatVB(coin: AbstractUtxoCoin): Promise<number> {
* @param wallet
* @return signing key
*/
async function getPrv(xprv?: string, passphrase?: string, wallet?: IWallet | WalletV1): Promise<BIP32Interface> {
async function getPrv(xprv?: string, passphrase?: string, wallet?: IWallet | WalletV1): Promise<BIP32> {
if (xprv) {
const key = bip32.fromBase58(xprv);
const key = BIP32.fromBase58(xprv);
if (key.isNeutered()) {
throw new Error(`not a private key`);
}
Expand Down
5 changes: 2 additions & 3 deletions modules/abstract-utxo/src/transaction/bip322.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { decodeOrElse } from '@bitgo/sdk-core';
import { bitgo } from '@bitgo/utxo-lib';
import { bip322, fixedScriptWallet, Transaction, type CoinName, type Triple } from '@bitgo/wasm-utxo';
import { bip322, fixedScriptWallet, hasPsbtMagic, Transaction, type CoinName, type Triple } from '@bitgo/wasm-utxo';
import * as t from 'io-ts';

const BIP322MessageInfo = t.type({
Expand Down Expand Up @@ -52,7 +51,7 @@ export function verifyTransactionFromBroadcastableMessage(
}
const network = coinName as CoinName;

if (bitgo.isPsbt(message.txHex)) {
if (hasPsbtMagic(Buffer.from(message.txHex, 'hex'))) {
const psbt = fixedScriptWallet.BitGoPsbt.fromBytes(Buffer.from(message.txHex, 'hex'), network);
try {
message.messageInfo.forEach((info, inputIndex) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import type { Unspent } from '../../unspent';

import type { PsbtParsedScriptType } from './signPsbtUtxolib';
export type PsbtParsedScriptType =
| 'p2sh'
| 'p2wsh'
| 'p2shP2wsh'
| 'p2shP2pk'
| 'taprootKeyPathSpend'
| 'taprootScriptPathSpend'
| 'p2trLegacy'
| 'p2trMusig2ScriptPath'
| 'p2trMusig2KeyPath';

export class InputSigningError<TNumber extends number | bigint = number> extends Error {
static expectedWalletUnspent<TNumber extends number | bigint>(
inputIndex: number,
inputType: PsbtParsedScriptType | null, // null for legacy transaction format
inputType: PsbtParsedScriptType | null,
unspent: Unspent<TNumber> | { id: string }
): InputSigningError<TNumber> {
return new InputSigningError(
Expand All @@ -18,7 +27,7 @@ export class InputSigningError<TNumber extends number | bigint = number> extends

constructor(
public inputIndex: number,
public inputType: PsbtParsedScriptType | null, // null for legacy transaction format
public inputType: PsbtParsedScriptType | null,
public unspent: Unspent<TNumber> | { id: string },
public reason: Error | string
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as utxolib from '@bitgo/utxo-lib';
import { bip322 } from '@bitgo/utxo-core';
import { BIP32Interface, bip32 } from '@bitgo/secp256k1';
import { bitgo } from '@bitgo/utxo-lib';
import { ITransactionExplanation as BaseTransactionExplanation, Triple } from '@bitgo/sdk-core';
import { BIP32 } from '@bitgo/wasm-utxo';
import * as utxocore from '@bitgo/utxo-core';

import type { Bip322Message } from '../../abstractUtxoCoin';
Expand All @@ -11,6 +11,7 @@ import type { Unspent } from '../../unspent';
import { toExtendedAddressFormat } from '../recipient';
import { getPayGoVerificationPubkey } from '../getPayGoVerificationPubkey';
import { toBip32Triple } from '../../keychains';
import { toUtxolibBIP32 } from '../../wasmUtil';
import { getNetworkFromCoinName, UtxoCoinName } from '../../names';

// ===== Transaction Explanation Type Definitions =====
Expand Down Expand Up @@ -174,8 +175,8 @@ function getRootWalletKeys(params: { pubs?: bitgo.RootWalletKeys | string[] }):
if (params.pubs instanceof bitgo.RootWalletKeys) {
return params.pubs;
}
const keys = params.pubs?.map((xpub) => bip32.fromBase58(xpub));
return keys && keys.length === 3 ? new bitgo.RootWalletKeys(keys as Triple<BIP32Interface>) : undefined;
const keys = params.pubs?.map((xpub) => toUtxolibBIP32(BIP32.fromBase58(xpub)));
return keys && keys.length === 3 ? new bitgo.RootWalletKeys(keys as Triple<utxolib.BIP32Interface>) : undefined;
}

function getPsbtInputSignaturesCount(
Expand Down Expand Up @@ -247,17 +248,23 @@ function getChainAndIndexFromBip32Derivations(output: bitgo.PsbtOutput) {
return utxolib.bitgo.getChainAndIndexFromPath(paths[0]);
}

function getChangeInfo(psbt: bitgo.UtxoPsbt, walletKeys?: Triple<BIP32Interface>): ChangeAddressInfo[] | undefined {
function getChangeInfo(
psbt: bitgo.UtxoPsbt,
walletKeys?: Triple<BIP32> | Triple<utxolib.BIP32Interface>
): ChangeAddressInfo[] | undefined {
let utxolibKeys: Triple<utxolib.BIP32Interface>;
try {
walletKeys = walletKeys ?? utxolib.bitgo.getSortedRootNodes(psbt);
utxolibKeys = walletKeys
? (walletKeys.map((k) => toUtxolibBIP32(k)) as Triple<utxolib.BIP32Interface>)
: utxolib.bitgo.getSortedRootNodes(psbt);
} catch (e) {
if (e instanceof utxolib.bitgo.ErrorNoMultiSigInputFound) {
return undefined;
}
throw e;
}

return utxolib.bitgo.findWalletOutputIndices(psbt, walletKeys).map((i) => {
return utxolib.bitgo.findWalletOutputIndices(psbt, utxolibKeys).map((i) => {
const derivationInformation = getChainAndIndexFromBip32Derivations(psbt.data.outputs[i]);
if (!derivationInformation) {
throw new Error('could not find derivation information on bip32Derivation or tapBip32Derivation');
Expand Down Expand Up @@ -392,7 +399,7 @@ export function explainPsbt(
utxocore.paygo.verifyPayGoAddressProof(
psbt,
payGoVerificationInfo.outputIndex,
bip32.fromBase58(payGoVerificationInfo.verificationPubkey, utxolib.networks.bitcoin).publicKey
Buffer.from(BIP32.fromBase58(payGoVerificationInfo.verificationPubkey).publicKey)
);
} catch (e) {
if (strict) {
Expand Down
Loading