diff --git a/.changeset/light-plants-remember.md b/.changeset/light-plants-remember.md new file mode 100644 index 00000000..693708ed --- /dev/null +++ b/.changeset/light-plants-remember.md @@ -0,0 +1,5 @@ +--- +"@caravan/bitcoin": major +--- + +transaction parser was stripping out network information from global xpubs being added to psbt. global xpubs will now respect the network and include appropriate prefix diff --git a/packages/caravan-bitcoin/src/psbtv2.test.ts b/packages/caravan-bitcoin/src/psbtv2.test.ts index 9968c4a3..270ef3c5 100644 --- a/packages/caravan-bitcoin/src/psbtv2.test.ts +++ b/packages/caravan-bitcoin/src/psbtv2.test.ts @@ -720,6 +720,14 @@ const BIP_174_VECTORS_VALID_PSBT = [ ]; describe("PsbtV2", () => { + beforeAll(() => { + global.console.warn = jest.fn().mockImplementation(() => {}); + global.console.error = jest.fn().mockImplementation(() => {}); + }); + afterAll(() => { + (global.console.warn as jest.Mock).mockRestore(); + (global.console.error as jest.Mock).mockRestore(); + }); test.each(BIP_370_VECTORS_INVALID_PSBT)( "Throws with BIP0370 test vectors. $case", (vect) => { diff --git a/packages/caravan-bitcoin/src/transactions.test.ts b/packages/caravan-bitcoin/src/transactions.test.ts index 8de4589f..6d462134 100644 --- a/packages/caravan-bitcoin/src/transactions.test.ts +++ b/packages/caravan-bitcoin/src/transactions.test.ts @@ -52,15 +52,15 @@ describe("transactions", () => { const transaction = unsignedMultisigTransaction( fixture.network, fixture.inputs, - fixture.outputs + fixture.outputs, ); if (fixture.psbt) { const transactionFromPSBT = unsignedTransactionObjectFromPSBT( unsignedMultisigPSBT( fixture.network, fixture.inputs, - fixture.outputs - ) + fixture.outputs, + ), ); expect(transaction).toEqual(transactionFromPSBT); } @@ -72,18 +72,18 @@ describe("transactions", () => { const reversedTXIDBuffer = transaction.ins[inputIndex].hash; // Don't want to modify buffer in place so use Buffer.from expect( - toHexString(Buffer.from(reversedTXIDBuffer).reverse()) + toHexString(Buffer.from(reversedTXIDBuffer).reverse()), ).toEqual(input.txid); }); fixture.outputs.forEach((output, outputIndex) => { expect(transaction.outs[outputIndex].value).toEqual( - Number(output.amountSats) + Number(output.amountSats), ); expect( address.fromOutputScript( transaction.outs[outputIndex].script, - networkData(fixture.network) - ) + networkData(fixture.network), + ), ).toEqual(output.address); }); expect(transaction.toHex()).toEqual(fixture.hex); @@ -126,7 +126,7 @@ describe("transactions", () => { const psbt = unsignedMultisigPSBT( fixture.network, fixture.inputs, - fixture.outputs + fixture.outputs, ); expect(fixture.psbt).toEqual(psbt.data.toBase64()); } @@ -140,7 +140,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - true + true, ); expect(fixture.psbt).not.toEqual(psbt.data.toBase64()); @@ -182,7 +182,7 @@ describe("transactions", () => { signedMultisigTransaction( fixture.network, fixture.inputs, - fixture.outputs + fixture.outputs, ); }).toThrow(/at least one transaction signature/i); expect(() => { @@ -190,7 +190,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - [] + [], ); }).toThrow(/at least one transaction signature/i); }); @@ -201,7 +201,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - [[]] + [[]], ); }).toThrow(/insufficient input signatures/i); expect(() => { @@ -209,7 +209,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - [fixture.signature, []] + [fixture.signature, []], ); }).toThrow(/insufficient input signatures/i); }); @@ -220,7 +220,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - [fixture.signature] + [fixture.signature], ); }).toThrow(/insufficient signatures for input/i); }); @@ -231,7 +231,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - [fixture.signature, ["foo", "bar", "baz"]] + [fixture.signature, ["foo", "bar", "baz"]], ); }).toThrow(/invalid signature for input/i); }); @@ -242,7 +242,7 @@ describe("transactions", () => { fixture.network, fixture.inputs, fixture.outputs, - [fixture.signature, fixture.signature] + [fixture.signature, fixture.signature], ); }).toThrow(/duplicate signature for input/i); }); @@ -253,7 +253,7 @@ describe("transactions", () => { const multisig = generateMultisigFromHex( Network.TESTNET, P2SH, - redeemScriptHex + redeemScriptHex, ); // This transaction has already been broadcast as @@ -290,7 +290,7 @@ describe("transactions", () => { Network.TESTNET, inputs, outputs, - [transactionSignature1, transactionSignature2] + [transactionSignature1, transactionSignature2], ); expect(signedTransaction.toHex()).toEqual(signedTransactionHex); @@ -302,7 +302,7 @@ describe("transactions", () => { const multisig = generateMultisigFromHex( Network.TESTNET, P2SH_P2WSH, - witnessScriptHex + witnessScriptHex, ); // This transaction has already been broadcast as @@ -336,7 +336,7 @@ describe("transactions", () => { Network.TESTNET, inputs, outputs, - [transactionSignature1, transactionSignature2] + [transactionSignature1, transactionSignature2], ); expect(signedTransaction.toHex()).toEqual(signedTransactionHex); @@ -348,7 +348,7 @@ describe("transactions", () => { const multisig = generateMultisigFromHex( Network.TESTNET, P2WSH, - witnessScriptHex + witnessScriptHex, ); // This transaction has already been broadcast as @@ -383,7 +383,7 @@ describe("transactions", () => { Network.TESTNET, inputs, outputs, - [transactionSignature1, transactionSignature2] + [transactionSignature1, transactionSignature2], ); expect(signedTransaction.toHex()).toEqual(signedTransactionHex); diff --git a/packages/caravan-bitcoin/src/transactions.ts b/packages/caravan-bitcoin/src/transactions.ts index 5ed7d369..edf812f1 100644 --- a/packages/caravan-bitcoin/src/transactions.ts +++ b/packages/caravan-bitcoin/src/transactions.ts @@ -92,12 +92,15 @@ export function unsignedMultisigPSBT( if (braidDetails && includeGlobalXpubs) { const braid = Braid.fromData(JSON.parse(braidDetails)); braid.extendedPublicKeys.forEach((extendedPublicKeyData) => { - const extendedPublicKey = new ExtendedPublicKey(extendedPublicKeyData); + const extendedPublicKey = new ExtendedPublicKey({ + ...extendedPublicKeyData, + network, + }); const alreadyFound = globalExtendedPublicKeys.find( (existingExtendedPublicKey: any) => existingExtendedPublicKey.toBase58() === - extendedPublicKey.toBase58() + extendedPublicKey.toBase58(), ); if (!alreadyFound) { diff --git a/packages/caravan-psbt/src/psbtv0/utils.ts b/packages/caravan-psbt/src/psbtv0/utils.ts index 30949330..8a926c18 100644 --- a/packages/caravan-psbt/src/psbtv0/utils.ts +++ b/packages/caravan-psbt/src/psbtv0/utils.ts @@ -105,7 +105,6 @@ const psbtOutputFormatter = (output: PsbtOutput, network: Network) => { const script = toOutputScript(output.address, networkData(network)); const outputData: any = { ...output, - // script: toOutputScript(output.address, networkData(network)), script, value: output.value, }; @@ -124,6 +123,7 @@ export const addGlobalXpubs = ( ) => { const globalXpubs = multisigConfig.extendedPublicKeys.map( ({ xfp, bip32Path, xpub }) => { + console.log("xpub:", xpub); return { extendedPubkey: ExtendedPublicKey.fromBase58(xpub).encode(), masterFingerprint: xfp ? Buffer.from(xfp, "hex") : Buffer.alloc(0),