diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs index cdee6755..f3609a47 100644 --- a/bitcoin/examples/ecdsa-psbt.rs +++ b/bitcoin/examples/ecdsa-psbt.rs @@ -192,11 +192,8 @@ impl WatchOnly { witness: Witness::default(), }], output: vec![ - TxOut { value: to_amount.to_sat(), script_pubkey: to_address.script_pubkey() }, - TxOut { - value: change_amount.to_sat(), - script_pubkey: change_address.script_pubkey(), - }, + TxOut { value: to_amount, script_pubkey: to_address.script_pubkey() }, + TxOut { value: change_amount, script_pubkey: change_address.script_pubkey() }, ], }; @@ -282,7 +279,7 @@ fn previous_output() -> TxOut { .expect("failed to parse input utxo scriptPubkey"); let amount = Amount::from_str(INPUT_UTXO_VALUE).expect("failed to parse input utxo value"); - TxOut { value: amount.to_sat(), script_pubkey } + TxOut { value: amount, script_pubkey } } struct Error(Box); diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs index 62b95356..0ad84de0 100644 --- a/bitcoin/examples/taproot-psbt.rs +++ b/bitcoin/examples/taproot-psbt.rs @@ -40,7 +40,7 @@ const UTXO_SCRIPT_PUBKEY: &str = "5120be27fa8b1f5278faf82cab8da23e8761f8f9bd5d5ebebbb37e0e12a70d92dd16"; const UTXO_PUBKEY: &str = "a6ac32163539c16b6b5dbbca01b725b8e8acaa5f821ba42c80e7940062140d19"; const UTXO_MASTER_FINGERPRINT: &str = "e61b318f"; -const ABSOLUTE_FEES_IN_SATS: u64 = 1000; +const ABSOLUTE_FEES_IN_SATS: Amount = Amount::from_sat(1_000); // UTXO_1 will be used for spending example 1 const UTXO_1: P2trUtxo = P2trUtxo { @@ -49,7 +49,7 @@ const UTXO_1: P2trUtxo = P2trUtxo { script_pubkey: UTXO_SCRIPT_PUBKEY, pubkey: UTXO_PUBKEY, master_fingerprint: UTXO_MASTER_FINGERPRINT, - amount_in_sats: 50 * COIN_VALUE, // 50 BTC + amount_in_sats: Amount::from_sat(50 * 100_000_000), // 50 BTC derivation_path: BIP86_DERIVATION_PATH, }; @@ -60,7 +60,7 @@ const UTXO_2: P2trUtxo = P2trUtxo { script_pubkey: UTXO_SCRIPT_PUBKEY, pubkey: UTXO_PUBKEY, master_fingerprint: UTXO_MASTER_FINGERPRINT, - amount_in_sats: 50 * COIN_VALUE, + amount_in_sats: Amount::from_sat(50 * 100_000_000), // 50 BTC derivation_path: BIP86_DERIVATION_PATH, }; @@ -71,7 +71,7 @@ const UTXO_3: P2trUtxo = P2trUtxo { script_pubkey: UTXO_SCRIPT_PUBKEY, pubkey: UTXO_PUBKEY, master_fingerprint: UTXO_MASTER_FINGERPRINT, - amount_in_sats: 50 * COIN_VALUE, + amount_in_sats: Amount::from_sat(50 * 100_000_000), // 50 BTC derivation_path: BIP86_DERIVATION_PATH, }; @@ -80,7 +80,6 @@ use std::str::FromStr; use bitcoin::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint}; use bitcoin::consensus::encode; -use bitcoin::constants::COIN_VALUE; use bitcoin::key::{TapTweak, XOnlyPublicKey}; use bitcoin::opcodes::all::{OP_CHECKSIG, OP_CLTV, OP_DROP}; use bitcoin::psbt::{self, Input, Output, Psbt, PsbtSighashType}; @@ -105,7 +104,7 @@ fn main() -> Result<(), Box> { let change_address = Address::from_str("bcrt1pz449kexzydh2kaypatup5ultru3ej284t6eguhnkn6wkhswt0l7q3a7j76")? .require_network(Network::Regtest)?; - let amount_to_send_in_sats = COIN_VALUE; + let amount_to_send_in_sats = Amount::ONE_BTC; let change_amount = UTXO_1 .amount_in_sats .checked_sub(amount_to_send_in_sats) @@ -216,7 +215,7 @@ struct P2trUtxo<'a> { script_pubkey: &'a str, pubkey: &'a str, master_fingerprint: &'a str, - amount_in_sats: u64, + amount_in_sats: Amount, derivation_path: &'a str, } @@ -259,9 +258,7 @@ fn generate_bip86_key_spend_tx( witness_utxo: { let script_pubkey = ScriptBuf::from_hex(input_utxo.script_pubkey) .expect("failed to parse input utxo scriptPubkey"); - let amount = Amount::from_sat(from_amount); - - Some(TxOut { value: amount.to_sat(), script_pubkey }) + Some(TxOut { value: from_amount, script_pubkey }) }, tap_key_origins: origins, ..Default::default() @@ -448,9 +445,7 @@ impl BenefactorWallet { let input = Input { witness_utxo: { let script_pubkey = script_pubkey; - let amount = Amount::from_sat(value); - - Some(TxOut { value: amount.to_sat(), script_pubkey }) + Some(TxOut { value, script_pubkey }) }, tap_key_origins: origins, tap_merkle_root: taproot_spend_info.merkle_root(), @@ -594,9 +589,9 @@ impl BenefactorWallet { let input = Input { witness_utxo: { let script_pubkey = output_script_pubkey; - let amount = Amount::from_sat(output_value); + let amount = output_value; - Some(TxOut { value: amount.to_sat(), script_pubkey }) + Some(TxOut { value: amount, script_pubkey }) }, tap_key_origins: origins, tap_merkle_root: taproot_spend_info.merkle_root(), diff --git a/bitcoin/src/amount.rs b/bitcoin/src/amount.rs index a5c4e6ef..2b1e95c4 100644 --- a/bitcoin/src/amount.rs +++ b/bitcoin/src/amount.rs @@ -11,6 +11,8 @@ use core::fmt::{self, Write}; use core::str::FromStr; use core::{default, ops}; +use crate::consensus::encode::{self, Decodable, Encodable}; +use crate::io; use crate::prelude::*; /// A set of denominations in which amounts can be expressed. @@ -483,6 +485,8 @@ fn fmt_satoshi_in( /// the checked arithmetic methods. /// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Amount(u64); impl Amount { @@ -660,6 +664,20 @@ impl Amount { } } +impl Decodable for Amount { + #[inline] + fn consensus_decode(r: &mut R) -> Result { + Ok(Amount(Decodable::consensus_decode(r)?)) + } +} + +impl Encodable for Amount { + #[inline] + fn consensus_encode(&self, w: &mut W) -> Result { + self.0.consensus_encode(w) + } +} + impl default::Default for Amount { fn default() -> Self { Amount::ZERO } } diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 05e6a2bc..380a8402 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -378,7 +378,8 @@ mod test { use crate::consensus::encode::{deserialize, serialize}; use crate::hash_types::TxMerkleNode; use crate::{ - CompactTarget, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, + Amount, CompactTarget, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, + Witness, }; fn dummy_tx(nonce: &[u8]) -> Transaction { @@ -391,7 +392,7 @@ mod test { sequence: Sequence(1), witness: Witness::new(), }], - output: vec![TxOut { value: 1, script_pubkey: ScriptBuf::new() }], + output: vec![TxOut { value: Amount::ONE_SAT, script_pubkey: ScriptBuf::new() }], } } diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index f8825ef7..8a368d45 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -22,9 +22,8 @@ use crate::blockdata::witness::Witness; use crate::internal_macros::impl_bytes_newtype; use crate::network::constants::Network; use crate::pow::CompactTarget; +use crate::Amount; -/// How many satoshis are in "one bitcoin". -pub const COIN_VALUE: u64 = 100_000_000; /// How many seconds between blocks we expect on average. pub const TARGET_BLOCK_SPACING: u32 = 600; /// How many blocks between diffchanges. @@ -61,11 +60,6 @@ pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31 /// Number of blocks needed for an output from a coinbase transaction to be spendable. pub const COINBASE_MATURITY: u32 = 100; -/// The maximum value allowed in an output (useful for sanity checking, -/// since keeping everything below this value should prevent overflows -/// if you are doing anything remotely sane with monetary values). -pub const MAX_MONEY: u64 = 21_000_000 * COIN_VALUE; - /// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block. fn bitcoin_genesis_tx() -> Transaction { // Base @@ -93,7 +87,7 @@ fn bitcoin_genesis_tx() -> Transaction { let script_bytes = hex!("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); let out_script = script::Builder::new().push_slice(script_bytes).push_opcode(OP_CHECKSIG).into_script(); - ret.output.push(TxOut { value: 50 * COIN_VALUE, script_pubkey: out_script }); + ret.output.push(TxOut { value: Amount::from_sat(50 * 100_000_000), script_pubkey: out_script }); // end ret @@ -198,6 +192,8 @@ impl ChainHash { #[cfg(test)] mod test { + use core::str::FromStr; + use super::*; use crate::blockdata::locktime::absolute; use crate::consensus::encode::serialize; @@ -219,7 +215,7 @@ mod test { assert_eq!(gen.output.len(), 1); assert_eq!(serialize(&gen.output[0].script_pubkey), hex!("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac")); - assert_eq!(gen.output[0].value, 50 * COIN_VALUE); + assert_eq!(gen.output[0].value, Amount::from_str("50 BTC").unwrap()); assert_eq!(gen.lock_time, absolute::LockTime::ZERO); assert_eq!( diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 1b6dd415..e1a5c94d 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -35,7 +35,7 @@ use crate::prelude::*; #[cfg(doc)] use crate::sighash::{EcdsaSighashType, TapSighashType}; use crate::string::FromHexStr; -use crate::{io, VarInt}; +use crate::{io, Amount, VarInt}; /// A reference to a transaction output. /// @@ -478,7 +478,7 @@ impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus); #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct TxOut { /// The value of the output, in satoshis. - pub value: u64, + pub value: Amount, /// The script which must be satisfied for the output to be spent. pub script_pubkey: ScriptBuf, } @@ -512,7 +512,7 @@ impl TxOut { let dust_amount = (len as u64) * 3; TxOut { - value: dust_amount + 1, // minimal non-dust amount is one higher than dust amount + value: Amount::from_sat(dust_amount + 1), // minimal non-dust amount is one higher than dust amount script_pubkey, } } @@ -520,7 +520,9 @@ impl TxOut { // This is used as a "null txout" in consensus signing code. impl Default for TxOut { - fn default() -> TxOut { TxOut { value: 0xffffffffffffffff, script_pubkey: ScriptBuf::new() } } + fn default() -> TxOut { + TxOut { value: Amount::from_sat(0xffffffffffffffff), script_pubkey: ScriptBuf::new() } + } } /// Result of [`Transaction::encode_signing_data_to`]. @@ -962,12 +964,7 @@ impl Transaction { let flags: u32 = flags.into(); for (idx, input) in self.input.iter().enumerate() { if let Some(output) = spent(&input.previous_output) { - output.script_pubkey.verify_with_flags( - idx, - crate::Amount::from_sat(output.value), - tx.as_slice(), - flags, - )?; + output.script_pubkey.verify_with_flags(idx, output.value, tx.as_slice(), flags)?; } else { return Err(script::Error::UnknownSpentOutput(input.previous_output)); } diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index 8ffdbf8d..6c8bc908 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -22,7 +22,7 @@ use crate::consensus::{encode, Encodable}; use crate::error::impl_std_error; use crate::prelude::*; use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX}; -use crate::{io, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut}; +use crate::{io, Amount, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut}; /// Used for signature hash for invalid use of SIGHASH_SINGLE. #[rustfmt::skip] @@ -751,7 +751,7 @@ impl> SighashCache { mut writer: Write, input_index: usize, script_code: &Script, - value: u64, + value: Amount, sighash_type: EcdsaSighashType, ) -> Result<(), Error> { let zero_hash = sha256d::Hash::all_zeros(); @@ -810,7 +810,7 @@ impl> SighashCache { &mut self, input_index: usize, script_code: &Script, - value: u64, + value: Amount, sighash_type: EcdsaSighashType, ) -> Result { let mut enc = SegwitV0Sighash::engine(); @@ -1062,7 +1062,7 @@ impl> SighashCache { /// /// This allows in-line signing such as /// ``` - /// use bitcoin::{absolute, Transaction, Script}; + /// use bitcoin::{absolute, Amount, Transaction, Script}; /// use bitcoin::sighash::{EcdsaSighashType, SighashCache}; /// /// let mut tx_to_sign = Transaction { version: 2, lock_time: absolute::LockTime::ZERO, input: Vec::new(), output: Vec::new() }; @@ -1071,7 +1071,7 @@ impl> SighashCache { /// let mut sig_hasher = SighashCache::new(&mut tx_to_sign); /// for inp in 0..input_count { /// let prevout_script = Script::empty(); - /// let _sighash = sig_hasher.segwit_signature_hash(inp, prevout_script, 42, EcdsaSighashType::All); + /// let _sighash = sig_hasher.segwit_signature_hash(inp, prevout_script, Amount::ONE_SAT, EcdsaSighashType::All); /// // ... sign the sighash /// sig_hasher.witness_mut(inp).unwrap().push(&Vec::new()); /// } @@ -1468,7 +1468,7 @@ mod tests { #[serde(rename = "scriptPubKey")] script_pubkey: ScriptBuf, #[serde(rename = "amountSats")] - value: u64, + value: Amount, } #[derive(serde::Deserialize)] @@ -1685,7 +1685,7 @@ mod tests { let witness_script = p2pkh_hex("025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357"); - let value = 600_000_000; + let value = Amount::from_sat(600_000_000); let mut cache = SighashCache::new(&tx); assert_eq!( @@ -1726,7 +1726,7 @@ mod tests { let witness_script = p2pkh_hex("03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873"); - let value = 1_000_000_000; + let value = Amount::from_sat(1_000_000_000); let mut cache = SighashCache::new(&tx); assert_eq!( @@ -1773,7 +1773,7 @@ mod tests { 56ae", ) .unwrap(); - let value = 987654321; + let value = Amount::from_sat(987_654_321); let mut cache = SighashCache::new(&tx); assert_eq!( diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 7aeeabcb..c057f1fa 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -459,11 +459,11 @@ impl PartiallySignedTransaction { pub fn fee(&self) -> Result { let mut inputs: u64 = 0; for utxo in self.iter_funding_utxos() { - inputs = inputs.checked_add(utxo?.value).ok_or(Error::FeeOverflow)?; + inputs = inputs.checked_add(utxo?.value.to_sat()).ok_or(Error::FeeOverflow)?; } let mut outputs: u64 = 0; for out in &self.unsigned_tx.output { - outputs = outputs.checked_add(out.value).ok_or(Error::FeeOverflow)?; + outputs = outputs.checked_add(out.value.to_sat()).ok_or(Error::FeeOverflow)?; } inputs.checked_sub(outputs).map(Amount::from_sat).ok_or(Error::NegativeFee) } @@ -922,14 +922,14 @@ mod tests { }], output: vec![ TxOut { - value: 99999699, + value: Amount::from_sat(99_999_699), script_pubkey: ScriptBuf::from_hex( "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac", ) .unwrap(), }, TxOut { - value: 100000000, + value: Amount::from_sat(100_000_000), script_pubkey: ScriptBuf::from_hex( "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", ) @@ -995,7 +995,7 @@ mod tests { )]), }], output: vec![TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), script_pubkey: ScriptBuf::from_hex( "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587", ) @@ -1046,7 +1046,7 @@ mod tests { Input { non_witness_utxo: Some(tx), witness_utxo: Some(TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }), sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::().unwrap()), @@ -1190,11 +1190,11 @@ mod tests { ], output: vec![ TxOut { - value: 99999699, + value: Amount::from_sat(99_999_699), script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), }, TxOut { - value: 100000000, + value: Amount::from_sat(100_000_000), script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), }, ], @@ -1237,11 +1237,11 @@ mod tests { ], output: vec![ TxOut { - value: 200000000, + value: Amount::from_sat(200_000_000), script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(), }, TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }, ], @@ -1522,11 +1522,11 @@ mod tests { ], output: vec![ TxOut { - value: 99999699, + value: Amount::from_sat(99_999_699), script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), }, TxOut { - value: 100000000, + value: Amount::from_sat(100_000_000), script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), }, ], @@ -1569,11 +1569,11 @@ mod tests { ], output: vec![ TxOut { - value: 200000000, + value: Amount::from_sat(200_000_000), script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(), }, TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }, ], @@ -1670,9 +1670,9 @@ mod tests { #[test] fn test_fee() { - let output_0_val = 99999699; - let output_1_val = 100000000; - let prev_output_val = 200000000; + let output_0_val = Amount::from_sat(99_999_699); + let output_1_val = Amount::from_sat(100_000_000); + let prev_output_val = Amount::from_sat(200_000_000); let mut t = PartiallySignedTransaction { unsigned_tx: Transaction { @@ -1733,7 +1733,7 @@ mod tests { ..Default::default() }, TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), ..Default::default() }, ], @@ -1752,7 +1752,7 @@ mod tests { }; assert_eq!( t.fee().expect("fee calculation"), - Amount::from_sat(prev_output_val - (output_0_val + output_1_val)) + prev_output_val - (output_0_val + output_1_val) ); // no previous output let mut t2 = t.clone(); @@ -1769,8 +1769,8 @@ mod tests { e => panic!("unexpected error: {:?}", e), } // overflow - t.unsigned_tx.output[0].value = u64::MAX; - t.unsigned_tx.output[1].value = u64::MAX; + t.unsigned_tx.output[0].value = Amount::MAX; + t.unsigned_tx.output[1].value = Amount::MAX; match t.fee().unwrap_err() { Error::FeeOverflow => {} e => panic!("unexpected error: {:?}", e), @@ -1801,7 +1801,7 @@ mod tests { // First input we can spend. See comment above on key_map for why we use defaults here. let txout_wpkh = TxOut { - value: 10, + value: Amount::from_sat(10), script_pubkey: ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&pk.to_bytes())), }; psbt.inputs[0].witness_utxo = Some(txout_wpkh); @@ -1813,8 +1813,10 @@ mod tests { // Second input is unspendable by us e.g., from another wallet that supports future upgrades. let unknown_prog = WitnessProgram::new(crate::address::WitnessVersion::V4, vec![0xaa; 34]).unwrap(); - let txout_unknown_future = - TxOut { value: 10, script_pubkey: ScriptBuf::new_witness_program(&unknown_prog) }; + let txout_unknown_future = TxOut { + value: Amount::from_sat(10), + script_pubkey: ScriptBuf::new_witness_program(&unknown_prog), + }; psbt.inputs[1].witness_utxo = Some(txout_unknown_future); let sigs = psbt.sign(&key_map, &secp).unwrap(); diff --git a/bitcoin/tests/psbt.rs b/bitcoin/tests/psbt.rs index a36b1afb..692cc9b6 100644 --- a/bitcoin/tests/psbt.rs +++ b/bitcoin/tests/psbt.rs @@ -188,15 +188,13 @@ fn create_transaction() -> Transaction { output: vec![ TxOut { value: Amount::from_str_in(output_0.amount, Denomination::Bitcoin) - .expect("failed to parse amount") - .to_sat(), + .expect("failed to parse amount"), script_pubkey: ScriptBuf::from_hex(output_0.script_pubkey) .expect("failed to parse script"), }, TxOut { value: Amount::from_str_in(output_1.amount, Denomination::Bitcoin) - .expect("failed to parse amount") - .to_sat(), + .expect("failed to parse amount"), script_pubkey: ScriptBuf::from_hex(output_1.script_pubkey) .expect("failed to parse script"), }, diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs index 042ac0ba..fc125975 100644 --- a/bitcoin/tests/serde.rs +++ b/bitcoin/tests/serde.rs @@ -38,8 +38,8 @@ use bitcoin::psbt::{Input, Output, Psbt, PsbtSighashType}; use bitcoin::sighash::{EcdsaSighashType, TapSighashType}; use bitcoin::taproot::{self, ControlBlock, LeafVersion, TapTree, TaprootBuilder}; use bitcoin::{ - ecdsa, Address, Block, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, Target, - Transaction, TxIn, TxOut, Txid, Work, + ecdsa, Address, Amount, Block, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence, + Target, Transaction, TxIn, TxOut, Txid, Work, }; /// Implicitly does regression test for `BlockHeader` also. @@ -110,8 +110,10 @@ fn serde_regression_txin() { #[test] fn serde_regression_txout() { - let txout = - TxOut { value: 0xDEADBEEFCAFEBABE, script_pubkey: ScriptBuf::from(vec![0u8, 1u8, 2u8]) }; + let txout = TxOut { + value: Amount::from_sat(0xDEADBEEFCAFEBABE), + script_pubkey: ScriptBuf::from(vec![0u8, 1u8, 2u8]), + }; let got = serialize(&txout).unwrap(); let want = include_bytes!("data/serde/txout_bincode") as &[_]; assert_eq!(got, want) @@ -237,7 +239,7 @@ fn serde_regression_psbt() { .unwrap()]), }], output: vec![TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587") .unwrap(), }], @@ -282,7 +284,7 @@ fn serde_regression_psbt() { inputs: vec![Input { non_witness_utxo: Some(tx), witness_utxo: Some(TxOut { - value: 190303501938, + value: Amount::from_sat(190_303_501_938), script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), }), sighash_type: Some(PsbtSighashType::from(EcdsaSighashType::from_str("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY").unwrap())),