Repository: rust-bitcoin/rust-bitcoin (rust)

Issue:
Make sure `minimal_non_dust` doesn't return an `Option` before release
In https://github.com/rust-bitcoin/rust-bitcoin/pull/4164 we changed the signature of `minimal_non_dust` to make refactors easier.

However, this function is nearly impossible to make panic (unlike `minimal_non_dust_custom` which is pretty easy) since you need a script on the order of magnitude of 600 petabytes. **Plus** we just deprecated `dust_value` telling users to switch to `minimal_non_dust` so it'd be pretty obnoxious for us to then change the signature.

Pull request:
Remove Option return from `minimal_non_dust`
Closes #4221 

This removes the `Option` return type from `minimal_non_dust

Overflow is only possible in 2 cases:
- `dust_relay_fee` would need to be excessively high
- script size would have to exceed ~6.15 × 10¹⁵ bytes (≈ 6 petabytes)

we now panic with the same message we had before in  https://github.com/rust-bitcoin/rust-bitcoin/blob/cf12ba262a646a6341098ee3f4c178a52fc90211/bitcoin/src/blockdata/script/borrowed.rs#L412

Patch:
diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs
index c048ba36..481145e8 100644
--- a/bitcoin/src/blockdata/script/borrowed.rs
+++ b/bitcoin/src/blockdata/script/borrowed.rs
@@ -261,7 +261,7 @@ fn redeem_script(&self) -> Option<&Script> {
         /// Returns the minimum value an output with this script should have in order to be
         /// broadcastable on today’s Bitcoin network.
         #[deprecated(since = "0.32.0", note = "use `minimal_non_dust` etc. instead")]
-        fn dust_value(&self) -> Option<Amount> { self.minimal_non_dust() }
+        fn dust_value(&self) -> Amount { self.minimal_non_dust() }
 
         /// Returns the minimum value an output with this script should have in order to be
         /// broadcastable on today's Bitcoin network.
@@ -272,8 +272,9 @@ fn dust_value(&self) -> Option<Amount> { self.minimal_non_dust() }
         /// To use a custom value, use [`minimal_non_dust_custom`].
         ///
         /// [`minimal_non_dust_custom`]: Script::minimal_non_dust_custom
-        fn minimal_non_dust(&self) -> Option<Amount> {
+        fn minimal_non_dust(&self) -> Amount {
             self.minimal_non_dust_internal(DUST_RELAY_TX_FEE.into())
+                .expect("dust_relay_fee or script length should not be absurdly large")
         }
 
         /// Returns the minimum value an output with this script should have in order to be
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 341fba10..bdb7a383 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -183,8 +183,8 @@ fn size(&self) -> usize { size_from_script_pubkey(&self.script_pubkey) }
         /// To use a custom value, use [`minimal_non_dust_custom`].
         ///
         /// [`minimal_non_dust_custom`]: TxOut::minimal_non_dust_custom
-        fn minimal_non_dust(script_pubkey: ScriptBuf) -> Option<TxOut> {
-            Some(TxOut { value: script_pubkey.minimal_non_dust()?, script_pubkey })
+        fn minimal_non_dust(script_pubkey: ScriptBuf) -> TxOut {
+            TxOut { value: script_pubkey.minimal_non_dust(), script_pubkey }
         }
 
         /// Constructs a new `TxOut` with given script and the smallest possible `value` that is **not** dust


Test patch:
diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs
index 27dcd32e..6d506810 100644
--- a/bitcoin/src/blockdata/script/tests.rs
+++ b/bitcoin/src/blockdata/script/tests.rs
@@ -684,7 +684,7 @@ fn default_dust_value() {
     // well-known scriptPubKey types.
     let script_p2wpkh = Builder::new().push_int_unchecked(0).push_slice([42; 20]).into_script();
     assert!(script_p2wpkh.is_p2wpkh());
-    assert_eq!(script_p2wpkh.minimal_non_dust(), Some(Amount::from_sat_u32(294)));
+    assert_eq!(script_p2wpkh.minimal_non_dust(), Amount::from_sat_u32(294));
     assert_eq!(
         script_p2wpkh.minimal_non_dust_custom(FeeRate::from_sat_per_vb_unchecked(6)),
         Some(Amount::from_sat_u32(588))
@@ -698,7 +698,7 @@ fn default_dust_value() {
         .push_opcode(OP_CHECKSIG)
         .into_script();
     assert!(script_p2pkh.is_p2pkh());
-    assert_eq!(script_p2pkh.minimal_non_dust(), Some(Amount::from_sat_u32(546)));
+    assert_eq!(script_p2pkh.minimal_non_dust(), Amount::from_sat_u32(546));
     assert_eq!(
         script_p2pkh.minimal_non_dust_custom(FeeRate::from_sat_per_vb_unchecked(6)),
         Some(Amount::from_sat_u32(1092))