Skip to content

Commit

Permalink
Introduce monadic AmountOpResult
Browse files Browse the repository at this point in the history
We would like to return an error when doing math ops on amount types.
We cannot however use the stdlib `Result` or `Option` because we want to
implement ops on the result type.

Add an `AmountOpResult` type. Return this type from all math operations
on `Amount` and `SignedAmount`.

Implement `core::iter::Sum` for the new type to allow summing iterators
of amounts - somewhat ugly to use, see tests for example usage.
  • Loading branch information
tcharding committed Feb 7, 2025
1 parent 94f9bac commit 2057469
Show file tree
Hide file tree
Showing 10 changed files with 902 additions and 276 deletions.
6 changes: 3 additions & 3 deletions bitcoin/examples/taproot-psbt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ impl BenefactorWallet {
taproot_spend_info.internal_key(),
taproot_spend_info.merkle_root(),
);
let value = input_utxo.amount - ABSOLUTE_FEES;
let value = (input_utxo.amount - ABSOLUTE_FEES).unwrap();

// Spend a normal BIP86-like output as an input in our inheritance funding transaction
let tx = generate_bip86_key_spend_tx(
Expand Down Expand Up @@ -476,7 +476,7 @@ impl BenefactorWallet {
let mut psbt = self.next_psbt.clone().expect("should have next_psbt");
let input = &mut psbt.inputs[0];
let input_value = input.witness_utxo.as_ref().unwrap().value;
let output_value = input_value - ABSOLUTE_FEES;
let output_value = (input_value - ABSOLUTE_FEES).into_result()?;

// We use some other derivation path in this example for our inheritance protocol. The important thing is to ensure
// that we use an unhardened path so we can make use of xpubs.
Expand Down Expand Up @@ -649,7 +649,7 @@ impl BeneficiaryWallet {
psbt.unsigned_tx.lock_time = lock_time;
psbt.unsigned_tx.output = vec![TxOut {
script_pubkey: to_address.script_pubkey(),
value: input_value - ABSOLUTE_FEES,
value: (input_value - ABSOLUTE_FEES).unwrap(),
}];
psbt.outputs = vec![Output::default()];
let unsigned_tx = psbt.unsigned_tx.clone();
Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/blockdata/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,7 +1673,7 @@ mod tests {

// 10 sat/kwu * (204wu + BASE_WEIGHT) = 4 sats
let expected_fee = "4 sats".parse::<SignedAmount>().unwrap();
let expected_effective_value = value.to_signed() - expected_fee;
let expected_effective_value = (value.to_signed() - expected_fee).unwrap();
assert_eq!(effective_value, expected_effective_value);
}

Expand Down
2 changes: 1 addition & 1 deletion bitcoin/src/psbt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2249,7 +2249,7 @@ mod tests {
};
assert_eq!(
t.fee().expect("fee calculation"),
prev_output_val - (output_0_val + output_1_val)
(prev_output_val - (output_0_val + output_1_val).unwrap()).unwrap()
);
// no previous output
let mut t2 = t.clone();
Expand Down
2 changes: 2 additions & 0 deletions units/src/amount/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//! We refer to the documentation on the types for more information.
mod error;
mod result;
#[cfg(feature = "serde")]
pub mod serde;

Expand Down Expand Up @@ -34,6 +35,7 @@ pub use self::{
OutOfRangeError, ParseAmountError, ParseDenominationError, ParseError,
PossiblyConfusingDenominationError, TooPreciseError, UnknownDenominationError,
},
result::{NumOpError, NumOpResult},
signed::SignedAmount,
unsigned::Amount,
};
Expand Down
Loading

0 comments on commit 2057469

Please sign in to comment.