From 65bf651c2f99abae9f88affb207e84d76a55ba7a Mon Sep 17 00:00:00 2001 From: Sreeraj S Date: Tue, 8 Sep 2026 18:44:00 +0000 Subject: [PATCH] fix(abstract-utxo): pass Zcash recovery block height Add blockHeight to public recovery parameters and thread it into the Zcash PSBT builder. Cover the NU6.2 branch ID at the activation height so non-BitGo ZEC recovery callers can supply an independent current height instead of using the stale NU6.1 branch ID. Ticket: SC-7552 Session-Id: f94964a3-36f2-408a-8e36-9d4dc606220b Task-Id: 726038f1-9cab-4db1-9198-faec874137e8 --- .../src/recovery/backupKeyRecovery.ts | 6 ++++++ .../test/unit/recovery/backupKeyRecovery.ts | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts index 0e0e2dde7a..e3592b1176 100644 --- a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts +++ b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts @@ -100,6 +100,8 @@ export interface RecoverParams { recoveryProvider?: RecoveryProvider; /** Satoshi per byte */ feeRate?: number; + /** Block height used to select the Zcash consensus branch ID. */ + blockHeight?: number; /** * Transaction lock time (nLockTime). Set before signing — it is part of the sighash. * Used for ECX replay-protection sweeps (e.g. 499_999_999) and other custom lock-time needs. @@ -270,6 +272,8 @@ export interface RecoverWithUnspentsParams { krsFee?: bigint; /** KRS fee address (required if krsFee > 0) */ krsFeeAddress?: string; + /** Block height used to select the Zcash consensus branch ID. */ + blockHeight?: number; /** Transaction lock time (nLockTime), set on the PSBT before signing */ lockTime?: number; /** Input sequence number applied to every input */ @@ -313,6 +317,7 @@ export function backupKeyRecoveryWithWalletUnspents( recoveryDestination: recoveryDestination, keyRecoveryServiceFee: krsFee ?? BigInt(0), keyRecoveryServiceFeeAddress: krsFeeAddress, + blockHeight: params.blockHeight, lockTime: params.lockTime, sequence: params.sequence, }); @@ -565,6 +570,7 @@ export async function backupKeyRecovery( feeRateSatVB, krsFee, krsFeeAddress, + blockHeight: params.blockHeight, lockTime: params.lockTime, sequence: params.sequence, }, diff --git a/modules/abstract-utxo/test/unit/recovery/backupKeyRecovery.ts b/modules/abstract-utxo/test/unit/recovery/backupKeyRecovery.ts index e1806bbcb7..c572bd3d46 100644 --- a/modules/abstract-utxo/test/unit/recovery/backupKeyRecovery.ts +++ b/modules/abstract-utxo/test/unit/recovery/backupKeyRecovery.ts @@ -176,6 +176,26 @@ function runWithScriptTypes(scriptTypes: ScriptType2Of3[]) { } describe('Backup Key Recovery PSBT', function () { + it('uses the supplied post-NU6.2 block height for Zcash', function () { + const { walletKeys: externalWallet } = createWasmWalletKeys('external'); + const recoveryDestination = getWalletAddress('zec', externalWallet); + const unspent = toUnspent({ scriptType: 'p2sh', value: BigInt(1e8) }, 0, 'zec', wasmWalletKeys); + + const psbt = backupKeyRecoveryWithWalletUnspents( + 'zec', + { + walletKeys: wasmWalletKeys, + keys: [userPrivkey, backupPrivkey, wasmWalletKeys.bitgoKey()], + recoveryDestination, + feeRateSatVB: 1, + blockHeight: 3_364_600, + }, + [unspent] + ); + + assert.strictEqual((psbt as fixedScriptWallet.ZcashBitGoPsbt).consensusBranchId, 0x5437f330); + }); + // compatible with all coins runWithScriptTypes(['p2sh']);