Skip to content

Commit 3e864cf

Browse files
feat(wasm-utxo): add Network::requires_prev_tx_for_legacy_input predicate
Rust-side source of truth for whether a legacy (non-segwit) transparent input needs the full previous transaction (non_witness_utxo) or can rely on witness_utxo alone. Mirrors requiresPrevTxForP2sh in js/fixedScriptWallet/prevTx.ts (added in T1-3654 / PR #306), generalized from P2SH to legacy inputs generally: ZIP-243 (Zcash) and BIP-143/FORKID (BCH family) sighashes commit the input amount regardless of script type, making non_witness_utxo cryptographically pointless for those coins. Refs: T1-3672
1 parent f628a43 commit 3e864cf

1 file changed

Lines changed: 56 additions & 0 deletions

File tree

packages/wasm-utxo/src/networks.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,30 @@ impl Network {
306306
!self.is_mainnet()
307307
}
308308

309+
/// Whether a non-segwit (legacy: P2PKH/P2SH/bare) transparent input on this network needs
310+
/// the full previous transaction (`non_witness_utxo`) to be signed/finalized safely, or can
311+
/// rely on `witness_utxo` alone.
312+
///
313+
/// `false` for value-committing coins whose sighash already commits the input amount,
314+
/// making `non_witness_utxo` cryptographically pointless (BIP174's rationale for requiring
315+
/// it — protecting against a lying `witness_utxo` misreporting the spent amount — doesn't
316+
/// apply):
317+
/// - Zcash (`zec`/`tzec`): the ZIP-243 sighash commits the amount.
318+
/// - BCH family (`bch`/`bcha`/`bsv`/`btg` + testnets): the replay-protected BIP-143/FORKID
319+
/// sighash commits the amount.
320+
///
321+
/// Mirrors `requiresPrevTxForP2sh` in `js/fixedScriptWallet/prevTx.ts` — keep both in sync.
322+
pub fn requires_prev_tx_for_legacy_input(self) -> bool {
323+
!matches!(
324+
self.mainnet(),
325+
Network::Zcash
326+
| Network::BitcoinCash
327+
| Network::Ecash
328+
| Network::BitcoinSV
329+
| Network::BitcoinGold
330+
)
331+
}
332+
309333
/// Convert to bitcoin crate Network type for address encoding
310334
pub fn to_bitcoin_network(self) -> crate::bitcoin::Network {
311335
use crate::bitcoin::Network as BitcoinNetwork;
@@ -403,6 +427,38 @@ mod tests {
403427
}
404428
}
405429

430+
#[test]
431+
fn test_requires_prev_tx_for_legacy_input() {
432+
// Mirrors the JS test matrix in test/fixedScript/prevTx.ts
433+
let value_committing = [
434+
Network::Zcash,
435+
Network::ZcashTestnet,
436+
Network::BitcoinCash,
437+
Network::BitcoinCashTestnet,
438+
Network::Ecash,
439+
Network::EcashTestnet,
440+
Network::BitcoinSV,
441+
Network::BitcoinSVTestnet,
442+
Network::BitcoinGold,
443+
Network::BitcoinGoldTestnet,
444+
];
445+
for network in value_committing {
446+
assert!(
447+
!network.requires_prev_tx_for_legacy_input(),
448+
"{network} should not require prevTx"
449+
);
450+
}
451+
452+
for network in Network::ALL {
453+
if !value_committing.contains(network) {
454+
assert!(
455+
network.requires_prev_tx_for_legacy_input(),
456+
"{network} should require prevTx"
457+
);
458+
}
459+
}
460+
}
461+
406462
#[test]
407463
fn test_display() {
408464
assert_eq!(Network::Bitcoin.to_string(), "Bitcoin");

0 commit comments

Comments
 (0)