Skip to content

Commit

Permalink
draft: add effective_value method
Browse files Browse the repository at this point in the history
  • Loading branch information
yancy committed Dec 2, 2023
1 parent 56c0d6c commit 7dc0a5c
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions bitcoin/src/blockdata/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::blockdata::locktime::absolute::{self, Height, Time};
use crate::blockdata::locktime::relative;
use crate::blockdata::script::{Script, ScriptBuf};
use crate::blockdata::witness::Witness;
use crate::blockdata::FeeRate;
use crate::consensus::{encode, Decodable, Encodable};
use crate::hash_types::{Txid, Wtxid};
use crate::internal_macros::impl_consensus_encoding;
Expand All @@ -31,7 +32,7 @@ use crate::script::Push;
#[cfg(doc)]
use crate::sighash::{EcdsaSighashType, TapSighashType};
use crate::string::FromHexStr;
use crate::{io, Amount, VarInt};
use crate::{io, Amount, SignedAmount, VarInt};

#[rustfmt::skip] // Keep public re-exports separate.
#[cfg(feature = "bitcoinconsensus")]
Expand Down Expand Up @@ -214,8 +215,6 @@ impl TxIn {
/// Returns the input base weight.
///
/// Base weight excludes the witness and script.
// to be used in up-coming commit to add effective_value()
#[allow(dead_code)]
const BASE_WEIGHT: Weight =
Weight::from_vb_unwrap(OutPoint::SIZE as u64 + Sequence::SIZE as u64);

Expand Down Expand Up @@ -534,6 +533,31 @@ impl TxOut {
Weight::from_vb(self.size() as u64).expect("should never happen under normal conditions")
}

/// Returns the effective_value `Amount` returning `None` on overflow.
///
/// The effective value is the value of this output minus the amount to spend it. That is,
/// the effective_value can be calculated as value - (fee_rate * weight).
///
/// # Arguments
///
/// * `fee_rate` - `FeeRate`in sat/kwu
/// * `satisfaction_weight` - output weight once the spending conditions are satisfied
pub fn effective_value(
&self,
fee_rate: FeeRate,
satisfaction_weight: Weight,
) -> Option<SignedAmount> {
let weight = satisfaction_weight.checked_add(TxIn::BASE_WEIGHT)?;
let input_fee = fee_rate.checked_mul_by_weight(weight)?;

// Note, this method could return Result instead of Option instead of
// discarding the error type here.
let signed_input_fee = input_fee.to_signed().ok()?;
let signed_value = self.value.to_signed().ok()?;

signed_value.checked_sub(signed_input_fee)
}

/// Returns the total number of bytes that this output contributes to a transaction.
///
/// There is no difference between base size vs total size for outputs.
Expand Down

0 comments on commit 7dc0a5c

Please sign in to comment.