From e81966185dbbbfdb61e3358cec405af218eeaeb1 Mon Sep 17 00:00:00 2001 From: David Kaplan Date: Tue, 25 Nov 2025 14:46:21 -0500 Subject: [PATCH] fix(utxo-lib): fix zec psbt serialization BTC-2825 TICKET: BTC-2825 --- modules/utxo-lib/src/bitgo/zcash/ZcashPsbt.ts | 5 +++ modules/utxo-lib/test/bitgo/psbt/ZcashPsbt.ts | 32 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/modules/utxo-lib/src/bitgo/zcash/ZcashPsbt.ts b/modules/utxo-lib/src/bitgo/zcash/ZcashPsbt.ts index b5872ac63f..04322e0414 100644 --- a/modules/utxo-lib/src/bitgo/zcash/ZcashPsbt.ts +++ b/modules/utxo-lib/src/bitgo/zcash/ZcashPsbt.ts @@ -84,6 +84,11 @@ export class ZcashPsbt extends UtxoPsbt> { if (this.tx.version === 5 || this.tx.version >= ZcashTransaction.VERSION5_BRANCH_NU5) { return super.toBuffer(); } + // check to see if the consensus branch id is already in the global map + if (this.data.globalMap.unknownKeyVals?.some(({ key }) => key.equals(CONSENSUS_BRANCH_ID_KEY))) { + return super.toBuffer(); + } + const value = Buffer.alloc(4); value.writeUint32LE(this.tx.consensusBranchId); this.addUnknownKeyValToGlobal({ key: CONSENSUS_BRANCH_ID_KEY, value }); diff --git a/modules/utxo-lib/test/bitgo/psbt/ZcashPsbt.ts b/modules/utxo-lib/test/bitgo/psbt/ZcashPsbt.ts index 59dc6ad0b6..662afccf07 100644 --- a/modules/utxo-lib/test/bitgo/psbt/ZcashPsbt.ts +++ b/modules/utxo-lib/test/bitgo/psbt/ZcashPsbt.ts @@ -2,7 +2,15 @@ import * as assert from 'assert'; import { networks } from '../../../src'; import * as utxolib from '../../../src'; -import { addWalletOutputToPsbt, getInternalChainCode, WalletUnspent, ZcashPsbt } from '../../../src/bitgo'; +import { + addWalletOutputToPsbt, + getInternalChainCode, + ProprietaryKeySubtype, + PSBT_PROPRIETARY_IDENTIFIER, + WalletUnspent, + ZcashPsbt, + ZcashTransaction, +} from '../../../src/bitgo'; import { getDefaultWalletKeys } from '../../../src/testutil'; import { mockUnspents } from '../../../src/testutil/mock'; @@ -57,4 +65,26 @@ describe('Zcash PSBT', function () { psbt.extractTransaction(true); }); }); + + it('if the consensus branch id is already in the global map, it should not be added again', function () { + psbt.setDefaultsForVersion(network, 456); + const psbtClone = ZcashPsbt.fromHex(psbt.toHex(), { network }); + const value = Buffer.alloc(4); + value.writeUint32LE(ZcashTransaction.VERSION4_BRANCH_NU6_1); + psbtClone.addUnknownKeyValToGlobal({ + key: Buffer.concat([ + Buffer.of(0xfc), + Buffer.of(0x05), + Buffer.from(PSBT_PROPRIETARY_IDENTIFIER), + Buffer.of(ProprietaryKeySubtype.ZEC_CONSENSUS_BRANCH_ID), + ]), + value, + }); + + (psbtClone as ZcashPsbt).setDefaultsForVersion(network, ZcashTransaction.VERSION4_BRANCH_NU6_1); + + const psbtBuffer = psbtClone.toBuffer(); + const psbt2 = utxolib.bitgo.createPsbtFromBuffer(psbtBuffer, network); + assert.deepStrictEqual(psbt2.toBuffer(), psbtBuffer); + }); });