2024-03-31 automated rustfmt nightly

This commit is contained in:
Fmt Bot 2024-03-31 01:03:18 +00:00 committed by github-actions[bot]
parent 4163641f44
commit a565db9fdd
37 changed files with 423 additions and 362 deletions

View File

@ -101,7 +101,11 @@ impl TooShortError {
impl fmt::Display for TooShortError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "base58 decoded data was not long enough, must be at least 4 byte: {}", self.length)
write!(
f,
"base58 decoded data was not long enough, must be at least 4 byte: {}",
self.length
)
}
}

View File

@ -268,10 +268,7 @@ mod tests {
Some(hex!("00f8917303bfa8ef24f292e8fa1419b20460ba064d"))
);
// Non Base58 char.
assert_eq!(
decode("¢").unwrap_err(),
InvalidCharacterError { invalid: 194 }
);
assert_eq!(decode("¢").unwrap_err(), InvalidCharacterError { invalid: 194 });
}
#[test]

View File

@ -133,7 +133,11 @@ impl ColdStorage {
fn master_fingerprint(&self) -> Fingerprint { self.master_xpub.fingerprint() }
/// Signs `psbt` with this signer.
fn sign_psbt<C: Signing + Verification>(&self, secp: &Secp256k1<C>, mut psbt: Psbt) -> Result<Psbt> {
fn sign_psbt<C: Signing + Verification>(
&self,
secp: &Secp256k1<C>,
mut psbt: Psbt,
) -> Result<Psbt> {
match psbt.sign(&self.master_xpriv, secp) {
Ok(keys) => assert_eq!(keys.len(), 1),
Err((_, e)) => {

View File

@ -49,7 +49,7 @@ impl std::error::Error for FromScriptError {
}
impl From<witness_program::Error> for FromScriptError {
fn from(e : witness_program::Error) -> Self { Self::WitnessProgram(e) }
fn from(e: witness_program::Error) -> Self { Self::WitnessProgram(e) }
}
impl From<witness_version::TryFromError> for FromScriptError {

View File

@ -379,10 +379,7 @@ mod test {
use crate::blockdata::locktime::absolute;
use crate::blockdata::transaction;
use crate::consensus::encode::{deserialize, serialize};
use crate::{
Amount, CompactTarget, OutPoint, ScriptBuf, Sequence, TxIn, TxOut, Txid,
Witness,
};
use crate::{Amount, CompactTarget, OutPoint, ScriptBuf, Sequence, TxIn, TxOut, Txid, Witness};
fn dummy_tx(nonce: &[u8]) -> Transaction {
Transaction {

View File

@ -17,8 +17,8 @@ use secp256k1::{Secp256k1, XOnlyPublicKey};
use crate::crypto::key::{CompressedPublicKey, Keypair, PrivateKey};
use crate::internal_macros::impl_bytes_newtype;
use crate::prelude::*;
use crate::network::NetworkKind;
use crate::prelude::*;
/// Version bytes for extended public keys on the Bitcoin network.
const VERSION_BYTES_MAINNET_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E];
@ -490,7 +490,7 @@ pub enum Error {
/// `PublicKey` hex should be 66 or 130 digits long.
InvalidPublicKeyHexLength(usize),
/// Base58 decoded data was an invalid length.
InvalidBase58PayloadLength(InvalidBase58PayloadLengthError)
InvalidBase58PayloadLength(InvalidBase58PayloadLengthError),
}
internals::impl_from_infallible!(Error);
@ -885,7 +885,11 @@ impl InvalidBase58PayloadLengthError {
impl fmt::Display for InvalidBase58PayloadLengthError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "decoded base58 xpriv/xpub data was an invalid length: {} (expected 78)", self.length)
write!(
f,
"decoded base58 xpriv/xpub data was an invalid length: {} (expected 78)",
self.length
)
}
}

View File

@ -357,9 +357,7 @@ pub struct DisabledLockTimeError(u32);
impl DisabledLockTimeError {
/// Accessor for the `u32` whose "disable" flag was set, preventing
/// it from being parsed as a relative locktime.
pub fn disabled_locktime_value(&self) -> u32 {
self.0
}
pub fn disabled_locktime_value(&self) -> u32 { self.0 }
}
impl fmt::Display for DisabledLockTimeError {

View File

@ -184,8 +184,7 @@ impl Script {
let ver_opcode = Opcode::from(self.0[0]); // Version 0 or PUSHNUM_1-PUSHNUM_16
let push_opbyte = self.0[1]; // Second byte push opcode 2-40 bytes
if push_opbyte < OP_PUSHBYTES_2.to_u8() || push_opbyte > OP_PUSHBYTES_40.to_u8()
{
if push_opbyte < OP_PUSHBYTES_2.to_u8() || push_opbyte > OP_PUSHBYTES_40.to_u8() {
return None;
}
// Check that the rest of the script has the correct size
@ -400,7 +399,6 @@ impl Script {
#[deprecated(since = "0.32.0", note = "use minimal_non_dust and friends")]
pub fn dust_value(&self) -> crate::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.
///

View File

@ -16,8 +16,8 @@ use crate::blockdata::script::{
use crate::key::{
PubkeyHash, PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey, WPubkeyHash,
};
use crate::taproot::TapNodeHash;
use crate::prelude::*;
use crate::taproot::TapNodeHash;
/// An owned, growable script.
///

View File

@ -25,11 +25,11 @@ use crate::blockdata::script::{Script, ScriptBuf};
use crate::blockdata::witness::Witness;
use crate::blockdata::FeeRate;
use crate::consensus::{encode, Decodable, Encodable};
use crate::error::{PrefixedHexError, UnprefixedHexError, ContainsPrefixError, MissingPrefixError};
use crate::error::{ContainsPrefixError, MissingPrefixError, PrefixedHexError, UnprefixedHexError};
use crate::internal_macros::{impl_consensus_encoding, impl_hashencode};
use crate::prelude::*;
#[cfg(doc)]
use crate::sighash::{EcdsaSighashType, TapSighashType};
use crate::prelude::*;
use crate::{Amount, SignedAmount, VarInt};
#[rustfmt::skip] // Keep public re-exports separate.
@ -825,7 +825,7 @@ impl Transaction {
#[inline]
pub fn total_size(&self) -> usize {
let mut size: usize = 4; // Serialized length of a u32 for the version number.
let uses_segwit = self.uses_segwit_serialization();
let uses_segwit = self.uses_segwit_serialization();
if uses_segwit {
size += 2; // 1 byte for the marker and 1 for the flag.
@ -835,13 +835,7 @@ impl Transaction {
size += self
.input
.iter()
.map(|input| {
if uses_segwit {
input.total_size()
} else {
input.base_size()
}
})
.map(|input| if uses_segwit { input.total_size() } else { input.base_size() })
.sum::<usize>();
size += VarInt::from(self.output.len()).size();
@ -1796,10 +1790,7 @@ mod tests {
let tx_bytes = hex!("0000fd000001021921212121212121212121f8b372b0239cc1dff600000000004f4f4f4f4f4f4f4f000000000000000000000000000000333732343133380d000000000000000000000000000000ff000000000009000dff000000000000000800000000000000000d");
let tx: Result<Transaction, _> = deserialize(&tx_bytes);
assert!(tx.is_err());
assert!(tx
.unwrap_err()
.to_string()
.contains("witness flag set but no witnesses present"));
assert!(tx.unwrap_err().to_string().contains("witness flag set but no witnesses present"));
}
#[test]
@ -1960,10 +1951,7 @@ mod tests {
format!("{:x}", tx.compute_txid()),
"9652aa62b0e748caeec40c4cb7bc17c6792435cc3dfe447dd1ca24f912a1c6ec"
);
assert_eq!(
format!("{:.10x}", tx.compute_txid()),
"9652aa62b0"
);
assert_eq!(format!("{:.10x}", tx.compute_txid()), "9652aa62b0");
assert_eq!(tx.weight(), Weight::from_wu(2718));
// non-segwit tx from my mempool

View File

@ -13,8 +13,8 @@ use io::{BufRead, Write};
use crate::consensus::encode::{Error, MAX_VEC_SIZE};
use crate::consensus::{Decodable, Encodable, WriteExt};
use crate::crypto::ecdsa;
use crate::taproot::{self, TAPROOT_ANNEX_PREFIX};
use crate::prelude::*;
use crate::taproot::{self, TAPROOT_ANNEX_PREFIX};
use crate::{Script, VarInt};
/// The Witness is the data used to unlock bitcoin since the [segwit upgrade].
@ -235,11 +235,7 @@ impl Witness {
/// Creates a new empty [`Witness`].
#[inline]
pub const fn new() -> Self {
Witness {
content: Vec::new(),
witness_elements: 0,
indices_start: 0,
}
Witness { content: Vec::new(), witness_elements: 0, indices_start: 0 }
}
/// Creates a witness required to spend a P2WPKH output.
@ -506,8 +502,7 @@ impl<'de> serde::Deserialize<'de> for Witness {
while let Some(elem) = a.next_element::<String>()? {
let vec = Vec::<u8>::from_hex(&elem).map_err(|e| match e {
InvalidChar(ref e) => match core::char::from_u32(e.invalid_char(
).into()) {
InvalidChar(ref e) => match core::char::from_u32(e.invalid_char().into()) {
Some(c) => de::Error::invalid_value(
Unexpected::Char(c),
&"a valid hex character",
@ -557,7 +552,7 @@ impl Default for Witness {
#[cfg(test)]
mod test {
use hex::{test_hex_unwrap as hex};
use hex::test_hex_unwrap as hex;
use super::*;
use crate::consensus::{deserialize, serialize};

View File

@ -20,7 +20,7 @@ use core::{fmt, mem, u32};
use hashes::{sha256, sha256d, Hash};
use hex::error::{InvalidCharError, OddLengthStringError};
use internals::write_err;
use io::{Cursor, BufRead, Read, Write};
use io::{BufRead, Cursor, Read, Write};
use crate::bip152::{PrefilledTransaction, ShortId};
use crate::bip158::{FilterHash, FilterHeader};
@ -109,7 +109,7 @@ pub enum FromHexError {
/// Purported hex string had odd length.
OddLengthString(OddLengthStringError),
/// Decoding error.
Decode(DecodeError<InvalidCharError>)
Decode(DecodeError<InvalidCharError>),
}
impl fmt::Display for FromHexError {
@ -406,13 +406,18 @@ macro_rules! impl_int_encodable {
($ty:ident, $meth_dec:ident, $meth_enc:ident) => {
impl Decodable for $ty {
#[inline]
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> core::result::Result<Self, Error> {
fn consensus_decode<R: BufRead + ?Sized>(
r: &mut R,
) -> core::result::Result<Self, Error> {
ReadExt::$meth_dec(r)
}
}
impl Encodable for $ty {
#[inline]
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> core::result::Result<usize, io::Error> {
fn consensus_encode<W: Write + ?Sized>(
&self,
w: &mut W,
) -> core::result::Result<usize, io::Error> {
w.$meth_enc(*self)?;
Ok(mem::size_of::<$ty>())
}
@ -588,7 +593,9 @@ macro_rules! impl_array {
impl Decodable for [u8; $size] {
#[inline]
fn consensus_decode<R: BufRead + ?Sized>(r: &mut R) -> core::result::Result<Self, Error> {
fn consensus_decode<R: BufRead + ?Sized>(
r: &mut R,
) -> core::result::Result<Self, Error> {
let mut ret = [0; $size];
r.read_slice(&mut ret)?;
Ok(ret)
@ -632,7 +639,10 @@ macro_rules! impl_vec {
($type: ty) => {
impl Encodable for Vec<$type> {
#[inline]
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> core::result::Result<usize, io::Error> {
fn consensus_encode<W: Write + ?Sized>(
&self,
w: &mut W,
) -> core::result::Result<usize, io::Error> {
let mut len = 0;
len += VarInt(self.len() as u64).consensus_encode(w)?;
for c in self.iter() {
@ -1293,6 +1303,9 @@ mod tests {
let mut hex = include_str!("../../tests/data/previous_tx_0_hex").to_string(); // An arbitrary transaction.
hex.push_str("abcdef");
assert!(matches!(deserialize_hex::<Transaction>(&hex).unwrap_err(), FromHexError::Decode(DecodeError::TooManyBytes)));
assert!(matches!(
deserialize_hex::<Transaction>(&hex).unwrap_err(),
FromHexError::Decode(DecodeError::TooManyBytes)
));
}
}

View File

@ -15,8 +15,8 @@ pub mod validation;
use core::fmt;
use io::{Read, BufRead};
use internals::write_err;
use io::{BufRead, Read};
use crate::consensus;
@ -40,7 +40,9 @@ struct IterReader<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> {
}
impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> IterReader<E, I> {
pub(crate) fn new(iterator: I) -> Self { IterReader { iterator: iterator.fuse(), buf: None, error: None } }
pub(crate) fn new(iterator: I) -> Self {
IterReader { iterator: iterator.fuse(), buf: None, error: None }
}
fn decode<T: Decodable>(mut self) -> Result<T, DecodeError<E>> {
let result = T::consensus_decode(&mut self);
@ -94,11 +96,11 @@ impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> BufRead for IterReader<E,
Some(Ok(byte)) => {
self.buf = Some(byte);
Ok(core::slice::from_ref(self.buf.as_ref().expect("we've just filled it")))
},
}
Some(Err(error)) => {
self.error = Some(error);
Err(io::ErrorKind::Other.into())
},
}
None => Ok(&[]),
}
}
@ -130,7 +132,8 @@ impl<E: fmt::Debug> fmt::Display for DecodeError<E> {
use DecodeError::*;
match *self {
TooManyBytes => write!(f, "attempted to decode object from an iterator that yielded too many bytes"),
TooManyBytes =>
write!(f, "attempted to decode object from an iterator that yielded too many bytes"),
Consensus(ref e) => write_err!(f, "invalid consensus encoding"; e),
Other(ref other) => write!(f, "other decoding error: {:?}", other),
}

View File

@ -136,7 +136,6 @@ impl From<Network> for Params {
fn from(value: Network) -> Self { Self::new(value) }
}
impl From<&Network> for Params {
fn from(value: &Network) -> Self { Self::new(*value) }
}

View File

@ -17,9 +17,9 @@ use serde::de::{SeqAccess, Unexpected, Visitor};
use serde::ser::SerializeSeq;
use serde::{Deserializer, Serializer};
use crate::consensus::{DecodeError, IterReader};
use super::encode::Error as ConsensusError;
use super::{Decodable, Encodable};
use crate::consensus::{DecodeError, IterReader};
/// Hex-encoding strategy
pub struct Hex<Case = hex::Lower>(PhantomData<Case>)
@ -75,9 +75,7 @@ pub mod hex {
pub struct Encoder<C: Case>(BufEncoder<{ HEX_BUF_SIZE }>, PhantomData<C>);
impl<C: Case> From<super::Hex<C>> for Encoder<C> {
fn from(_: super::Hex<C>) -> Self {
Encoder(BufEncoder::new(), Default::default())
}
fn from(_: super::Hex<C>) -> Self { Encoder(BufEncoder::new(), Default::default()) }
}
impl<C: Case> super::EncodeBytes for Encoder<C> {

View File

@ -224,9 +224,7 @@ pub struct SortKey(ArrayVec<u8, 65>);
impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.with_serialized(|bytes| {
fmt::Display::fmt(&bytes.as_hex(), f)
})
self.with_serialized(|bytes| fmt::Display::fmt(&bytes.as_hex(), f))
}
}
@ -239,14 +237,14 @@ impl FromStr for PublicKey {
66 => {
let bytes = <[u8; 33]>::from_hex(s).map_err(|e| match e {
InvalidChar(e) => ParsePublicKeyError::InvalidChar(e.invalid_char()),
InvalidLength(_) => unreachable!("length checked already")
InvalidLength(_) => unreachable!("length checked already"),
})?;
Ok(PublicKey::from_slice(&bytes)?)
},
}
130 => {
let bytes = <[u8; 65]>::from_hex(s).map_err(|e| match e {
InvalidChar(e) => ParsePublicKeyError::InvalidChar(e.invalid_char()),
InvalidLength(_) => unreachable!("length checked already")
InvalidLength(_) => unreachable!("length checked already"),
})?;
Ok(PublicKey::from_slice(&bytes)?)
}
@ -441,7 +439,10 @@ impl PrivateKey {
pub fn to_bytes(self) -> Vec<u8> { self.inner[..].to_vec() }
/// Deserialize a private key from a slice
pub fn from_slice(data: &[u8], network: impl Into<NetworkKind>) -> Result<PrivateKey, secp256k1::Error> {
pub fn from_slice(
data: &[u8],
network: impl Into<NetworkKind>,
) -> Result<PrivateKey, secp256k1::Error> {
Ok(PrivateKey::new(secp256k1::SecretKey::from_slice(data)?, network))
}
@ -948,8 +949,10 @@ impl fmt::Display for FromWifError {
match *self {
Base58(ref e) => write_err!(f, "invalid base58"; e),
InvalidBase58PayloadLength(ref e) => write_err!(f, "decoded base58 data was an invalid length"; e),
InvalidAddressVersion(ref e) => write_err!(f, "decoded base58 data contained an invalid address version btye"; e),
InvalidBase58PayloadLength(ref e) =>
write_err!(f, "decoded base58 data was an invalid length"; e),
InvalidAddressVersion(ref e) =>
write_err!(f, "decoded base58 data contained an invalid address version btye"; e),
Secp256k1(ref e) => write_err!(f, "private key validation failed"; e),
}
}
@ -964,7 +967,7 @@ impl std::error::Error for FromWifError {
Base58(ref e) => Some(e),
InvalidBase58PayloadLength(ref e) => Some(e),
InvalidAddressVersion(ref e) => Some(e),
Secp256k1(ref e)=> Some(e),
Secp256k1(ref e) => Some(e),
}
}
}
@ -978,7 +981,9 @@ impl From<secp256k1::Error> for FromWifError {
}
impl From<InvalidBase58PayloadLengthError> for FromWifError {
fn from(e: InvalidBase58PayloadLengthError) -> FromWifError { Self::InvalidBase58PayloadLength(e) }
fn from(e: InvalidBase58PayloadLengthError) -> FromWifError {
Self::InvalidBase58PayloadLength(e)
}
}
impl From<InvalidAddressVersionError> for FromWifError {
@ -1004,7 +1009,8 @@ impl fmt::Display for ParsePublicKeyError {
match self {
Encoding(e) => write_err!(f, "string error"; e),
InvalidChar(char) => write!(f, "hex error {}", char),
InvalidHexLength(got) => write!(f, "pubkey string should be 66 or 130 digits long, got: {}", got),
InvalidHexLength(got) =>
write!(f, "pubkey string should be 66 or 130 digits long, got: {}", got),
}
}
}
@ -1041,7 +1047,7 @@ impl fmt::Display for ParseCompressedPublicKeyError {
use ParseCompressedPublicKeyError::*;
match self {
Secp256k1(e) => write_err!(f, "secp256k1 error"; e),
Hex(e) => write_err!(f, "invalid hex"; e)
Hex(e) => write_err!(f, "invalid hex"; e),
}
}
}
@ -1463,19 +1469,32 @@ mod tests {
assert_eq!(s.len(), 130);
let res = PublicKey::from_str(s);
assert!(res.is_err());
assert_eq!(res.unwrap_err(), ParsePublicKeyError::Encoding(FromSliceError::Secp256k1(secp256k1::Error::InvalidPublicKey)));
assert_eq!(
res.unwrap_err(),
ParsePublicKeyError::Encoding(FromSliceError::Secp256k1(
secp256k1::Error::InvalidPublicKey
))
);
let s = "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd169";
assert_eq!(s.len(), 66);
let res = PublicKey::from_str(s);
assert!(res.is_err());
assert_eq!(res.unwrap_err(), ParsePublicKeyError::Encoding(FromSliceError::Secp256k1(secp256k1::Error::InvalidPublicKey)));
assert_eq!(
res.unwrap_err(),
ParsePublicKeyError::Encoding(FromSliceError::Secp256k1(
secp256k1::Error::InvalidPublicKey
))
);
let s = "062e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133";
assert_eq!(s.len(), 130);
let res = PublicKey::from_str(s);
assert!(res.is_err());
assert_eq!(res.unwrap_err(), ParsePublicKeyError::Encoding(FromSliceError::InvalidKeyPrefix(6)));
assert_eq!(
res.unwrap_err(),
ParsePublicKeyError::Encoding(FromSliceError::InvalidKeyPrefix(6))
);
let s = "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b13g";
assert_eq!(s.len(), 130);

View File

@ -19,8 +19,8 @@ use io::Write;
use crate::blockdata::witness::Witness;
use crate::consensus::{encode, Encodable};
use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX};
use crate::prelude::*;
use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX};
use crate::{transaction, Amount, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut};
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
@ -607,8 +607,12 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
// sha_sequences (32): the SHA256 of the serialization of all input nSequence.
if !anyone_can_pay {
self.common_cache().prevouts.consensus_encode(writer)?;
self.taproot_cache(prevouts.get_all().map_err(SigningDataError::sighash)?).amounts.consensus_encode(writer)?;
self.taproot_cache(prevouts.get_all().map_err(SigningDataError::sighash)?).script_pubkeys.consensus_encode(writer)?;
self.taproot_cache(prevouts.get_all().map_err(SigningDataError::sighash)?)
.amounts
.consensus_encode(writer)?;
self.taproot_cache(prevouts.get_all().map_err(SigningDataError::sighash)?)
.script_pubkeys
.consensus_encode(writer)?;
self.common_cache().sequences.consensus_encode(writer)?;
}
@ -668,7 +672,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
.ok_or(TaprootError::SingleMissingOutput(SingleMissingOutputError {
input_index,
outputs_length: self.tx.borrow().output.len(),
})).map_err(SigningDataError::Sighash)?
}))
.map_err(SigningDataError::Sighash)?
.consensus_encode(&mut enc)?;
let hash = sha256::Hash::from_engine(enc);
hash.consensus_encode(writer)?;
@ -704,7 +709,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
annex,
leaf_hash_code_separator,
sighash_type,
).map_err(SigningDataError::unwrap_sighash)?;
)
.map_err(SigningDataError::unwrap_sighash)?;
Ok(TapSighash::from_engine(enc))
}
@ -723,7 +729,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
None,
None,
sighash_type,
).map_err(SigningDataError::unwrap_sighash)?;
)
.map_err(SigningDataError::unwrap_sighash)?;
Ok(TapSighash::from_engine(enc))
}
@ -746,7 +753,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
None,
Some((leaf_hash.into(), 0xFFFFFFFF)),
sighash_type,
).map_err(SigningDataError::unwrap_sighash)?;
)
.map_err(SigningDataError::unwrap_sighash)?;
Ok(TapSighash::from_engine(enc))
}
@ -830,7 +838,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
&script_code,
value,
sighash_type,
).map_err(SigningDataError::unwrap_sighash)?;
)
.map_err(SigningDataError::unwrap_sighash)?;
Ok(SegwitV0Sighash::from_engine(enc))
}
@ -849,7 +858,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
witness_script,
value,
sighash_type,
).map_err(SigningDataError::unwrap_sighash)?;
)
.map_err(SigningDataError::unwrap_sighash)?;
Ok(SegwitV0Sighash::from_engine(enc))
}
@ -1215,9 +1225,7 @@ pub enum P2wpkhError {
internals::impl_from_infallible!(P2wpkhError);
impl From<transaction::InputsIndexError> for P2wpkhError {
fn from(value: transaction::InputsIndexError) -> Self {
P2wpkhError::Sighash(value)
}
fn from(value: transaction::InputsIndexError) -> Self { P2wpkhError::Sighash(value) }
}
impl fmt::Display for P2wpkhError {
@ -1400,17 +1408,13 @@ impl<E> SigningDataError<E> {
}
}
fn sighash<E2: Into<E>>(error: E2) -> Self {
Self::Sighash(error.into())
}
fn sighash<E2: Into<E>>(error: E2) -> Self { Self::Sighash(error.into()) }
}
// We cannot simultaneously impl `From<E>`. it was determined that this alternative requires less
// manual `map_err` calls.
impl<E> From<io::Error> for SigningDataError<E> {
fn from(value: io::Error) -> Self {
Self::Io(value)
}
fn from(value: io::Error) -> Self { Self::Io(value) }
}
impl<E: fmt::Display> fmt::Display for SigningDataError<E> {

View File

@ -10,9 +10,9 @@ use core::fmt;
use internals::write_err;
use io::Write;
use crate::prelude::*;
use crate::sighash::{InvalidSighashTypeError, TapSighashType};
use crate::taproot::serialized_signature::{self, SerializedSignature};
use crate::prelude::*;
/// A BIP340-341 serialized taproot signature with the corresponding hash type.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]

View File

@ -12,10 +12,12 @@ pub use crate::{
#[cfg(test)]
mod tests {
use crate::hashes::Hash;
use super::*;
use crate::{LegacySighash, SegwitV0Sighash, TapSighash, PubkeyHash, WPubkeyHash, WScriptHash, ScriptHash, XKeyIdentifier};
use crate::hashes::Hash;
use crate::{
LegacySighash, PubkeyHash, ScriptHash, SegwitV0Sighash, TapSighash, WPubkeyHash,
WScriptHash, XKeyIdentifier,
};
#[test]
fn hash_display() {
@ -45,18 +47,9 @@ mod tests {
"dabc11914abcd8072900042a2681e52f8dba99ce82e224f97b5fdb7cd4b9c803",
);
assert_eq!(
PubkeyHash::hash(&[]).to_string(),
"b472a266d0bd89c13706a4132ccfb16f7c3b9fcb",
);
assert_eq!(
ScriptHash::hash(&[]).to_string(),
"b472a266d0bd89c13706a4132ccfb16f7c3b9fcb",
);
assert_eq!(
WPubkeyHash::hash(&[]).to_string(),
"b472a266d0bd89c13706a4132ccfb16f7c3b9fcb",
);
assert_eq!(PubkeyHash::hash(&[]).to_string(), "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb",);
assert_eq!(ScriptHash::hash(&[]).to_string(), "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb",);
assert_eq!(WPubkeyHash::hash(&[]).to_string(), "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb",);
assert_eq!(
WScriptHash::hash(&[]).to_string(),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",

View File

@ -107,7 +107,10 @@ macro_rules! impl_bytes_newtype {
#[cfg(feature = "serde")]
impl $crate::serde::Serialize for $t {
fn serialize<S: $crate::serde::Serializer>(&self, s: S) -> core::result::Result<S::Ok, S::Error> {
fn serialize<S: $crate::serde::Serializer>(
&self,
s: S,
) -> core::result::Result<S::Ok, S::Error> {
if s.is_human_readable() {
s.collect_str(self)
} else {
@ -118,7 +121,9 @@ macro_rules! impl_bytes_newtype {
#[cfg(feature = "serde")]
impl<'de> $crate::serde::Deserialize<'de> for $t {
fn deserialize<D: $crate::serde::Deserializer<'de>>(d: D) -> core::result::Result<$t, D::Error> {
fn deserialize<D: $crate::serde::Deserializer<'de>>(
d: D,
) -> core::result::Result<$t, D::Error> {
if d.is_human_readable() {
struct HexVisitor;

View File

@ -29,17 +29,13 @@
//! happen the implementations diverge one day.
#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
// Experimental features we need.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(bench, feature(test))]
// Coding conventions.
#![warn(missing_docs)]
// Instead of littering the codebase for non-fuzzing code just globally allow.
#![cfg_attr(fuzzing, allow(dead_code, unused_imports))]
// Exclude lints we don't think are valuable.
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.

View File

@ -540,9 +540,10 @@ impl std::error::Error for MerkleBlockError {
#[cfg(test)]
mod tests {
use hex::{test_hex_unwrap as hex};
use hex::test_hex_unwrap as hex;
#[cfg(feature = "rand-std")]
use secp256k1::rand::prelude::*;
use super::*;
use crate::consensus::encode::{deserialize, serialize};
@ -832,7 +833,8 @@ mod tests {
000000000300000000000003000000000200000000ff00000000c7f1ccb10407\
00000000000000ccb100c76538b100000004bfa9c251681b1b00040000000025\
00000004bfaac251681b1b25\
");
"
);
let deser = crate::consensus::deserialize::<MerkleBlock>(&bytes);
assert!(deser.is_err());
}

View File

@ -226,7 +226,7 @@ impl Decodable for AddrV2 {
}
let addr: [u16; 8] = read_be_address(r)?;
// check the first byte for the CJDNS marker
if addr[0] >> 8 != 0xFC{
if addr[0] >> 8 != 0xFC {
return Err(encode::Error::ParseFailed("Invalid CJDNS address"));
}
AddrV2::Cjdns(Ipv6Addr::new(

View File

@ -742,8 +742,7 @@ mod test {
0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2
]);
let preimage =
RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr);
let preimage = RawNetworkMessage::new(Magic::BITCOIN, NetworkMessage::GetAddr);
assert!(msg.is_ok());
let msg: RawNetworkMessage = msg.unwrap();
assert_eq!(preimage.magic, msg.magic);

View File

@ -11,10 +11,10 @@ use io::{BufRead, Write};
use crate::consensus::{encode, Decodable, Encodable, ReadExt};
use crate::internal_macros::impl_consensus_encoding;
use crate::p2p;
use crate::p2p::address::Address;
use crate::p2p::ServiceFlags;
use crate::prelude::*;
use crate::p2p;
/// Some simple messages

View File

@ -18,7 +18,7 @@ use crate::blockdata::block::BlockHash;
use crate::consensus::encode::{self, Decodable, Encodable};
#[cfg(doc)]
use crate::consensus::Params;
use crate::error::{PrefixedHexError, UnprefixedHexError, ContainsPrefixError, MissingPrefixError};
use crate::error::{ContainsPrefixError, MissingPrefixError, PrefixedHexError, UnprefixedHexError};
use crate::Network;
/// Implement traits and methods shared by `Target` and `Work`.
@ -44,17 +44,23 @@ macro_rules! do_impl {
impl fmt::Display for $ty {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { fmt::Display::fmt(&self.0, f) }
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::LowerHex for $ty {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}
impl fmt::UpperHex for $ty {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result {
fmt::UpperHex::fmt(&self.0, f)
}
}
};
}

View File

@ -24,13 +24,12 @@ use secp256k1::{Keypair, Message, Secp256k1, Signing, Verification};
use crate::bip32::{self, KeySource, Xpriv, Xpub};
use crate::blockdata::transaction::{self, Transaction, TxOut};
use crate::crypto::{ecdsa, taproot};
use crate::crypto::key::{PrivateKey, PublicKey};
use crate::crypto::{ecdsa, taproot};
use crate::key::TapTweak;
use crate::prelude::*;
use crate::sighash::{self, EcdsaSighashType, Prevouts, SighashCache};
use crate::{Amount, FeeRate, TapSighashType};
use crate::key::TapTweak;
use crate::TapLeafHash;
use crate::{Amount, FeeRate, TapLeafHash, TapSighashType};
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(inline)]
@ -316,7 +315,7 @@ impl Psbt {
for i in 0..self.inputs.len() {
match self.signing_algorithm(i) {
Ok(SigningAlgorithm::Ecdsa) => {
Ok(SigningAlgorithm::Ecdsa) =>
match self.bip32_sign_ecdsa(k, i, &mut cache, secp) {
Ok(v) => {
used.insert(i, v);
@ -324,8 +323,7 @@ impl Psbt {
Err(e) => {
errors.insert(i, e);
}
}
}
},
Ok(SigningAlgorithm::Schnorr) => {
match self.bip32_sign_schnorr(k, i, &mut cache, secp) {
Ok(v) => {
@ -417,18 +415,19 @@ impl Psbt {
cache: &mut SighashCache<T>,
secp: &Secp256k1<C>,
) -> Result<Vec<PublicKey>, SignError>
where
C: Signing + Verification,
T: Borrow<Transaction>,
K: GetKey,
where
C: Signing + Verification,
T: Borrow<Transaction>,
K: GetKey,
{
let mut input = self.inputs[input_index].clone();
let mut used = vec![]; // List of pubkeys used to sign the input.
for (&xonly, (leaf_hashes, key_source)) in input.tap_key_origins.iter() {
let sk = if let Ok(Some(secret_key)) = k.get_key(KeyRequest::Bip32(key_source.clone()), secp) {
let sk = if let Ok(Some(secret_key)) =
k.get_key(KeyRequest::Bip32(key_source.clone()), secp)
{
secret_key
} else {
continue;
@ -441,7 +440,6 @@ impl Psbt {
// key path spend
if let Some(internal_key) = input.tap_internal_key {
// BIP 371: The internal key does not have leaf hashes, so can be indicated with a hashes len of 0.
// Based on input.tap_internal_key.is_some() alone, it is not sufficient to determine whether it is a key path spend.
@ -473,11 +471,11 @@ impl Psbt {
.collect::<Vec<_>>();
if !leaf_hashes.is_empty() {
let key_pair = Keypair::from_secret_key(secp, &sk.inner);
for lh in leaf_hashes {
let (msg, sighash_type) = self.sighash_taproot(input_index, cache, Some(lh))?;
let (msg, sighash_type) =
self.sighash_taproot(input_index, cache, Some(lh))?;
#[cfg(feature = "rand-std")]
let signature = secp.sign_schnorr(&msg, &key_pair);
@ -548,8 +546,9 @@ impl Psbt {
Wsh | ShWsh => {
let witness_script =
input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?;
let sighash =
cache.p2wsh_signature_hash(input_index, witness_script, utxo.value, hash_ty).map_err(SignError::SegwitV0Sighash)?;
let sighash = cache
.p2wsh_signature_hash(input_index, witness_script, utxo.value, hash_ty)
.map_err(SignError::SegwitV0Sighash)?;
Ok((Message::from_digest(sighash.to_byte_array()), hash_ty))
}
Tr => {
@ -567,7 +566,7 @@ impl Psbt {
&self,
input_index: usize,
cache: &mut SighashCache<T>,
leaf_hash: Option<TapLeafHash>
leaf_hash: Option<TapLeafHash>,
) -> Result<(Message, TapSighashType), SignError> {
use OutputType::*;
@ -585,9 +584,8 @@ impl Psbt {
.taproot_hash_ty()
.map_err(|_| SignError::InvalidSighashType)?;
let spend_utxos = (0..self.inputs.len())
.map(|i| self.spend_utxo(i).ok())
.collect::<Vec<_>>();
let spend_utxos =
(0..self.inputs.len()).map(|i| self.spend_utxo(i).ok()).collect::<Vec<_>>();
let all_spend_utxos;
let is_anyone_can_pay = PsbtSighashType::from(hash_ty).to_u32() & 0x80 != 0;
@ -605,15 +603,18 @@ impl Psbt {
};
let sighash = if let Some(leaf_hash) = leaf_hash {
cache.taproot_script_spend_signature_hash(input_index, &prev_outs, leaf_hash, hash_ty)?
cache.taproot_script_spend_signature_hash(
input_index,
&prev_outs,
leaf_hash,
hash_ty,
)?
} else {
cache.taproot_key_spend_signature_hash(input_index, &prev_outs, hash_ty)?
};
Ok((Message::from(sighash), hash_ty))
}
_ => {
Err(SignError::Unsupported)
}
_ => Err(SignError::Unsupported),
}
}

View File

@ -1443,8 +1443,8 @@ impl std::error::Error for TaprootError {
mod test {
use core::str::FromStr;
use hashes::sha256t::Tag;
use hashes::sha256;
use hashes::sha256t::Tag;
use hex::FromHex;
use secp256k1::VerifyOnly;

View File

@ -2,20 +2,22 @@
use std::collections::BTreeMap;
use std::str::FromStr;
use secp256k1::{Keypair, Signing, Secp256k1, XOnlyPublicKey};
use bitcoin::{absolute, Address, Network, OutPoint, PrivateKey, Psbt, script, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Witness};
use bitcoin::bip32::{DerivationPath, Fingerprint};
use bitcoin::consensus::encode::serialize_hex;
use bitcoin::opcodes::all::OP_CHECKSIG;
use bitcoin::psbt::{GetKey, Input, KeyRequest, PsbtSighashType, SignError};
use bitcoin::taproot::{LeafVersion, TaprootBuilder, TaprootSpendInfo};
use bitcoin::transaction::Version;
use bitcoin::{
absolute, script, Address, Network, OutPoint, PrivateKey, Psbt, ScriptBuf, Sequence,
Transaction, TxIn, TxOut, Witness,
};
use secp256k1::{Keypair, Secp256k1, Signing, XOnlyPublicKey};
use units::Amount;
#[test]
fn psbt_sign_taproot() {
struct Keystore {
sk: PrivateKey,
mfp: Fingerprint,
@ -23,16 +25,19 @@ fn psbt_sign_taproot() {
impl GetKey for Keystore {
type Error = SignError;
fn get_key<C: Signing>(&self, key_request: KeyRequest, _secp: &Secp256k1<C>) -> Result<Option<PrivateKey>, Self::Error> {
fn get_key<C: Signing>(
&self,
key_request: KeyRequest,
_secp: &Secp256k1<C>,
) -> Result<Option<PrivateKey>, Self::Error> {
match key_request {
KeyRequest::Bip32((mfp, _)) => {
KeyRequest::Bip32((mfp, _)) =>
if mfp == self.mfp {
Ok(Some(self.sk))
} else {
Err(SignError::KeyNotFound)
}
}
_ => Err(SignError::KeyNotFound)
},
_ => Err(SignError::KeyNotFound),
}
}
}
@ -60,10 +65,14 @@ fn psbt_sign_taproot() {
let internal_key = kp.x_only_public_key().0; // Ignore the parity.
let tree = create_taproot_tree(secp, script1.clone(), script2.clone(), script3.clone(), internal_key);
let tree =
create_taproot_tree(secp, script1.clone(), script2.clone(), script3.clone(), internal_key);
let address = create_p2tr_address(tree.clone());
assert_eq!("tb1pytee2mxz0f4fkrsqqws2lsgnkp8nrw2atjkjy2n9gahggsphr0gszaxxmv", address.to_string());
assert_eq!(
"tb1pytee2mxz0f4fkrsqqws2lsgnkp8nrw2atjkjy2n9gahggsphr0gszaxxmv",
address.to_string()
);
// m/86'/1'/0'/0/7
let to_address = "tb1pyfv094rr0vk28lf8v9yx3veaacdzg26ztqk4ga84zucqqhafnn5q9my9rz";
@ -74,7 +83,11 @@ fn psbt_sign_taproot() {
//
// Step 1: create psbt for key path spend.
//
let mut psbt_key_path_spend = create_psbt_for_taproot_key_path_spend(address.clone(), to_address.clone(), tree.clone());
let mut psbt_key_path_spend = create_psbt_for_taproot_key_path_spend(
address.clone(),
to_address.clone(),
tree.clone(),
);
//
// Step 2: sign psbt.
@ -117,7 +130,14 @@ fn psbt_sign_taproot() {
//
// Step 1: create psbt for script path spend.
//
let mut psbt_script_path_spend = create_psbt_for_taproot_script_path_spend(address.clone(), to_address.clone(), tree.clone(), x_only_pubkey, signing_key_path, script2.clone());
let mut psbt_script_path_spend = create_psbt_for_taproot_script_path_spend(
address.clone(),
to_address.clone(),
tree.clone(),
x_only_pubkey,
signing_key_path,
script2.clone(),
);
//
// Step 2: sign psbt.
@ -125,7 +145,15 @@ fn psbt_sign_taproot() {
let _ = psbt_script_path_spend.sign(&keystore, secp);
let sig = "9c1466e1631a58c55fcb8642ce5f7896314f4b565d92c5c80b17aa9abf56d22e0b5e5dcbcfe836bbd7d409491f58aa9e1f68a491ef8f05eef62fb50ffac85727";
assert_eq!(sig, psbt_script_path_spend.inputs[0].tap_script_sigs.get(&(x_only_pubkey, script2.clone().tapscript_leaf_hash())).unwrap().signature.to_string());
assert_eq!(
sig,
psbt_script_path_spend.inputs[0]
.tap_script_sigs
.get(&(x_only_pubkey, script2.clone().tapscript_leaf_hash()))
.unwrap()
.signature
.to_string()
);
//
// Step 3: finalize psbt.
@ -142,7 +170,7 @@ fn psbt_sign_taproot() {
}
}
fn create_basic_single_sig_script(secp: &Secp256k1::<secp256k1::All>, sk: &str) -> ScriptBuf {
fn create_basic_single_sig_script(secp: &Secp256k1<secp256k1::All>, sk: &str) -> ScriptBuf {
let kp = Keypair::from_seckey_str(secp, sk).expect("failed to create keypair");
let x_only_pubkey = kp.x_only_public_key().0;
script::Builder::new()
@ -151,7 +179,13 @@ fn create_basic_single_sig_script(secp: &Secp256k1::<secp256k1::All>, sk: &str)
.into_script()
}
fn create_taproot_tree(secp: &Secp256k1::<secp256k1::All>, script1: ScriptBuf, script2: ScriptBuf, script3: ScriptBuf, internal_key: XOnlyPublicKey) -> TaprootSpendInfo {
fn create_taproot_tree(
secp: &Secp256k1<secp256k1::All>,
script1: ScriptBuf,
script2: ScriptBuf,
script3: ScriptBuf,
internal_key: XOnlyPublicKey,
) -> TaprootSpendInfo {
let builder = TaprootBuilder::new();
let builder = builder.add_leaf(2, script1).unwrap();
let builder = builder.add_leaf(2, script2).unwrap();
@ -164,12 +198,16 @@ fn create_p2tr_address(tree: TaprootSpendInfo) -> Address {
Address::p2tr_tweaked(output_key, Network::Testnet)
}
fn create_psbt_for_taproot_key_path_spend(from_address: Address, to_address: Address, tree: TaprootSpendInfo) -> Psbt {
fn create_psbt_for_taproot_key_path_spend(
from_address: Address,
to_address: Address,
tree: TaprootSpendInfo,
) -> Psbt {
let send_value = 6400;
let out_puts = vec![
TxOut { value: Amount::from_sat(send_value), script_pubkey: to_address.script_pubkey() },
];
let out_puts = vec![TxOut {
value: Amount::from_sat(send_value),
script_pubkey: to_address.script_pubkey(),
}];
let prev_tx_id = "06980ca116f74c7845a897461dd0e1d15b114130176de5004957da516b4dee3a";
let transaction = Transaction {
@ -186,7 +224,6 @@ fn create_psbt_for_taproot_key_path_spend(from_address: Address, to_address: Add
let mut psbt = Psbt::from_unsigned_tx(transaction).unwrap();
let mfp = "73c5da0a";
let internal_key_path = "86'/1'/0'/0/2";
@ -233,14 +270,22 @@ fn finalize_psbt_for_key_path_spend(mut psbt: Psbt) -> Psbt {
psbt
}
fn create_psbt_for_taproot_script_path_spend(from_address: Address, to_address: Address, tree: TaprootSpendInfo, x_only_pubkey_of_signing_key: XOnlyPublicKey, signing_key_path: &str, use_script: ScriptBuf) -> Psbt {
fn create_psbt_for_taproot_script_path_spend(
from_address: Address,
to_address: Address,
tree: TaprootSpendInfo,
x_only_pubkey_of_signing_key: XOnlyPublicKey,
signing_key_path: &str,
use_script: ScriptBuf,
) -> Psbt {
let utxo_value = 6280;
let send_value = 6000;
let mfp = "73c5da0a";
let out_puts = vec![
TxOut { value: Amount::from_sat(send_value), script_pubkey: to_address.script_pubkey() },
];
let out_puts = vec![TxOut {
value: Amount::from_sat(send_value),
script_pubkey: to_address.script_pubkey(),
}];
let prev_tx_id = "9d7c6770fca57285babab60c51834cfcfd10ad302119cae842d7216b4ac9a376";
let transaction = Transaction {
version: Version(2),
@ -276,7 +321,7 @@ fn create_psbt_for_taproot_script_path_spend(from_address: Address, to_address:
let mut input = Input {
witness_utxo: {
let script_pubkey= from_address.script_pubkey();
let script_pubkey = from_address.script_pubkey();
Some(TxOut { value: Amount::from_sat(utxo_value), script_pubkey })
},
tap_key_origins: origins,
@ -291,7 +336,6 @@ fn create_psbt_for_taproot_script_path_spend(from_address: Address, to_address:
psbt
}
fn finalize_psbt_for_script_path_spend(mut psbt: Psbt) -> Psbt {
psbt.inputs.iter_mut().for_each(|input| {
let mut script_witness: Witness = Witness::new();

View File

@ -66,17 +66,13 @@
//! ```
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
// Experimental features we need.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![cfg_attr(bench, feature(test))]
// Coding conventions.
#![warn(missing_docs)]
// Instead of littering the codebase for non-fuzzing code just globally allow.
#![cfg_attr(hashes_fuzz, allow(dead_code, unused_imports))]
// Exclude lints we don't think are valuable.
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.

View File

@ -815,8 +815,8 @@ impl HashEngine {
#[cfg(test)]
mod tests {
use crate::{sha256, Hash as _, HashEngine};
use super::*;
use crate::{sha256, Hash as _, HashEngine};
#[test]
#[cfg(feature = "alloc")]

View File

@ -7,13 +7,10 @@
//!
#![no_std]
// Experimental features we need.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
// Coding conventions.
#![warn(missing_docs)]
// Exclude lints we don't think are valuable.
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.

View File

@ -99,7 +99,10 @@ macro_rules! impl_array_newtype {
macro_rules! debug_from_display {
($thing:ident) => {
impl core::fmt::Debug for $thing {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
fn fmt(
&self,
f: &mut core::fmt::Formatter,
) -> core::result::Result<(), core::fmt::Error> {
core::fmt::Display::fmt(self, f)
}
}

View File

@ -9,13 +9,10 @@
//! `std::io`'s traits without unnecessary complexity.
#![cfg_attr(not(feature = "std"), no_std)]
// Experimental features we need.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
// Coding conventions.
#![warn(missing_docs)]
// Exclude lints we don't think are valuable.
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
@ -325,11 +322,11 @@ pub fn sink() -> Sink { Sink }
#[cfg(test)]
mod tests {
use super::*;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{string::ToString, vec};
use super::*;
#[test]
fn buf_read_fill_and_consume_slice() {
let data = [0_u8, 1, 2];

View File

@ -5,21 +5,19 @@
//! This module mainly introduces the [Amount] and [SignedAmount] types.
//! We refer to the documentation on the types for more information.
#[cfg(feature = "alloc")]
use alloc::string::{String, ToString};
use core::cmp::Ordering;
use core::fmt;
#[cfg(feature = "alloc")]
use core::fmt::Write as _;
use core::str::FromStr;
use core::{default, ops};
use core::{default, fmt, ops};
#[cfg(feature = "serde")]
use ::serde::{Deserialize, Serialize};
use internals::error::InputString;
use internals::write_err;
#[cfg(feature = "alloc")]
use alloc::string::{String, ToString};
/// A set of denominations in which amounts can be expressed.
///
/// # Examples
@ -198,7 +196,8 @@ impl fmt::Display for ParseError {
ParseError::Denomination(error) => write_err!(f, "invalid denomination"; error),
// We consider this to not be a source because it currently doesn't contain useful
// information
ParseError::MissingDenomination(_) => f.write_str("the input doesn't contain a denomination"),
ParseError::MissingDenomination(_) =>
f.write_str("the input doesn't contain a denomination"),
}
}
}
@ -233,28 +232,19 @@ pub enum ParseAmountError {
}
impl From<TooPreciseError> for ParseAmountError {
fn from(value: TooPreciseError) -> Self {
Self::TooPrecise(value)
}
fn from(value: TooPreciseError) -> Self { Self::TooPrecise(value) }
}
impl From<MissingDigitsError> for ParseAmountError {
fn from(value: MissingDigitsError) -> Self {
Self::MissingDigits(value)
}
fn from(value: MissingDigitsError) -> Self { Self::MissingDigits(value) }
}
impl From<InputTooLargeError> for ParseAmountError {
fn from(value: InputTooLargeError) -> Self {
Self::InputTooLarge(value)
}
fn from(value: InputTooLargeError) -> Self { Self::InputTooLarge(value) }
}
impl From<InvalidCharacterError> for ParseAmountError {
fn from(value: InvalidCharacterError) -> Self {
Self::InvalidCharacter(value)
}
fn from(value: InvalidCharacterError) -> Self { Self::InvalidCharacter(value) }
}
internals::impl_from_infallible!(ParseAmountError);
@ -307,21 +297,12 @@ impl OutOfRangeError {
}
/// Returns true if the input value was large than the maximum allowed value.
pub fn is_above_max(&self) -> bool {
self.is_greater_than_max
}
pub fn is_above_max(&self) -> bool { self.is_greater_than_max }
/// Returns true if the input value was smaller than the minimum allowed value.
pub fn is_below_min(&self) -> bool {
!self.is_greater_than_max
}
pub fn is_below_min(&self) -> bool { !self.is_greater_than_max }
pub(crate) fn too_big(is_signed: bool) -> Self {
Self {
is_signed,
is_greater_than_max: true,
}
}
pub(crate) fn too_big(is_signed: bool) -> Self { Self { is_signed, is_greater_than_max: true } }
pub(crate) fn too_small() -> Self {
Self {
@ -354,9 +335,7 @@ impl fmt::Display for OutOfRangeError {
impl std::error::Error for OutOfRangeError {}
impl From<OutOfRangeError> for ParseAmountError {
fn from(value: OutOfRangeError) -> Self {
ParseAmountError::OutOfRange(value)
}
fn from(value: OutOfRangeError) -> Self { ParseAmountError::OutOfRange(value) }
}
/// Error returned when the input string has higher precision than satoshis.
@ -369,7 +348,11 @@ impl fmt::Display for TooPreciseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.position {
0 => f.write_str("the amount is less than 1 satoshi but it's not zero"),
pos => write!(f, "the digits starting from position {} represent a sub-satoshi amount", pos),
pos => write!(
f,
"the digits starting from position {} represent a sub-satoshi amount",
pos
),
}
}
}
@ -386,8 +369,16 @@ pub struct InputTooLargeError {
impl fmt::Display for InputTooLargeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.len - INPUT_STRING_LEN_LIMIT {
1 => write!(f, "the input is one character longer than the maximum allowed length ({})", INPUT_STRING_LEN_LIMIT),
n => write!(f, "the input is {} characters longer than the maximum allowed length ({})", n, INPUT_STRING_LEN_LIMIT),
1 => write!(
f,
"the input is one character longer than the maximum allowed length ({})",
INPUT_STRING_LEN_LIMIT
),
n => write!(
f,
"the input is {} characters longer than the maximum allowed length ({})",
n, INPUT_STRING_LEN_LIMIT
),
}
}
}
@ -407,7 +398,8 @@ impl fmt::Display for MissingDigitsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.kind {
MissingDigitsKind::Empty => f.write_str("the input is empty"),
MissingDigitsKind::OnlyMinusSign => f.write_str("there are no digits following the minus (-) sign"),
MissingDigitsKind::OnlyMinusSign =>
f.write_str("there are no digits following the minus (-) sign"),
}
}
}
@ -433,7 +425,11 @@ impl fmt::Display for InvalidCharacterError {
match self.invalid_char {
'.' => f.write_str("there is more than one decimal separator (dot) in the input"),
'-' => f.write_str("there is more than one minus sign (-) in the input"),
c => write!(f, "the character '{}' at position {} is not a valid digit", c, self.position),
c => write!(
f,
"the character '{}' at position {} is not a valid digit",
c, self.position
),
}
}
}
@ -517,17 +513,18 @@ impl std::error::Error for PossiblyConfusingDenominationError {
/// The position indicates the first digit that is too precise.
fn is_too_precise(s: &str, precision: usize) -> Option<usize> {
match s.find('.') {
Some(pos) if precision >= pos => { Some(0) },
Some(pos) => {
s[..pos].char_indices().rev().take(precision).find(|(_, d)| *d != '0').map(|(i, _)| i)
.or_else(|| {
s[(pos + 1)..].char_indices().find(|(_, d)| *d != '0').map(|(i, _)| i + pos + 1)
})
},
None if precision >= s.len() => { Some(0) },
None => {
s.char_indices().rev().take(precision).find(|(_, d)| *d != '0').map(|(i, _)| i)
},
Some(pos) if precision >= pos => Some(0),
Some(pos) => s[..pos]
.char_indices()
.rev()
.take(precision)
.find(|(_, d)| *d != '0')
.map(|(i, _)| i)
.or_else(|| {
s[(pos + 1)..].char_indices().find(|(_, d)| *d != '0').map(|(i, _)| i + pos + 1)
}),
None if precision >= s.len() => Some(0),
None => s.char_indices().rev().take(precision).find(|(_, d)| *d != '0').map(|(i, _)| i),
}
}
@ -540,7 +537,9 @@ fn parse_signed_to_satoshi(
denom: Denomination,
) -> Result<(bool, u64), InnerParseError> {
if s.is_empty() {
return Err(InnerParseError::MissingDigits(MissingDigitsError { kind: MissingDigitsKind::Empty }));
return Err(InnerParseError::MissingDigits(MissingDigitsError {
kind: MissingDigitsKind::Empty,
}));
}
if s.len() > INPUT_STRING_LEN_LIMIT {
return Err(InnerParseError::InputTooLarge(s.len()));
@ -549,7 +548,9 @@ fn parse_signed_to_satoshi(
let is_negative = s.starts_with('-');
if is_negative {
if s.len() == 1 {
return Err(InnerParseError::MissingDigits(MissingDigitsError { kind: MissingDigitsKind::OnlyMinusSign }));
return Err(InnerParseError::MissingDigits(MissingDigitsError {
kind: MissingDigitsKind::OnlyMinusSign,
}));
}
s = &s[1..];
}
@ -567,7 +568,10 @@ fn parse_signed_to_satoshi(
if let Some(position) = is_too_precise(s, last_n) {
match s.parse::<i64>() {
Ok(0) => return Ok((is_negative, 0)),
_ => return Err(InnerParseError::TooPrecise(TooPreciseError { position: position + is_negative as usize })),
_ =>
return Err(InnerParseError::TooPrecise(TooPreciseError {
position: position + is_negative as usize,
})),
}
}
s = &s[0..s.find('.').unwrap_or(s.len()) - last_n];
@ -594,16 +598,27 @@ fn parse_signed_to_satoshi(
decimals = match decimals {
None => None,
Some(d) if d < max_decimals => Some(d + 1),
_ => return Err(InnerParseError::TooPrecise(TooPreciseError { position: i + is_negative as usize, })),
_ =>
return Err(InnerParseError::TooPrecise(TooPreciseError {
position: i + is_negative as usize,
})),
};
}
'.' => match decimals {
None if max_decimals <= 0 => break,
None => decimals = Some(0),
// Double decimal dot.
_ => return Err(InnerParseError::InvalidCharacter(InvalidCharacterError { invalid_char: '.', position: i + is_negative as usize })),
_ =>
return Err(InnerParseError::InvalidCharacter(InvalidCharacterError {
invalid_char: '.',
position: i + is_negative as usize,
})),
},
c => return Err(InnerParseError::InvalidCharacter(InvalidCharacterError { invalid_char: c, position: i + is_negative as usize })),
c =>
return Err(InnerParseError::InvalidCharacter(InvalidCharacterError {
invalid_char: c,
position: i + is_negative as usize,
})),
}
}
@ -632,7 +647,8 @@ internals::impl_from_infallible!(InnerParseError);
impl InnerParseError {
fn convert(self, is_signed: bool) -> ParseAmountError {
match self {
Self::Overflow { is_negative } => OutOfRangeError { is_signed, is_greater_than_max: !is_negative }.into(),
Self::Overflow { is_negative } =>
OutOfRangeError { is_signed, is_greater_than_max: !is_negative }.into(),
Self::TooPrecise(error) => ParseAmountError::TooPrecise(error),
Self::MissingDigits(error) => ParseAmountError::MissingDigits(error),
Self::InputTooLarge(len) => ParseAmountError::InputTooLarge(InputTooLargeError { len }),
@ -645,7 +661,9 @@ fn split_amount_and_denomination(s: &str) -> Result<(&str, Denomination), ParseE
let (i, j) = if let Some(i) = s.find(' ') {
(i, i + 1)
} else {
let i = s.find(|c: char| c.is_alphabetic()).ok_or(ParseError::MissingDenomination(MissingDenominationError))?;
let i = s
.find(|c: char| c.is_alphabetic())
.ok_or(ParseError::MissingDenomination(MissingDenominationError))?;
(i, i)
};
Ok((&s[..i], s[j..].parse()?))
@ -891,8 +909,8 @@ impl Amount {
/// Note: This only parses the value string. If you want to parse a value
/// with denomination, use [FromStr].
pub fn from_str_in(s: &str, denom: Denomination) -> Result<Amount, ParseAmountError> {
let (negative, satoshi) = parse_signed_to_satoshi(s, denom)
.map_err(|error| error.convert(false))?;
let (negative, satoshi) =
parse_signed_to_satoshi(s, denom).map_err(|error| error.convert(false))?;
if negative {
return Err(ParseAmountError::OutOfRange(OutOfRangeError::negative()));
}
@ -1029,16 +1047,12 @@ impl Amount {
/// Unchecked addition.
///
/// Computes `self + rhs`. Panics in debug mode, wraps in release mode.
pub fn unchecked_add(self, rhs: Amount) -> Amount {
Self(self.0 + rhs.0)
}
pub fn unchecked_add(self, rhs: Amount) -> Amount { Self(self.0 + rhs.0) }
/// Unchecked subtraction.
///
/// Computes `self - rhs`. Panics in debug mode, wraps in release mode.
pub fn unchecked_sub(self, rhs: Amount) -> Amount {
Self(self.0 - rhs.0)
}
pub fn unchecked_sub(self, rhs: Amount) -> Amount { Self(self.0 - rhs.0) }
/// Convert to a signed amount.
pub fn to_signed(self) -> Result<SignedAmount, OutOfRangeError> {
@ -1055,9 +1069,7 @@ impl default::Default for Amount {
}
impl fmt::Debug for Amount {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} SAT", self.to_sat())
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} SAT", self.to_sat()) }
}
// No one should depend on a binding contract for Display for this type.
@ -1143,9 +1155,7 @@ impl FromStr for Amount {
impl TryFrom<SignedAmount> for Amount {
type Error = OutOfRangeError;
fn try_from(value: SignedAmount) -> Result<Self, Self::Error> {
value.to_unsigned()
}
fn try_from(value: SignedAmount) -> Result<Self, Self::Error> { value.to_unsigned() }
}
impl core::iter::Sum for Amount {
@ -1264,10 +1274,12 @@ impl SignedAmount {
pub fn from_str_in(s: &str, denom: Denomination) -> Result<SignedAmount, ParseAmountError> {
match parse_signed_to_satoshi(s, denom).map_err(|error| error.convert(true))? {
// (negative, amount)
(false, sat) if sat > i64::MAX as u64 => Err(ParseAmountError::OutOfRange(OutOfRangeError::too_big(true))),
(false, sat) if sat > i64::MAX as u64 =>
Err(ParseAmountError::OutOfRange(OutOfRangeError::too_big(true))),
(false, sat) => Ok(SignedAmount(sat as i64)),
(true, sat) if sat == i64::MIN.unsigned_abs() => Ok(SignedAmount(i64::MIN)),
(true, sat) if sat > i64::MIN.unsigned_abs() => Err(ParseAmountError::OutOfRange(OutOfRangeError::too_small())),
(true, sat) if sat > i64::MIN.unsigned_abs() =>
Err(ParseAmountError::OutOfRange(OutOfRangeError::too_small())),
(true, sat) => Ok(SignedAmount(-(sat as i64))),
}
}
@ -1423,16 +1435,12 @@ impl SignedAmount {
/// Unchecked addition.
///
/// Computes `self + rhs`. Panics in debug mode, wraps in release mode.
pub fn unchecked_add(self, rhs: SignedAmount) -> SignedAmount {
Self(self.0 + rhs.0)
}
pub fn unchecked_add(self, rhs: SignedAmount) -> SignedAmount { Self(self.0 + rhs.0) }
/// Unchecked subtraction.
///
/// Computes `self - rhs`. Panics in debug mode, wraps in release mode.
pub fn unchecked_sub(self, rhs: SignedAmount) -> SignedAmount {
Self(self.0 - rhs.0)
}
pub fn unchecked_sub(self, rhs: SignedAmount) -> SignedAmount { Self(self.0 - rhs.0) }
/// Subtraction that doesn't allow negative [SignedAmount]s.
/// Returns [None] if either [self], `rhs` or the result is strictly negative.
@ -1548,9 +1556,7 @@ impl FromStr for SignedAmount {
impl TryFrom<Amount> for SignedAmount {
type Error = OutOfRangeError;
fn try_from(value: Amount) -> Result<Self, Self::Error> {
value.to_signed()
}
fn try_from(value: Amount) -> Result<Self, Self::Error> { value.to_signed() }
}
impl core::iter::Sum for SignedAmount {
@ -1621,11 +1627,12 @@ pub mod serde {
//! ```
use core::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::{Amount, SignedAmount, ParseAmountError};
#[cfg(feature = "alloc")]
use super::Denomination;
use super::{Amount, ParseAmountError, SignedAmount};
/// This trait is used only to avoid code duplication and naming collisions
/// of the different serde serialization crates.
@ -1670,9 +1677,7 @@ pub mod serde {
#[cfg(not(feature = "std"))]
impl fmt::Display for DisplayFullError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
impl SerdeAmount for Amount {
@ -1741,10 +1746,9 @@ pub mod serde {
//! Serialize and deserialize [`Amount`](crate::Amount) as real numbers denominated in satoshi.
//! Use with `#[serde(with = "amount::serde::as_sat")]`.
//!
use super::private;
use serde::{Deserializer, Serializer};
use super::private;
use crate::amount::serde::SerdeAmount;
pub fn serialize<A: SerdeAmount, S: Serializer>(a: &A, s: S) -> Result<S::Ok, S::Error> {
@ -1759,12 +1763,12 @@ pub mod serde {
//! Serialize and deserialize [`Option<Amount>`](crate::Amount) as real numbers denominated in satoshi.
//! Use with `#[serde(default, with = "amount::serde::as_sat::opt")]`.
use super::private;
use core::fmt;
use core::marker::PhantomData;
use serde::{de, Deserializer, Serializer};
use super::private;
use crate::amount::serde::SerdeAmountForOpt;
pub fn serialize<A: SerdeAmountForOpt, S: Serializer>(
@ -1812,10 +1816,9 @@ pub mod serde {
//! Serialize and deserialize [`Amount`](crate::Amount) as JSON numbers denominated in BTC.
//! Use with `#[serde(with = "amount::serde::as_btc")]`.
use super::private;
use serde::{Deserializer, Serializer};
use super::private;
use crate::amount::serde::SerdeAmount;
pub fn serialize<A: SerdeAmount, S: Serializer>(a: &A, s: S) -> Result<S::Ok, S::Error> {
@ -1830,12 +1833,12 @@ pub mod serde {
//! Serialize and deserialize `Option<Amount>` as JSON numbers denominated in BTC.
//! Use with `#[serde(default, with = "amount::serde::as_btc::opt")]`.
use super::private;
use core::fmt;
use core::marker::PhantomData;
use serde::{de, Deserializer, Serializer};
use super::private;
use crate::amount::serde::SerdeAmountForOpt;
pub fn serialize<A: SerdeAmountForOpt, S: Serializer>(
@ -1971,10 +1974,7 @@ mod verification {
if n1 >= 0 {
Ok(Amount::from_sat(n1.try_into().unwrap()))
} else {
Err(OutOfRangeError {
is_signed: true,
is_greater_than_max: false
})
Err(OutOfRangeError { is_signed: true, is_greater_than_max: false })
},
);
}
@ -2008,7 +2008,6 @@ mod verification {
mod tests {
#[cfg(feature = "alloc")]
use alloc::format;
#[cfg(feature = "std")]
use std::panic;
@ -2029,7 +2028,10 @@ mod tests {
let s = format!("-0 {}", denom);
match Amount::from_str(&s) {
Err(e) => assert_eq!(e, ParseError::Amount(ParseAmountError::OutOfRange(OutOfRangeError::negative()))),
Err(e) => assert_eq!(
e,
ParseError::Amount(ParseAmountError::OutOfRange(OutOfRangeError::negative()))
),
Ok(_) => panic!("Unsigned amount from {}", s),
}
match SignedAmount::from_str(&s) {
@ -2057,13 +2059,7 @@ mod tests {
let ua_max = Amount::MAX;
let result = SignedAmount::try_from(ua_max);
assert_eq!(
result,
Err(OutOfRangeError {
is_signed: true,
is_greater_than_max: true
})
);
assert_eq!(result, Err(OutOfRangeError { is_signed: true, is_greater_than_max: true }));
}
#[test]
@ -2074,13 +2070,7 @@ mod tests {
let sa_negative = SignedAmount(-123);
let result = Amount::try_from(sa_negative);
assert_eq!(
result,
Err(OutOfRangeError {
is_signed: false,
is_greater_than_max: false
})
);
assert_eq!(result, Err(OutOfRangeError { is_signed: false, is_greater_than_max: false }));
}
#[test]
@ -2175,7 +2165,10 @@ mod tests {
assert_eq!(sf(-100.0, D::MilliSatoshi), Err(TooPreciseError { position: 1 }.into()));
assert_eq!(f(42.123456781, D::Bitcoin), Err(TooPreciseError { position: 11 }.into()));
assert_eq!(sf(-184467440738.0, D::Bitcoin), Err(OutOfRangeError::too_small().into()));
assert_eq!(f(18446744073709551617.0, D::Satoshi), Err(OutOfRangeError::too_big(false).into()));
assert_eq!(
f(18446744073709551617.0, D::Satoshi),
Err(OutOfRangeError::too_big(false).into())
);
// Amount can be grater than the max SignedAmount.
assert!(f(SignedAmount::MAX.to_float_in(D::Satoshi) + 1.0, D::Satoshi).is_ok());
@ -2210,12 +2203,30 @@ mod tests {
let p = Amount::from_str_in;
let sp = SignedAmount::from_str_in;
assert_eq!(p("x", btc), Err(E::from(InvalidCharacterError { invalid_char: 'x', position: 0 })));
assert_eq!(p("-", btc), Err(E::from(MissingDigitsError { kind: MissingDigitsKind::OnlyMinusSign })));
assert_eq!(sp("-", btc), Err(E::from(MissingDigitsError { kind: MissingDigitsKind::OnlyMinusSign })));
assert_eq!(p("-1.0x", btc), Err(E::from(InvalidCharacterError { invalid_char: 'x', position: 4 })));
assert_eq!(p("0.0 ", btc), Err(E::from(InvalidCharacterError { invalid_char: ' ', position: 3 })));
assert_eq!(p("0.000.000", btc), Err(E::from(InvalidCharacterError { invalid_char: '.', position: 5 })));
assert_eq!(
p("x", btc),
Err(E::from(InvalidCharacterError { invalid_char: 'x', position: 0 }))
);
assert_eq!(
p("-", btc),
Err(E::from(MissingDigitsError { kind: MissingDigitsKind::OnlyMinusSign }))
);
assert_eq!(
sp("-", btc),
Err(E::from(MissingDigitsError { kind: MissingDigitsKind::OnlyMinusSign }))
);
assert_eq!(
p("-1.0x", btc),
Err(E::from(InvalidCharacterError { invalid_char: 'x', position: 4 }))
);
assert_eq!(
p("0.0 ", btc),
Err(E::from(InvalidCharacterError { invalid_char: ' ', position: 3 }))
);
assert_eq!(
p("0.000.000", btc),
Err(E::from(InvalidCharacterError { invalid_char: '.', position: 5 }))
);
#[cfg(feature = "alloc")]
let more_than_max = format!("1{}", Amount::MAX);
#[cfg(feature = "alloc")]
@ -2253,11 +2264,16 @@ mod tests {
{
let amount = Amount::from_sat(i64::MAX as u64);
assert_eq!(Amount::from_str_in(&amount.to_string_in(sat), sat), Ok(amount));
assert!(SignedAmount::from_str_in(&(amount + Amount(1)).to_string_in(sat), sat).is_err());
assert!(
SignedAmount::from_str_in(&(amount + Amount(1)).to_string_in(sat), sat).is_err()
);
assert!(Amount::from_str_in(&(amount + Amount(1)).to_string_in(sat), sat).is_ok());
}
assert_eq!(p("12.000", Denomination::MilliSatoshi), Err(TooPreciseError { position: 0 }.into()));
assert_eq!(
p("12.000", Denomination::MilliSatoshi),
Err(TooPreciseError { position: 0 }.into())
);
// exactly 50 chars.
assert_eq!(
p("100000000000000.0000000000000000000000000000000000", Denomination::Bitcoin),
@ -2500,7 +2516,10 @@ mod tests {
use super::ParseAmountError as E;
assert_eq!(Amount::from_str("x BTC"), Err(InvalidCharacterError { invalid_char: 'x', position: 0 }.into()));
assert_eq!(
Amount::from_str("x BTC"),
Err(InvalidCharacterError { invalid_char: 'x', position: 0 }.into())
);
assert_eq!(
Amount::from_str("xBTC"),
Err(Unknown(UnknownDenominationError("xBTC".into())).into()),
@ -2509,7 +2528,10 @@ mod tests {
Amount::from_str("5 BTC BTC"),
Err(Unknown(UnknownDenominationError("BTC BTC".into())).into()),
);
assert_eq!(Amount::from_str("5BTC BTC"), Err(E::from(InvalidCharacterError { invalid_char: 'B', position: 1 }).into()));
assert_eq!(
Amount::from_str("5BTC BTC"),
Err(E::from(InvalidCharacterError { invalid_char: 'B', position: 1 }).into())
);
assert_eq!(
Amount::from_str("5 5 BTC"),
Err(Unknown(UnknownDenominationError("5 BTC".into())).into()),
@ -2732,7 +2754,10 @@ mod tests {
// errors
let t: Result<T, serde_json::Error> =
serde_json::from_str("{\"amt\": 1000000.000000001, \"samt\": 1}");
assert!(t.unwrap_err().to_string().contains(&ParseAmountError::TooPrecise(TooPreciseError { position: 16 }).to_string()));
assert!(t
.unwrap_err()
.to_string()
.contains(&ParseAmountError::TooPrecise(TooPreciseError { position: 16 }).to_string()));
let t: Result<T, serde_json::Error> = serde_json::from_str("{\"amt\": -1, \"samt\": 1}");
assert!(t.unwrap_err().to_string().contains(&OutOfRangeError::negative().to_string()));
}
@ -2830,11 +2855,8 @@ mod tests {
let sum = amounts.into_iter().sum::<Amount>();
assert_eq!(Amount::from_sat(1400), sum);
let amounts = [
SignedAmount::from_sat(-42),
SignedAmount::from_sat(1337),
SignedAmount::from_sat(21),
];
let amounts =
[SignedAmount::from_sat(-42), SignedAmount::from_sat(1337), SignedAmount::from_sat(21)];
let sum = amounts.into_iter().sum::<SignedAmount>();
assert_eq!(SignedAmount::from_sat(1316), sum);
}
@ -2848,8 +2870,7 @@ mod tests {
let sum = amounts.into_iter().checked_sum();
assert_eq!(Some(Amount::from_sat(1400)), sum);
let amounts =
[Amount::from_sat(u64::MAX), Amount::from_sat(1337), Amount::from_sat(21)];
let amounts = [Amount::from_sat(u64::MAX), Amount::from_sat(1337), Amount::from_sat(21)];
let sum = amounts.into_iter().checked_sum();
assert_eq!(None, sum);
@ -2869,11 +2890,8 @@ mod tests {
let sum = amounts.into_iter().checked_sum();
assert_eq!(None, sum);
let amounts = [
SignedAmount::from_sat(42),
SignedAmount::from_sat(3301),
SignedAmount::from_sat(21),
];
let amounts =
[SignedAmount::from_sat(42), SignedAmount::from_sat(3301), SignedAmount::from_sat(21)];
let sum = amounts.into_iter().checked_sum();
assert_eq!(Some(SignedAmount::from_sat(3364)), sum);
}
@ -2932,17 +2950,8 @@ mod tests {
assert_eq!(format!("{:.2}", Amount::from_sat(100_000_000)), "1.00 BTC");
assert_eq!(format!("{}", Amount::from_sat(100_000_000)), "1 BTC");
assert_eq!(format!("{}", Amount::from_sat(40_000_000_000)), "400 BTC");
assert_eq!(
format!("{:.10}", Amount::from_sat(100_000_000)),
"1.0000000000 BTC"
);
assert_eq!(
format!("{}", Amount::from_sat(400_000_000_000_010)),
"4000000.00000010 BTC"
);
assert_eq!(
format!("{}", Amount::from_sat(400_000_000_000_000)),
"4000000 BTC"
);
assert_eq!(format!("{:.10}", Amount::from_sat(100_000_000)), "1.0000000000 BTC");
assert_eq!(format!("{}", Amount::from_sat(400_000_000_000_010)), "4000000.00000010 BTC");
assert_eq!(format!("{}", Amount::from_sat(400_000_000_000_000)), "4000000 BTC");
}
}

View File

@ -6,14 +6,11 @@
// Experimental features we need.
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
// Coding conventions.
#![warn(missing_docs)]
// Exclude lints we don't think are valuable.
#![allow(clippy::needless_question_mark)] // https://github.com/rust-bitcoin/rust-bitcoin/pull/2134
#![allow(clippy::manual_range_contains)] // More readable than clippy's format.
#![no_std]
// Disable 16-bit support at least for now as we can't guarantee it yet.
@ -39,18 +36,16 @@ mod test_macros;
pub mod amount;
#[cfg(feature = "alloc")]
pub mod locktime;
#[cfg(feature = "alloc")]
pub mod fee_rate;
#[cfg(feature = "alloc")]
pub mod locktime;
#[cfg(feature = "alloc")]
pub mod parse;
#[cfg(feature = "alloc")]
pub mod weight;
#[doc(inline)]
pub use self::{
amount::{Amount, ParseAmountError, SignedAmount},
};
pub use self::amount::{Amount, ParseAmountError, SignedAmount};
#[cfg(feature = "alloc")]
pub use self::parse::ParseIntError;

View File

@ -2,9 +2,9 @@
//! Parsing utilities.
use alloc::string::String;
use core::fmt;
use core::str::FromStr;
use alloc::string::String;
use internals::write_err;
@ -58,10 +58,7 @@ impl AsRef<core::num::ParseIntError> for ParseIntError {
/// Not strictly necessary but serves as a lint - avoids weird behavior if someone accidentally
/// passes non-integer to the `parse()` function.
pub trait Integer:
FromStr<Err = core::num::ParseIntError> + TryFrom<i8> + Sized
{
}
pub trait Integer: FromStr<Err = core::num::ParseIntError> + TryFrom<i8> + Sized {}
macro_rules! impl_integer {
($($type:ty),* $(,)?) => {