Skip to content

Commit

Permalink
Replace u64 with Amount type in TxOut
Browse files Browse the repository at this point in the history
Some places, most prominently TxOut, were still using u64s
for amounts (in sat). This PR replaces these with the
Amount newtype and also implements the consensus encode
traits for Amount to make it all work.
  • Loading branch information
sgeisler committed Apr 30, 2021
1 parent 4db4e60 commit c3eb51f
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 22 deletions.
6 changes: 4 additions & 2 deletions src/blockdata/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use blockdata::transaction::{OutPoint, Transaction, TxOut, TxIn};
use blockdata::block::{Block, BlockHeader};
use network::constants::Network;
use util::uint::Uint256;
use Amount;

/// The maximum allowable sequence number
pub const MAX_SEQUENCE: u32 = 0xFFFFFFFF;
Expand Down Expand Up @@ -88,7 +89,7 @@ fn bitcoin_genesis_tx() -> Transaction {
.push_opcode(opcodes::all::OP_CHECKSIG)
.into_script();
ret.output.push(TxOut {
value: 50 * COIN_VALUE,
value: Amount::from_sat(50 * COIN_VALUE),
script_pubkey: out_script
});

Expand Down Expand Up @@ -166,6 +167,7 @@ mod test {
use consensus::encode::serialize;
use blockdata::constants::{genesis_block, bitcoin_genesis_tx};
use blockdata::constants::{MAX_SEQUENCE, COIN_VALUE};
use Amount;

#[test]
fn bitcoin_genesis_first_transaction() {
Expand All @@ -182,7 +184,7 @@ mod test {
assert_eq!(gen.output.len(), 1);
assert_eq!(serialize(&gen.output[0].script_pubkey),
Vec::from_hex("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac").unwrap());
assert_eq!(gen.output[0].value, 50 * COIN_VALUE);
assert_eq!(gen.output[0].value, Amount::from_sat(50 * COIN_VALUE));
assert_eq!(gen.lock_time, 0);

assert_eq!(format!("{:x}", gen.wtxid()),
Expand Down
4 changes: 2 additions & 2 deletions src/blockdata/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,8 @@ impl Script {
/// * index - the input index in spending which is spending this transaction
/// * amount - the amount this script guards
/// * spending - the transaction that attempts to spend the output holding this script
pub fn verify (&self, index: usize, amount: u64, spending: &[u8]) -> Result<(), Error> {
Ok(bitcoinconsensus::verify (&self.0[..], amount, spending, index)?)
pub fn verify (&self, index: usize, amount: Amount, spending: &[u8]) -> Result<(), Error> {
Ok(bitcoinconsensus::verify (&self.0[..], amount.as_sat(), spending, index)?)
}

/// Write the assembly decoding of the script bytes to the formatter.
Expand Down
7 changes: 4 additions & 3 deletions src/blockdata/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use blockdata::constants::WITNESS_SCALE_FACTOR;
use blockdata::script::Script;
use consensus::{encode, Decodable, Encodable};
use hash_types::{SigHash, Txid, Wtxid};
use VarInt;
use ::{VarInt, Amount};

/// A reference to a transaction output
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
Expand Down Expand Up @@ -210,15 +210,16 @@ impl Default for TxIn {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TxOut {
/// The value of the output, in satoshis
pub value: u64,
#[cfg_attr(feature = "serde", serde(with="crate::util::amount::serde::as_sat"))]
pub value: Amount,
/// The script which must satisfy for the output to be spent
pub script_pubkey: Script
}

// This is used as a "null txout" in consensus signing code
impl Default for TxOut {
fn default() -> TxOut {
TxOut { value: 0xffffffffffffffff, script_pubkey: Script::new() }
TxOut { value: Amount::from_sat(0xffffffffffffffff), script_pubkey: Script::new() }
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/util/amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::fmt::{self, Write};
use std::ops;
use std::str::FromStr;
use std::cmp::Ordering;
use consensus::{Encodable, Decodable, encode};

/// A set of denominations in which amounts can be expressed.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -446,6 +447,18 @@ impl fmt::Display for Amount {
}
}

impl Encodable for Amount {
fn consensus_encode<W: std::io::Write>(&self, writer: W) -> Result<usize, std::io::Error> {
self.0.consensus_encode(writer)
}
}

impl Decodable for Amount {
fn consensus_decode<D: std::io::Read>(d: D) -> Result<Self, encode::Error> {
Ok(Amount(u64::consensus_decode(d)?))
}
}

impl ops::Add for Amount {
type Output = Amount;

Expand Down
11 changes: 6 additions & 5 deletions src/util/bip143.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use consensus::{encode, Encodable};

use std::io;
use std::ops::{Deref, DerefMut};
use Amount;

/// Parts of a sighash which are common across inputs or signatures, and which are
/// sufficient (in conjunction with a private key) to sign the transaction
Expand Down Expand Up @@ -176,7 +177,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
mut writer: Write,
input_index: usize,
script_code: &Script,
value: u64,
value: Amount,
sighash_type: SigHashType,
) -> Result<(), encode::Error> {
let zero_hash = sha256d::Hash::default();
Expand Down Expand Up @@ -229,7 +230,7 @@ impl<R: Deref<Target=Transaction>> SigHashCache<R> {
&mut self,
input_index: usize,
script_code: &Script,
value: u64,
value: Amount,
sighash_type: SigHashType
) -> SigHash {
let mut enc = SigHash::engine();
Expand All @@ -247,15 +248,15 @@ impl<R: DerefMut<Target=Transaction>> SigHashCache<R> {
/// ```
/// use bitcoin::blockdata::transaction::{Transaction, SigHashType};
/// use bitcoin::util::bip143::SigHashCache;
/// use bitcoin::Script;
/// use bitcoin::{Script, Amount};
///
/// let mut tx_to_sign = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: Vec::new() };
/// let input_count = tx_to_sign.input.len();
///
/// let mut sig_hasher = SigHashCache::new(&mut tx_to_sign);
/// for inp in 0..input_count {
/// let prevout_script = Script::new();
/// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, 42, SigHashType::All);
/// let _sighash = sig_hasher.signature_hash(inp, &prevout_script, Amount::from_sat(42), SigHashType::All);
/// // ... sign the sighash
/// sig_hasher.access_witness(inp).push(Vec::new());
/// }
Expand Down Expand Up @@ -293,7 +294,7 @@ mod tests {
let expected_result = SigHash::from_slice(&raw_expected[..]).unwrap();
let mut cache = SigHashCache::new(&tx);
let sighash_type = SigHashType::from_u32_consensus(hash_type);
let actual_result = cache.signature_hash(input_index, &script, value, sighash_type);
let actual_result = cache.signature_hash(input_index, &script, Amount::from_sat(value), sighash_type);
assert_eq!(actual_result, expected_result);
}

Expand Down
22 changes: 12 additions & 10 deletions src/util/psbt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ mod tests {

use super::PartiallySignedTransaction;
use util::psbt::raw::ProprietaryKey;
use Amount;

#[test]
fn trivial_psbt() {
Expand Down Expand Up @@ -316,13 +317,13 @@ mod tests {
}],
output: vec![
TxOut {
value: 99999699,
value: Amount::from_sat(99999699),
script_pubkey: hex_script!(
"76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"
),
},
TxOut {
value: 100000000,
value: Amount::from_sat(100000000),
script_pubkey: hex_script!(
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"
),
Expand Down Expand Up @@ -475,6 +476,7 @@ mod tests {
use util::psbt::map::{Map, Global, Input, Output};
use util::psbt::raw;
use util::psbt::{PartiallySignedTransaction, Error};
use Amount;

#[test]
#[should_panic(expected = "InvalidMagic")]
Expand Down Expand Up @@ -572,11 +574,11 @@ mod tests {
}],
output: vec![
TxOut {
value: 99999699,
value: Amount::from_sat(99999699),
script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
},
TxOut {
value: 100000000,
value: Amount::from_sat(100000000),
script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
},
],
Expand Down Expand Up @@ -620,11 +622,11 @@ mod tests {
}],
output: vec![
TxOut {
value: 200000000,
value: Amount::from_sat(200000000),
script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
},
TxOut {
value: 190303501938,
value: Amount::from_sat(190303501938),
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
},
],
Expand Down Expand Up @@ -805,11 +807,11 @@ mod tests {
}],
output: vec![
TxOut {
value: 99999699,
value: Amount::from_sat(99999699),
script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
},
TxOut {
value: 100000000,
value: Amount::from_sat(100000000),
script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
},
],
Expand Down Expand Up @@ -853,11 +855,11 @@ mod tests {
}],
output: vec![
TxOut {
value: 200000000,
value: Amount::from_sat(200000000),
script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
},
TxOut {
value: 190303501938,
value: Amount::from_sat(190303501938),
script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
},
],
Expand Down

0 comments on commit c3eb51f

Please sign in to comment.