Merge rust-bitcoin/rust-bitcoin#1111: Run cargo fmt in CI
2d6467f980
Add cargo fmt to pre-commit githook (Tobin C. Harding)55312f2972
Update contributing docs re cargo fmt (Tobin C. Harding)c1360067e9
Enable formatting in CI (Tobin C. Harding)61c560baba
Improve the DO_BENCH error message (Tobin C. Harding)a11cf07501
Run the formatter (Tobin C. Harding)21d716b313
Use new fn_params_layout option (Tobin C. Harding) Pull request description: Run the formatter in CI so we stop continually introducing formatting problems in the code that is currently supposed to be formatted. ACKs for top commit: apoelstra: ACK2d6467f980
sanket1729: ACK2d6467f980
Tree-SHA512: 0dbe12bb853b0ec6102066118a9272462bf9ebf2dc53b1394c294185b9d4a824ba0cca478f500fcc44088e4bc54a61153402a6911f285435b68bc9a306f9f11f
This commit is contained in:
commit
e074ee4316
|
@ -53,6 +53,7 @@ jobs:
|
|||
uses: dtolnay/rust-toolchain@nightly
|
||||
- name: Running test script
|
||||
env:
|
||||
DO_FMT: true
|
||||
DO_BENCH: true
|
||||
AS_DEPENDENCY: false
|
||||
DO_NO_STD: true
|
||||
|
|
|
@ -170,9 +170,9 @@ Library reflects Bitcoin Core approach whenever possible.
|
|||
|
||||
### Formatting
|
||||
|
||||
The repository currently does use `rustfmt`. The introduction of this is still
|
||||
WIP (see 'ignore' in `rustfmt.toml`) but we are working towards full
|
||||
formatting.
|
||||
The repository currently uses `rustfmt` (WIP, some directories are excluded). We use nightly
|
||||
features so to run the formatter use `cargo +nightly fmt`. (Remember that your editor may be
|
||||
configured to fmt with a stable toolchain, this will result in many unwanted changes.)
|
||||
|
||||
### Naming conventions
|
||||
|
||||
|
|
|
@ -12,11 +12,16 @@ fi
|
|||
cargo --version
|
||||
rustc --version
|
||||
|
||||
# Work out if we are using a nightly toolchain.
|
||||
# Some tests require certain toolchain types.
|
||||
NIGHTLY=false
|
||||
STABLE=true
|
||||
if cargo --version | grep nightly; then
|
||||
STABLE=false
|
||||
NIGHTLY=true
|
||||
fi
|
||||
if cargo --version | grep beta; then
|
||||
STABLE=false
|
||||
fi
|
||||
|
||||
# Pin dependencies as required if we are using MSRV toolchain.
|
||||
if cargo --version | grep "1\.41"; then
|
||||
|
@ -106,16 +111,24 @@ then
|
|||
)
|
||||
fi
|
||||
|
||||
# Run formatter if told to.
|
||||
if [ "$DO_FMT" = true ]; then
|
||||
if [ "$NIGHTLY" = false ]; then
|
||||
echo "DO_FMT requires a nightly toolchain (consider using RUSTUP_TOOLCHAIN)"
|
||||
exit 1
|
||||
fi
|
||||
rustup component add rustfmt
|
||||
cargo fmt --check
|
||||
fi
|
||||
|
||||
# Bench if told to, only works with non-stable toolchain (nightly, beta).
|
||||
if [ "$DO_BENCH" = true ]
|
||||
then
|
||||
if [ "$NIGHTLY" = false ]
|
||||
then
|
||||
if [ -n "$RUSTUP_TOOLCHAIN" ]
|
||||
then
|
||||
echo "RUSTUP_TOOLCHAIN is set to a non-nightly toolchain but DO_BENCH requires a nightly toolchain"
|
||||
if [ "$STABLE" = true ]; then
|
||||
if [ -n "$RUSTUP_TOOLCHAIN" ]; then
|
||||
echo "RUSTUP_TOOLCHAIN is set to a stable toolchain but DO_BENCH requires a non-stable (beta, nightly) toolchain"
|
||||
else
|
||||
echo "DO_BENCH requires a nightly toolchain"
|
||||
echo "DO_BENCH requires a non-stable (beta, nightly) toolchain"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
@ -176,8 +176,7 @@ impl WatchOnly {
|
|||
|
||||
/// Creates the PSBT, in BIP174 parlance this is the 'Creater'.
|
||||
fn create_psbt<C: Verification>(&self, secp: &Secp256k1<C>) -> Result<Psbt> {
|
||||
let to_address = Address::from_str(RECEIVE_ADDRESS)?
|
||||
.require_network(Network::Regtest)?;
|
||||
let to_address = Address::from_str(RECEIVE_ADDRESS)?.require_network(Network::Regtest)?;
|
||||
let to_amount = Amount::from_str(OUTPUT_AMOUNT_BTC)?;
|
||||
|
||||
let (_, change_address, _) = self.change_address(secp)?;
|
||||
|
@ -187,10 +186,7 @@ impl WatchOnly {
|
|||
version: 2,
|
||||
lock_time: absolute::LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint {
|
||||
txid: INPUT_UTXO_TXID.parse()?,
|
||||
vout: INPUT_UTXO_VOUT,
|
||||
},
|
||||
previous_output: OutPoint { txid: INPUT_UTXO_TXID.parse()?, vout: INPUT_UTXO_VOUT },
|
||||
script_sig: ScriptBuf::new(),
|
||||
sequence: Sequence::MAX, // Disable LockTime and RBF.
|
||||
witness: Witness::default(),
|
||||
|
|
|
@ -88,7 +88,8 @@ use bitcoin::secp256k1::Secp256k1;
|
|||
use bitcoin::sighash::{self, SighashCache, TapSighash, TapSighashType};
|
||||
use bitcoin::taproot::{self, LeafVersion, TapLeafHash, TaprootBuilder, TaprootSpendInfo};
|
||||
use bitcoin::{
|
||||
absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Witness,
|
||||
absolute, script, Address, Amount, Network, OutPoint, ScriptBuf, Transaction, TxIn, TxOut,
|
||||
Witness,
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
@ -100,10 +101,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
// Just some addresses for outputs from our wallets. Not really important.
|
||||
let to_address =
|
||||
Address::from_str("bcrt1p0p3rvwww0v9znrclp00uneq8ytre9kj922v8fxhnezm3mgsmn9usdxaefc")?
|
||||
.require_network(Network::Regtest)?;
|
||||
.require_network(Network::Regtest)?;
|
||||
let change_address =
|
||||
Address::from_str("bcrt1pz449kexzydh2kaypatup5ultru3ej284t6eguhnkn6wkhswt0l7q3a7j76")?
|
||||
.require_network(Network::Regtest)?;
|
||||
.require_network(Network::Regtest)?;
|
||||
let amount_to_send_in_sats = COIN_VALUE;
|
||||
let change_amount = UTXO_1
|
||||
.amount_in_sats
|
||||
|
@ -233,10 +234,7 @@ fn generate_bip86_key_spend_tx(
|
|||
version: 2,
|
||||
lock_time: absolute::LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint {
|
||||
txid: input_utxo.txid.parse()?,
|
||||
vout: input_utxo.vout,
|
||||
},
|
||||
previous_output: OutPoint { txid: input_utxo.txid.parse()?, vout: input_utxo.vout },
|
||||
script_sig: ScriptBuf::new(),
|
||||
sequence: bitcoin::Sequence(0xFFFFFFFF), // Ignore nSequence.
|
||||
witness: Witness::default(),
|
||||
|
@ -363,7 +361,10 @@ impl BenefactorWallet {
|
|||
})
|
||||
}
|
||||
|
||||
fn time_lock_script(locktime: absolute::LockTime, beneficiary_key: XOnlyPublicKey) -> ScriptBuf {
|
||||
fn time_lock_script(
|
||||
locktime: absolute::LockTime,
|
||||
beneficiary_key: XOnlyPublicKey,
|
||||
) -> ScriptBuf {
|
||||
script::Builder::new()
|
||||
.push_int(locktime.to_consensus_u32() as i64)
|
||||
.push_opcode(OP_CLTV)
|
||||
|
|
|
@ -43,7 +43,9 @@ use crate::blockdata::constants::{
|
|||
};
|
||||
use crate::blockdata::opcodes;
|
||||
use crate::blockdata::opcodes::all::*;
|
||||
use crate::blockdata::script::{self, Instruction, Script, ScriptBuf, PushBytes, PushBytesBuf, PushBytesErrorReport};
|
||||
use crate::blockdata::script::{
|
||||
self, Instruction, PushBytes, PushBytesBuf, PushBytesErrorReport, Script, ScriptBuf,
|
||||
};
|
||||
use crate::crypto::key::{PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey};
|
||||
use crate::error::ParseIntError;
|
||||
use crate::hash_types::{PubkeyHash, ScriptHash};
|
||||
|
@ -94,8 +96,8 @@ pub enum Error {
|
|||
/// Network on which the address was found to be valid.
|
||||
found: Network,
|
||||
/// The address itself
|
||||
address: Address<NetworkUnchecked>
|
||||
}
|
||||
address: Address<NetworkUnchecked>,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
|
@ -412,8 +414,13 @@ pub struct WitnessProgram {
|
|||
|
||||
impl WitnessProgram {
|
||||
/// Creates a new witness program.
|
||||
pub fn new<P>(version: WitnessVersion, program: P) -> Result<Self, Error> where P: TryInto<PushBytesBuf>, <P as TryInto<PushBytesBuf>>::Error: PushBytesErrorReport {
|
||||
let program = program.try_into()
|
||||
pub fn new<P>(version: WitnessVersion, program: P) -> Result<Self, Error>
|
||||
where
|
||||
P: TryInto<PushBytesBuf>,
|
||||
<P as TryInto<PushBytesBuf>>::Error: PushBytesErrorReport,
|
||||
{
|
||||
let program = program
|
||||
.try_into()
|
||||
.map_err(|error| Error::InvalidWitnessProgramLength(error.input_len()))?;
|
||||
if program.len() < 2 || program.len() > 40 {
|
||||
return Err(Error::InvalidWitnessProgramLength(program.len()));
|
||||
|
@ -427,14 +434,10 @@ impl WitnessProgram {
|
|||
}
|
||||
|
||||
/// Returns the witness program version.
|
||||
pub fn version(&self) -> WitnessVersion {
|
||||
self.version
|
||||
}
|
||||
pub fn version(&self) -> WitnessVersion { self.version }
|
||||
|
||||
/// Returns the witness program.
|
||||
pub fn program(&self) -> &PushBytes {
|
||||
&self.program
|
||||
}
|
||||
pub fn program(&self) -> &PushBytes { &self.program }
|
||||
}
|
||||
|
||||
impl Payload {
|
||||
|
@ -443,21 +446,16 @@ impl Payload {
|
|||
Ok(if script.is_p2pkh() {
|
||||
let bytes = script.as_bytes()[3..23].try_into().expect("statically 20B long");
|
||||
Payload::PubkeyHash(PubkeyHash::from_byte_array(bytes))
|
||||
|
||||
} else if script.is_p2sh() {
|
||||
let bytes = script.as_bytes()[2..22].try_into().expect("statically 20B long");
|
||||
Payload::ScriptHash(ScriptHash::from_byte_array(bytes))
|
||||
} else if script.is_witness_program() {
|
||||
let opcode = script.first_opcode().expect("witness_version guarantees len() > 4");
|
||||
|
||||
let witness_program = script
|
||||
.as_bytes()[2..]
|
||||
.to_vec();
|
||||
let witness_program = script.as_bytes()[2..].to_vec();
|
||||
|
||||
let witness_program = WitnessProgram::new(
|
||||
WitnessVersion::try_from(opcode)?,
|
||||
witness_program,
|
||||
)?;
|
||||
let witness_program =
|
||||
WitnessProgram::new(WitnessVersion::try_from(opcode)?, witness_program)?;
|
||||
Payload::WitnessProgram(witness_program)
|
||||
} else {
|
||||
return Err(Error::UnrecognizedScript);
|
||||
|
@ -469,8 +467,7 @@ impl Payload {
|
|||
match *self {
|
||||
Payload::PubkeyHash(ref hash) => ScriptBuf::new_p2pkh(hash),
|
||||
Payload::ScriptHash(ref hash) => ScriptBuf::new_p2sh(hash),
|
||||
Payload::WitnessProgram(ref prog) =>
|
||||
ScriptBuf::new_witness_program(prog)
|
||||
Payload::WitnessProgram(ref prog) => ScriptBuf::new_witness_program(prog),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,15 +475,12 @@ impl Payload {
|
|||
/// This function doesn't make any allocations.
|
||||
pub fn matches_script_pubkey(&self, script: &Script) -> bool {
|
||||
match *self {
|
||||
Payload::PubkeyHash(ref hash) if script.is_p2pkh() => {
|
||||
&script.as_bytes()[3..23] == <PubkeyHash as AsRef<[u8; 20]>>::as_ref(hash)
|
||||
},
|
||||
Payload::ScriptHash(ref hash) if script.is_p2sh() => {
|
||||
&script.as_bytes()[2..22] == <ScriptHash as AsRef<[u8; 20]>>::as_ref(hash)
|
||||
},
|
||||
Payload::WitnessProgram(ref prog) if script.is_witness_program() => {
|
||||
&script.as_bytes()[2..] == prog.program.as_bytes()
|
||||
},
|
||||
Payload::PubkeyHash(ref hash) if script.is_p2pkh() =>
|
||||
&script.as_bytes()[3..23] == <PubkeyHash as AsRef<[u8; 20]>>::as_ref(hash),
|
||||
Payload::ScriptHash(ref hash) if script.is_p2sh() =>
|
||||
&script.as_bytes()[2..22] == <ScriptHash as AsRef<[u8; 20]>>::as_ref(hash),
|
||||
Payload::WitnessProgram(ref prog) if script.is_witness_program() =>
|
||||
&script.as_bytes()[2..] == prog.program.as_bytes(),
|
||||
Payload::PubkeyHash(_) | Payload::ScriptHash(_) | Payload::WitnessProgram(_) => false,
|
||||
}
|
||||
}
|
||||
|
@ -508,7 +502,7 @@ impl Payload {
|
|||
pub fn p2wpkh(pk: &PublicKey) -> Result<Payload, Error> {
|
||||
let prog = WitnessProgram::new(
|
||||
WitnessVersion::V0,
|
||||
pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?
|
||||
pk.wpubkey_hash().ok_or(Error::UncompressedPubkey)?,
|
||||
)?;
|
||||
Ok(Payload::WitnessProgram(prog))
|
||||
}
|
||||
|
@ -524,17 +518,14 @@ impl Payload {
|
|||
|
||||
/// Create a witness pay to script hash payload.
|
||||
pub fn p2wsh(script: &Script) -> Payload {
|
||||
let prog = WitnessProgram::new(
|
||||
WitnessVersion::V0,
|
||||
script.wscript_hash()
|
||||
).expect("wscript_hash has len 32 compatible with segwitv0");
|
||||
let prog = WitnessProgram::new(WitnessVersion::V0, script.wscript_hash())
|
||||
.expect("wscript_hash has len 32 compatible with segwitv0");
|
||||
Payload::WitnessProgram(prog)
|
||||
}
|
||||
|
||||
/// Create a pay to script payload that embeds a witness pay to script hash address
|
||||
pub fn p2shwsh(script: &Script) -> Payload {
|
||||
let ws =
|
||||
script::Builder::new().push_int(0).push_slice(script.wscript_hash()).into_script();
|
||||
let ws = script::Builder::new().push_int(0).push_slice(script.wscript_hash()).into_script();
|
||||
|
||||
Payload::ScriptHash(ws.script_hash())
|
||||
}
|
||||
|
@ -546,10 +537,8 @@ impl Payload {
|
|||
merkle_root: Option<TapNodeHash>,
|
||||
) -> Payload {
|
||||
let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
|
||||
let prog = WitnessProgram::new(
|
||||
WitnessVersion::V1,
|
||||
output_key.to_inner().serialize()
|
||||
).expect("taproot output key has len 32 <= 40");
|
||||
let prog = WitnessProgram::new(WitnessVersion::V1, output_key.to_inner().serialize())
|
||||
.expect("taproot output key has len 32 <= 40");
|
||||
Payload::WitnessProgram(prog)
|
||||
}
|
||||
|
||||
|
@ -557,10 +546,8 @@ impl Payload {
|
|||
///
|
||||
/// This method is not recommended for use and [Payload::p2tr()] should be used where possible.
|
||||
pub fn p2tr_tweaked(output_key: TweakedPublicKey) -> Payload {
|
||||
let prog = WitnessProgram::new(
|
||||
WitnessVersion::V1,
|
||||
output_key.to_inner().serialize()
|
||||
).expect("taproot output key has len 32 <= 40");
|
||||
let prog = WitnessProgram::new(WitnessVersion::V1, output_key.to_inner().serialize())
|
||||
.expect("taproot output key has len 32 <= 40");
|
||||
Payload::WitnessProgram(prog)
|
||||
}
|
||||
|
||||
|
@ -644,8 +631,12 @@ pub enum NetworkChecked {}
|
|||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum NetworkUnchecked {}
|
||||
|
||||
impl NetworkValidation for NetworkChecked { const IS_CHECKED: bool = true; }
|
||||
impl NetworkValidation for NetworkUnchecked { const IS_CHECKED: bool = false; }
|
||||
impl NetworkValidation for NetworkChecked {
|
||||
const IS_CHECKED: bool = true;
|
||||
}
|
||||
impl NetworkValidation for NetworkUnchecked {
|
||||
const IS_CHECKED: bool = false;
|
||||
}
|
||||
|
||||
/// A Bitcoin address.
|
||||
///
|
||||
|
@ -792,7 +783,9 @@ impl<V: NetworkValidation> Address<V> {
|
|||
WitnessVersion::V0 => match prog.program().len() {
|
||||
20 => Some(AddressType::P2wpkh),
|
||||
32 => Some(AddressType::P2wsh),
|
||||
_ => unreachable!("Address creation invariant violation: invalid program length")
|
||||
_ => unreachable!(
|
||||
"Address creation invariant violation: invalid program length"
|
||||
),
|
||||
},
|
||||
WitnessVersion::V1 if prog.program().len() == 32 => Some(AddressType::P2tr),
|
||||
_ => None,
|
||||
|
@ -828,7 +821,7 @@ impl<V: NetworkValidation> Address<V> {
|
|||
/// marker type of the address.
|
||||
#[inline]
|
||||
pub fn new(network: Network, payload: Payload) -> Address<V> {
|
||||
Address { network, payload, _validation: PhantomData }
|
||||
Address { network, payload, _validation: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -905,9 +898,7 @@ impl Address {
|
|||
/// # Returns
|
||||
/// None if unknown, non-standard or related to the future witness version.
|
||||
#[inline]
|
||||
pub fn address_type(&self) -> Option<AddressType> {
|
||||
self.address_type_internal()
|
||||
}
|
||||
pub fn address_type(&self) -> Option<AddressType> { self.address_type_internal() }
|
||||
|
||||
/// Checks whether or not the address is following Bitcoin standardness rules when
|
||||
/// *spending* from this address. *NOT* to be called by senders.
|
||||
|
@ -1042,15 +1033,11 @@ impl Address<NetworkUnchecked> {
|
|||
/// For details about this mechanism, see section [*Parsing addresses*](Address#parsing-addresses)
|
||||
/// on [`Address`].
|
||||
#[inline]
|
||||
pub fn assume_checked(self) -> Address {
|
||||
Address::new(self.network, self.payload)
|
||||
}
|
||||
pub fn assume_checked(self) -> Address { Address::new(self.network, self.payload) }
|
||||
}
|
||||
|
||||
impl From<Address> for script::ScriptBuf {
|
||||
fn from(a: Address) -> Self {
|
||||
a.script_pubkey()
|
||||
}
|
||||
fn from(a: Address) -> Self { a.script_pubkey() }
|
||||
}
|
||||
|
||||
// Alternate formatting `{:#}` is used to return uppercase version of bech32 addresses which should
|
||||
|
@ -1168,11 +1155,11 @@ fn segwit_redeem_hash(pubkey_hash: &PubkeyHash) -> crate::hashes::hash160::Hash
|
|||
mod tests {
|
||||
use core::str::FromStr;
|
||||
|
||||
use hex_lit::hex;
|
||||
use secp256k1::XOnlyPublicKey;
|
||||
|
||||
use super::*;
|
||||
use crate::crypto::key::PublicKey;
|
||||
use hex_lit::hex;
|
||||
use crate::network::constants::Network::{Bitcoin, Testnet};
|
||||
|
||||
fn roundtrips(addr: &Address) {
|
||||
|
@ -1192,14 +1179,18 @@ mod tests {
|
|||
#[cfg(feature = "serde")]
|
||||
{
|
||||
let ser = serde_json::to_string(addr).expect("failed to serialize address");
|
||||
let back: Address<NetworkUnchecked> = serde_json::from_str(&ser).expect("failed to deserialize address");
|
||||
let back: Address<NetworkUnchecked> =
|
||||
serde_json::from_str(&ser).expect("failed to deserialize address");
|
||||
assert_eq!(back.assume_checked(), *addr, "serde round-trip failed for {}", addr)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_p2pkh_address_58() {
|
||||
let addr = Address::new(Bitcoin, Payload::PubkeyHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()));
|
||||
let addr = Address::new(
|
||||
Bitcoin,
|
||||
Payload::PubkeyHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
addr.script_pubkey(),
|
||||
|
@ -1216,7 +1207,9 @@ mod tests {
|
|||
let addr = Address::p2pkh(&key, Bitcoin);
|
||||
assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY");
|
||||
|
||||
let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f".parse::<PublicKey>().unwrap();
|
||||
let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f"
|
||||
.parse::<PublicKey>()
|
||||
.unwrap();
|
||||
let addr = Address::p2pkh(&key, Testnet);
|
||||
assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC");
|
||||
assert_eq!(addr.address_type(), Some(AddressType::P2pkh));
|
||||
|
@ -1225,7 +1218,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_p2sh_address_58() {
|
||||
let addr = Address::new(Bitcoin, Payload::ScriptHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()));
|
||||
let addr = Address::new(
|
||||
Bitcoin,
|
||||
Payload::ScriptHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
addr.script_pubkey(),
|
||||
|
@ -1254,7 +1250,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_p2wpkh() {
|
||||
// stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20
|
||||
let mut key = "033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc".parse::<PublicKey>().unwrap();
|
||||
let mut key = "033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc"
|
||||
.parse::<PublicKey>()
|
||||
.unwrap();
|
||||
let addr = Address::p2wpkh(&key, Bitcoin).unwrap();
|
||||
assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw");
|
||||
assert_eq!(addr.address_type(), Some(AddressType::P2wpkh));
|
||||
|
@ -1281,7 +1279,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_p2shwpkh() {
|
||||
// stolen from Bitcoin transaction: ad3fd9c6b52e752ba21425435ff3dd361d6ac271531fc1d2144843a9f550ad01
|
||||
let mut key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766".parse::<PublicKey>().unwrap();
|
||||
let mut key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766"
|
||||
.parse::<PublicKey>()
|
||||
.unwrap();
|
||||
let addr = Address::p2shwpkh(&key, Bitcoin).unwrap();
|
||||
assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE");
|
||||
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
|
||||
|
@ -1305,7 +1305,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_non_existent_segwit_version() {
|
||||
// 40-byte program
|
||||
let program = hex!("654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4");
|
||||
let program = hex!(
|
||||
"654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4"
|
||||
);
|
||||
let witness_prog = WitnessProgram::new(WitnessVersion::V13, program.to_vec()).unwrap();
|
||||
let addr = Address::new(Bitcoin, Payload::WitnessProgram(witness_prog));
|
||||
roundtrips(&addr);
|
||||
|
@ -1315,19 +1317,24 @@ mod tests {
|
|||
fn test_address_debug() {
|
||||
// This is not really testing output of Debug but the ability and proper functioning
|
||||
// of Debug derivation on structs generic in NetworkValidation.
|
||||
#[derive(Debug)] #[allow(unused)]
|
||||
struct Test<V: NetworkValidation> { address: Address<V> }
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
struct Test<V: NetworkValidation> {
|
||||
address: Address<V>,
|
||||
}
|
||||
|
||||
let addr_str = "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k";
|
||||
let unchecked = Address::from_str(addr_str).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
format!("{:?}", Test { address: unchecked.clone() }),
|
||||
format!("Test {{ address: Address<NetworkUnchecked>({}) }}", addr_str));
|
||||
format!("Test {{ address: Address<NetworkUnchecked>({}) }}", addr_str)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
format!("{:?}", Test { address: unchecked.assume_checked() }),
|
||||
format!("Test {{ address: {} }}", addr_str));
|
||||
format!("Test {{ address: {} }}", addr_str)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1442,7 +1449,8 @@ mod tests {
|
|||
fn test_json_serialize() {
|
||||
use serde_json;
|
||||
|
||||
let addr = Address::from_str("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM").unwrap().assume_checked();
|
||||
let addr =
|
||||
Address::from_str("132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM").unwrap().assume_checked();
|
||||
let json = serde_json::to_value(&addr).unwrap();
|
||||
assert_eq!(
|
||||
json,
|
||||
|
@ -1455,7 +1463,8 @@ mod tests {
|
|||
ScriptBuf::from_hex("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac").unwrap()
|
||||
);
|
||||
|
||||
let addr = Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap().assume_checked();
|
||||
let addr =
|
||||
Address::from_str("33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k").unwrap().assume_checked();
|
||||
let json = serde_json::to_value(&addr).unwrap();
|
||||
assert_eq!(
|
||||
json,
|
||||
|
@ -1481,7 +1490,8 @@ mod tests {
|
|||
|
||||
let addr =
|
||||
Address::from_str("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7")
|
||||
.unwrap().assume_checked();
|
||||
.unwrap()
|
||||
.assume_checked();
|
||||
let json = serde_json::to_value(&addr).unwrap();
|
||||
assert_eq!(
|
||||
json,
|
||||
|
@ -1493,10 +1503,15 @@ mod tests {
|
|||
assert_eq!(addr.to_string(), into.to_string());
|
||||
assert_eq!(
|
||||
into.script_pubkey(),
|
||||
ScriptBuf::from_hex("00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262").unwrap()
|
||||
ScriptBuf::from_hex(
|
||||
"00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl").unwrap().assume_checked();
|
||||
let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl")
|
||||
.unwrap()
|
||||
.assume_checked();
|
||||
let json = serde_json::to_value(&addr).unwrap();
|
||||
assert_eq!(
|
||||
json,
|
||||
|
@ -1515,7 +1530,8 @@ mod tests {
|
|||
for el in
|
||||
["132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"].iter()
|
||||
{
|
||||
let addr = Address::from_str(el).unwrap().require_network(Network::Bitcoin).expect("mainnet");
|
||||
let addr =
|
||||
Address::from_str(el).unwrap().require_network(Network::Bitcoin).expect("mainnet");
|
||||
assert_eq!(addr.to_qr_uri(), format!("bitcoin:{}", el));
|
||||
}
|
||||
|
||||
|
@ -1537,10 +1553,15 @@ mod tests {
|
|||
Payload::ScriptHash(ScriptHash::all_zeros()),
|
||||
];
|
||||
let segwit_payload = (0..=16)
|
||||
.map(|version| Payload::WitnessProgram(WitnessProgram::new(
|
||||
WitnessVersion::try_from(version).unwrap(),
|
||||
vec![0xab; 32], // Choose 32 to make test case valid for all witness versions(including v0)
|
||||
).unwrap()))
|
||||
.map(|version| {
|
||||
Payload::WitnessProgram(
|
||||
WitnessProgram::new(
|
||||
WitnessVersion::try_from(version).unwrap(),
|
||||
vec![0xab; 32], // Choose 32 to make test case valid for all witness versions(including v0)
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
const LEGACY_EQUIVALENCE_CLASSES: &[&[Network]] =
|
||||
|
@ -1726,9 +1747,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_fail_address_from_script() {
|
||||
let bad_p2wpkh = ScriptBuf::from_hex("0014dbc5b0a8f9d4353b4b54c3db48846bb15abfec").unwrap();
|
||||
let bad_p2wsh =
|
||||
ScriptBuf::from_hex("00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623").unwrap();
|
||||
let invalid_segwitv0_script = ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
|
||||
let bad_p2wsh = ScriptBuf::from_hex(
|
||||
"00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623",
|
||||
)
|
||||
.unwrap();
|
||||
let invalid_segwitv0_script =
|
||||
ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
|
||||
let expected = Err(Error::UnrecognizedScript);
|
||||
|
||||
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
|
||||
|
@ -1765,15 +1789,10 @@ mod tests {
|
|||
"bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e",
|
||||
];
|
||||
for addr in &addresses {
|
||||
let addr = Address::from_str(addr)
|
||||
.unwrap()
|
||||
.require_network(Network::Bitcoin)
|
||||
.unwrap();
|
||||
let addr = Address::from_str(addr).unwrap().require_network(Network::Bitcoin).unwrap();
|
||||
for another in &addresses {
|
||||
let another = Address::from_str(another)
|
||||
.unwrap()
|
||||
.require_network(Network::Bitcoin)
|
||||
.unwrap();
|
||||
let another =
|
||||
Address::from_str(another).unwrap().require_network(Network::Bitcoin).unwrap();
|
||||
assert_eq!(addr.matches_script_pubkey(&another.script_pubkey()), addr == another);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,13 +307,13 @@ fn parse_signed_to_satoshi(
|
|||
}
|
||||
|
||||
fn split_amount_and_denomination(s: &str) -> Result<(&str, Denomination), ParseAmountError> {
|
||||
let (i, j) = if let Some(i) = s.find(' ') {
|
||||
(i, i + 1)
|
||||
} else {
|
||||
let i = s.find(|c: char| c.is_alphabetic()).ok_or(ParseAmountError::InvalidFormat)?;
|
||||
(i, i)
|
||||
};
|
||||
Ok((&s[..i], s[j..].parse()?))
|
||||
let (i, j) = if let Some(i) = s.find(' ') {
|
||||
(i, i + 1)
|
||||
} else {
|
||||
let i = s.find(|c: char| c.is_alphabetic()).ok_or(ParseAmountError::InvalidFormat)?;
|
||||
(i, i)
|
||||
};
|
||||
Ok((&s[..i], s[j..].parse()?))
|
||||
}
|
||||
|
||||
/// Options given by `fmt::Formatter`
|
||||
|
@ -1945,14 +1945,14 @@ mod tests {
|
|||
|
||||
#[cfg_attr(rust_v_1_46, track_caller)]
|
||||
fn case(s: &str, expected: Result<Amount, ParseAmountError>) {
|
||||
assert_eq!(Amount::from_str(s), expected);
|
||||
assert_eq!(Amount::from_str(&s.replace(' ', "")), expected);
|
||||
assert_eq!(Amount::from_str(s), expected);
|
||||
assert_eq!(Amount::from_str(&s.replace(' ', "")), expected);
|
||||
}
|
||||
|
||||
#[cfg_attr(rust_v_1_46, track_caller)]
|
||||
fn scase(s: &str, expected: Result<SignedAmount, ParseAmountError>) {
|
||||
assert_eq!(SignedAmount::from_str(s), expected);
|
||||
assert_eq!(SignedAmount::from_str(&s.replace(' ', "")), expected);
|
||||
assert_eq!(SignedAmount::from_str(s), expected);
|
||||
assert_eq!(SignedAmount::from_str(&s.replace(' ', "")), expected);
|
||||
}
|
||||
|
||||
case("5 BCH", Err(E::UnknownDenomination("BCH".to_owned())));
|
||||
|
@ -2078,12 +2078,12 @@ mod tests {
|
|||
assert_eq!(Amount::from_str(&denom(amt, D::PicoBitcoin)), Ok(amt));
|
||||
|
||||
assert_eq!(
|
||||
Amount::from_str("42 satoshi BTC"),
|
||||
Err(ParseAmountError::UnknownDenomination("satoshi BTC".into())),
|
||||
Amount::from_str("42 satoshi BTC"),
|
||||
Err(ParseAmountError::UnknownDenomination("satoshi BTC".into())),
|
||||
);
|
||||
assert_eq!(
|
||||
SignedAmount::from_str("-42 satoshi BTC"),
|
||||
Err(ParseAmountError::UnknownDenomination("satoshi BTC".into())),
|
||||
SignedAmount::from_str("-42 satoshi BTC"),
|
||||
Err(ParseAmountError::UnknownDenomination("satoshi BTC".into())),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -375,8 +375,8 @@ mod test {
|
|||
use super::*;
|
||||
use crate::blockdata::locktime::absolute;
|
||||
use crate::consensus::encode::{deserialize, serialize};
|
||||
use crate::hashes::hex::FromHex;
|
||||
use crate::hash_types::TxMerkleNode;
|
||||
use crate::hashes::hex::FromHex;
|
||||
use crate::{
|
||||
CompactTarget, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
|
||||
};
|
||||
|
|
|
@ -561,8 +561,8 @@ mod test {
|
|||
use super::*;
|
||||
use crate::consensus::encode::deserialize;
|
||||
use crate::hash_types::BlockHash;
|
||||
use crate::ScriptBuf;
|
||||
use crate::internal_macros::hex;
|
||||
use crate::ScriptBuf;
|
||||
|
||||
#[test]
|
||||
fn test_blockfilters() {
|
||||
|
@ -572,8 +572,7 @@ mod test {
|
|||
let testdata = serde_json::from_str::<Value>(data).unwrap().as_array().unwrap().clone();
|
||||
for t in testdata.iter().skip(1) {
|
||||
let block_hash = t.get(1).unwrap().as_str().unwrap().parse::<BlockHash>().unwrap();
|
||||
let block: Block =
|
||||
deserialize(&hex!(t.get(2).unwrap().as_str().unwrap())).unwrap();
|
||||
let block: Block = deserialize(&hex!(t.get(2).unwrap().as_str().unwrap())).unwrap();
|
||||
assert_eq!(block.block_hash(), block_hash);
|
||||
let scripts = t.get(3).unwrap().as_array().unwrap();
|
||||
let previous_filter_header =
|
||||
|
|
|
@ -475,7 +475,8 @@ impl fmt::Display for Error {
|
|||
write!(f, "encoded extended key data has wrong length {}", len),
|
||||
Error::Base58(ref e) => write_err!(f, "base58 encoding error"; e),
|
||||
Error::Hex(ref e) => write_err!(f, "Hexadecimal decoding error"; e),
|
||||
Error::InvalidPublicKeyHexLength(got) => write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got),
|
||||
Error::InvalidPublicKeyHexLength(got) =>
|
||||
write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -622,9 +623,13 @@ impl ExtendedPrivKey {
|
|||
Ok(ExtendedPrivKey {
|
||||
network,
|
||||
depth: data[4],
|
||||
parent_fingerprint: data[5..9].try_into().expect("9 - 5 == 4, which is the Fingerprint length"),
|
||||
parent_fingerprint: data[5..9]
|
||||
.try_into()
|
||||
.expect("9 - 5 == 4, which is the Fingerprint length"),
|
||||
child_number: u32::from_be_bytes(data[9..13].try_into().expect("4 byte slice")).into(),
|
||||
chain_code: data[13..45].try_into().expect("45 - 13 == 32, which is the ChainCode length"),
|
||||
chain_code: data[13..45]
|
||||
.try_into()
|
||||
.expect("45 - 13 == 32, which is the ChainCode length"),
|
||||
private_key: secp256k1::SecretKey::from_slice(&data[46..78])?,
|
||||
})
|
||||
}
|
||||
|
@ -754,9 +759,13 @@ impl ExtendedPubKey {
|
|||
return Err(Error::UnknownVersion(ver));
|
||||
},
|
||||
depth: data[4],
|
||||
parent_fingerprint: data[5..9].try_into().expect("9 - 5 == 4, which is the Fingerprint length"),
|
||||
parent_fingerprint: data[5..9]
|
||||
.try_into()
|
||||
.expect("9 - 5 == 4, which is the Fingerprint length"),
|
||||
child_number: u32::from_be_bytes(data[9..13].try_into().expect("4 byte slice")).into(),
|
||||
chain_code: data[13..45].try_into().expect("45 - 13 == 32, which is the ChainCode length"),
|
||||
chain_code: data[13..45]
|
||||
.try_into()
|
||||
.expect("45 - 13 == 32, which is the ChainCode length"),
|
||||
public_key: secp256k1::PublicKey::from_slice(&data[45..78])?,
|
||||
})
|
||||
}
|
||||
|
@ -786,7 +795,9 @@ impl ExtendedPubKey {
|
|||
}
|
||||
|
||||
/// Returns the first four bytes of the identifier
|
||||
pub fn fingerprint(&self) -> Fingerprint { self.identifier()[0..4].try_into().expect("4 is the fingerprint length") }
|
||||
pub fn fingerprint(&self) -> Fingerprint {
|
||||
self.identifier()[0..4].try_into().expect("4 is the fingerprint length")
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ExtendedPrivKey {
|
||||
|
|
|
@ -84,14 +84,14 @@ macro_rules! impl_bytes_newtype {
|
|||
|
||||
impl core::fmt::LowerHex for $t {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
use bitcoin_internals::hex::{Case, display};
|
||||
use bitcoin_internals::hex::{display, Case};
|
||||
display::fmt_hex_exact!(f, $len, &self.0, Case::Lower)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::UpperHex for $t {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
use bitcoin_internals::hex::{Case, display};
|
||||
use bitcoin_internals::hex::{display, Case};
|
||||
display::fmt_hex_exact!(f, $len, &self.0, Case::Upper)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
// 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))]
|
||||
|
||||
|
@ -132,7 +131,9 @@ pub use crate::consensus::encode::VarInt;
|
|||
pub use crate::crypto::key::{self, PrivateKey, PublicKey};
|
||||
pub use crate::crypto::{ecdsa, sighash};
|
||||
pub use crate::error::Error;
|
||||
pub use crate::hash_types::{Txid, Wtxid, BlockHash, PubkeyHash, ScriptHash, WPubkeyHash, WScriptHash};
|
||||
pub use crate::hash_types::{
|
||||
BlockHash, PubkeyHash, ScriptHash, Txid, WPubkeyHash, WScriptHash, Wtxid,
|
||||
};
|
||||
pub use crate::merkle_tree::MerkleBlock;
|
||||
pub use crate::network::constants::Network;
|
||||
pub use crate::pow::{CompactTarget, Target, Work};
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
use core::fmt;
|
||||
|
||||
use self::MerkleBlockError::*;
|
||||
use crate::blockdata::block::{self, Block};
|
||||
use crate::blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
|
||||
use crate::blockdata::transaction::Transaction;
|
||||
|
@ -49,7 +50,6 @@ use crate::hash_types::{TxMerkleNode, Txid};
|
|||
use crate::hashes::Hash;
|
||||
use crate::io;
|
||||
use crate::prelude::*;
|
||||
use self::MerkleBlockError::*;
|
||||
|
||||
/// Data structure that represents a block header paired to a partial merkle tree.
|
||||
///
|
||||
|
@ -509,8 +509,9 @@ impl std::error::Error for MerkleBlockError {
|
|||
use self::MerkleBlockError::*;
|
||||
|
||||
match *self {
|
||||
MerkleRootMismatch | NoTransactions | TooManyTransactions | TooManyHashes | NotEnoughBits | NotAllBitsConsumed |
|
||||
NotAllHashesConsumed | BitsArrayOverflow | HashesArrayOverflow | IdenticalHashesFound => None,
|
||||
MerkleRootMismatch | NoTransactions | TooManyTransactions | TooManyHashes
|
||||
| NotEnoughBits | NotAllBitsConsumed | NotAllHashesConsumed | BitsArrayOverflow
|
||||
| HashesArrayOverflow | IdenticalHashesFound => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -564,6 +565,7 @@ mod tests {
|
|||
#[cfg(feature = "rand-std")]
|
||||
fn pmt_test(tx_count: usize) {
|
||||
use core::cmp::min;
|
||||
|
||||
use crate::merkle_tree;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
|
|
@ -454,8 +454,7 @@ mod test {
|
|||
assert!(deserialize::<AddrV2>(&hex!("01fd010201020304")).is_err());
|
||||
|
||||
// Valid IPv6.
|
||||
let ip: AddrV2 =
|
||||
deserialize(&hex!("02100102030405060708090a0b0c0d0e0f10")).unwrap();
|
||||
let ip: AddrV2 = deserialize(&hex!("02100102030405060708090a0b0c0d0e0f10")).unwrap();
|
||||
assert_eq!(
|
||||
ip,
|
||||
AddrV2::Ipv6(Ipv6Addr::from_str("102:304:506:708:90a:b0c:d0e:f10").unwrap())
|
||||
|
@ -465,16 +464,10 @@ mod test {
|
|||
assert!(deserialize::<AddrV2>(&hex!("020400")).is_err());
|
||||
|
||||
// Invalid IPv6, contains embedded IPv4.
|
||||
assert!(deserialize::<AddrV2>(
|
||||
&hex!("021000000000000000000000ffff01020304")
|
||||
)
|
||||
.is_err());
|
||||
assert!(deserialize::<AddrV2>(&hex!("021000000000000000000000ffff01020304")).is_err());
|
||||
|
||||
// Invalid IPv6, contains embedded TORv2.
|
||||
assert!(deserialize::<AddrV2>(
|
||||
&hex!("0210fd87d87eeb430102030405060708090a")
|
||||
)
|
||||
.is_err());
|
||||
assert!(deserialize::<AddrV2>(&hex!("0210fd87d87eeb430102030405060708090a")).is_err());
|
||||
|
||||
// Valid TORv2.
|
||||
let ip: AddrV2 = deserialize(&hex!("030af1f2f3f4f5f6f7f8f9fa")).unwrap();
|
||||
|
@ -484,10 +477,9 @@ mod test {
|
|||
assert!(deserialize::<AddrV2>(&hex!("030700")).is_err());
|
||||
|
||||
// Valid TORv3.
|
||||
let ip: AddrV2 = deserialize(
|
||||
&hex!("042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f")
|
||||
,
|
||||
)
|
||||
let ip: AddrV2 = deserialize(&hex!(
|
||||
"042079bcc625184b05194975c28b66b66b0469f7f6556fb1ac3189a79b40dda32f1f"
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
ip,
|
||||
|
@ -503,10 +495,9 @@ mod test {
|
|||
assert!(deserialize::<AddrV2>(&hex!("040000")).is_err());
|
||||
|
||||
// Valid I2P.
|
||||
let ip: AddrV2 = deserialize(
|
||||
&hex!("0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87")
|
||||
,
|
||||
)
|
||||
let ip: AddrV2 = deserialize(&hex!(
|
||||
"0520a2894dabaec08c0051a481a6dac88b64f98232ae42d4b6fd2fa81952dfe36a87"
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
ip,
|
||||
|
@ -522,23 +513,17 @@ mod test {
|
|||
assert!(deserialize::<AddrV2>(&hex!("050300")).is_err());
|
||||
|
||||
// Valid CJDNS.
|
||||
let ip: AddrV2 =
|
||||
deserialize(&hex!("0610fc000001000200030004000500060007")).unwrap();
|
||||
let ip: AddrV2 = deserialize(&hex!("0610fc000001000200030004000500060007")).unwrap();
|
||||
assert_eq!(ip, AddrV2::Cjdns(Ipv6Addr::from_str("fc00:1:2:3:4:5:6:7").unwrap()));
|
||||
|
||||
// Invalid CJDNS, incorrect marker
|
||||
assert!(deserialize::<AddrV2>(
|
||||
&hex!("0610fd000001000200030004000500060007")
|
||||
)
|
||||
.is_err());
|
||||
assert!(deserialize::<AddrV2>(&hex!("0610fd000001000200030004000500060007")).is_err());
|
||||
|
||||
// Invalid CJDNS, with bogus length.
|
||||
assert!(deserialize::<AddrV2>(&hex!("060100")).is_err());
|
||||
|
||||
// Unknown, with extreme length.
|
||||
assert!(
|
||||
deserialize::<AddrV2>(&hex!("aafe0000000201020304050607")).is_err()
|
||||
);
|
||||
assert!(deserialize::<AddrV2>(&hex!("aafe0000000201020304050607")).is_err());
|
||||
|
||||
// Unknown, with reasonable length.
|
||||
let ip: AddrV2 = deserialize(&hex!("aa0401020304")).unwrap();
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
use core::borrow::{Borrow, BorrowMut};
|
||||
use core::convert::TryFrom;
|
||||
use core::fmt::Display;
|
||||
use core::str::FromStr;
|
||||
use core::{fmt, ops};
|
||||
use core::fmt::Display;
|
||||
|
||||
use bitcoin_internals::{debug_from_display, write_err};
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -155,9 +155,7 @@ impl Network {
|
|||
/// let network = Network::Bitcoin;
|
||||
/// assert_eq!(network.chain_hash(), ChainHash::BITCOIN);
|
||||
/// ```
|
||||
pub fn chain_hash(self) -> ChainHash {
|
||||
ChainHash::using_genesis_block(self)
|
||||
}
|
||||
pub fn chain_hash(self) -> ChainHash { ChainHash::using_genesis_block(self) }
|
||||
|
||||
/// Creates a `Network` from the chain hash (genesis block hash).
|
||||
///
|
||||
|
@ -170,7 +168,9 @@ impl Network {
|
|||
///
|
||||
/// assert_eq!(Ok(Network::Bitcoin), Network::try_from(ChainHash::BITCOIN));
|
||||
/// ```
|
||||
pub fn from_chain_hash(chain_hash: ChainHash) -> Option<Network> { Network::try_from(chain_hash).ok() }
|
||||
pub fn from_chain_hash(chain_hash: ChainHash) -> Option<Network> {
|
||||
Network::try_from(chain_hash).ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// An error in parsing network string.
|
||||
|
|
|
@ -540,10 +540,8 @@ mod test {
|
|||
let tx: Transaction = deserialize(&hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000")).unwrap();
|
||||
let block: Block = deserialize(&include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap();
|
||||
let header: block::Header = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b")).unwrap();
|
||||
let script: ScriptBuf = deserialize(
|
||||
&hex!("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac"),
|
||||
)
|
||||
.unwrap();
|
||||
let script: ScriptBuf =
|
||||
deserialize(&hex!("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac")).unwrap();
|
||||
let merkle_block: MerkleBlock = deserialize(&hex!("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101")).unwrap();
|
||||
let cmptblock = deserialize(&hex!("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000")).unwrap();
|
||||
let blocktxn = deserialize(&hex!("2e93c0cff39ff605020072d96bc3a8d20b8447e294d08092351c8583e08d9b5a01020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402dc0000ffffffff0200f90295000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000")).unwrap();
|
||||
|
@ -582,7 +580,9 @@ mod test {
|
|||
flags: BloomFlags::All,
|
||||
}),
|
||||
NetworkMessage::FilterAdd(FilterAdd { data: script.as_bytes().to_vec() }),
|
||||
NetworkMessage::FilterAdd(FilterAdd { data: hash([29u8; 32]).as_byte_array().to_vec() }),
|
||||
NetworkMessage::FilterAdd(FilterAdd {
|
||||
data: hash([29u8; 32]).as_byte_array().to_vec(),
|
||||
}),
|
||||
NetworkMessage::FilterClear,
|
||||
NetworkMessage::GetCFilters(GetCFilters {
|
||||
filter_type: 2,
|
||||
|
|
|
@ -135,8 +135,7 @@ mod tests {
|
|||
#[test]
|
||||
fn getblocks_message_test() {
|
||||
let from_sat = hex!("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000");
|
||||
let genhash =
|
||||
hex!("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
let genhash = hex!("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
|
||||
let decode: Result<GetBlocksMessage, _> = deserialize(&from_sat);
|
||||
assert!(decode.is_ok());
|
||||
|
@ -152,8 +151,7 @@ mod tests {
|
|||
#[test]
|
||||
fn getheaders_message_test() {
|
||||
let from_sat = hex!("72110100014a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b0000000000000000000000000000000000000000000000000000000000000000");
|
||||
let genhash =
|
||||
hex!("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
let genhash = hex!("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
|
||||
let decode: Result<GetHeadersMessage, _> = deserialize(&from_sat);
|
||||
assert!(decode.is_ok());
|
||||
|
|
|
@ -183,7 +183,8 @@ mod tests {
|
|||
assert_eq!(RejectReason::Duplicate, conflict.ccode);
|
||||
assert_eq!("txn-mempool-conflict", conflict.reason);
|
||||
assert_eq!(
|
||||
"0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05".parse::<sha256d::Hash>()
|
||||
"0470f4f2dc4191221b59884bcffaaf00932748ab46356a80413c0b86d354df05"
|
||||
.parse::<sha256d::Hash>()
|
||||
.unwrap(),
|
||||
conflict.hash
|
||||
);
|
||||
|
@ -193,7 +194,8 @@ mod tests {
|
|||
assert_eq!(RejectReason::NonStandard, nonfinal.ccode);
|
||||
assert_eq!("non-final", nonfinal.reason);
|
||||
assert_eq!(
|
||||
"0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25".parse::<sha256d::Hash>()
|
||||
"0b46a539138b5fde4e341b37f2d945c23d41193b30caa7fcbd8bdb836cbe9b25"
|
||||
.parse::<sha256d::Hash>()
|
||||
.unwrap(),
|
||||
nonfinal.hash
|
||||
);
|
||||
|
|
|
@ -402,15 +402,16 @@ impl U256 {
|
|||
// mutagen false positive: binop_bit, replace `|` with `^`
|
||||
fn mul_u64(self, rhs: u64) -> (U256, bool) {
|
||||
let mut carry: u128 = 0;
|
||||
let mut split_le = [self.1 as u64, (self.1 >> 64) as u64, self.0 as u64, (self.0 >> 64) as u64];
|
||||
let mut split_le =
|
||||
[self.1 as u64, (self.1 >> 64) as u64, self.0 as u64, (self.0 >> 64) as u64];
|
||||
|
||||
for word in &mut split_le {
|
||||
// TODO: Use `carrying_mul` when stabilized: https://github.com/rust-lang/rust/issues/85532
|
||||
// This will not overflow, for proof see https://github.com/rust-bitcoin/rust-bitcoin/pull/1496#issuecomment-1365938572
|
||||
let n = carry + u128::from(rhs) * u128::from(*word);
|
||||
|
||||
*word = n as u64; // Intentional truncation, save the low bits
|
||||
carry = n >> 64; // and carry the high bits.
|
||||
*word = n as u64; // Intentional truncation, save the low bits
|
||||
carry = n >> 64; // and carry the high bits.
|
||||
}
|
||||
|
||||
let low = u128::from(split_le[0]) | u128::from(split_le[1]) << 64;
|
||||
|
@ -1336,7 +1337,10 @@ mod tests {
|
|||
|
||||
let (got, overflow) = x.overflowing_mul(y);
|
||||
|
||||
let want = U256(0x0000_0000_0000_0008_0000_0000_0000_0008, 0x0000_0000_0000_0006_0000_0000_0000_0004);
|
||||
let want = U256(
|
||||
0x0000_0000_0000_0008_0000_0000_0000_0008,
|
||||
0x0000_0000_0000_0006_0000_0000_0000_0004,
|
||||
);
|
||||
assert!(!overflow);
|
||||
assert_eq!(got, want)
|
||||
}
|
||||
|
@ -1489,9 +1493,12 @@ mod tests {
|
|||
#[test]
|
||||
fn target_is_met_by_for_target_equals_hash() {
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::hashes::Hash;
|
||||
|
||||
let hash = BlockHash::from_str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c").expect("failed to parse block hash");
|
||||
let hash =
|
||||
BlockHash::from_str("ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c")
|
||||
.expect("failed to parse block hash");
|
||||
let target = Target(U256::from_le_bytes(hash.to_byte_array()));
|
||||
assert!(target.is_met_by(hash));
|
||||
}
|
||||
|
@ -1598,9 +1605,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn u256_multiplication_by_max_panics() {
|
||||
let _ = U256::MAX * U256::MAX;
|
||||
}
|
||||
fn u256_multiplication_by_max_panics() { let _ = U256::MAX * U256::MAX; }
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
|
|
|
@ -18,7 +18,6 @@ impl<'a> serde::Serialize for SerializeBytesAsHex<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub mod btreemap_byte_values {
|
||||
//! Module for serialization of BTreeMaps with hex byte values.
|
||||
#![allow(missing_docs)]
|
||||
|
@ -310,7 +309,7 @@ pub mod hex_bytes {
|
|||
|
||||
macro_rules! serde_string_serialize_impl {
|
||||
($name:ty, $expecting:literal) => {
|
||||
impl $crate::serde::Serialize for $name {
|
||||
impl $crate::serde::Serialize for $name {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: $crate::serde::Serializer,
|
||||
|
@ -342,7 +341,7 @@ macro_rules! serde_string_deserialize_impl {
|
|||
where
|
||||
E: $crate::serde::de::Error,
|
||||
{
|
||||
v.parse::<$name>().map_err(E::custom)
|
||||
v.parse::<$name>().map_err(E::custom)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,13 +353,11 @@ macro_rules! serde_string_deserialize_impl {
|
|||
|
||||
macro_rules! serde_string_impl {
|
||||
($name:ty, $expecting:literal) => {
|
||||
$crate::serde_utils::serde_string_deserialize_impl!($name, $expecting);
|
||||
$crate::serde_utils::serde_string_serialize_impl!($name, $expecting);
|
||||
$crate::serde_utils::serde_string_deserialize_impl!($name, $expecting);
|
||||
$crate::serde_utils::serde_string_serialize_impl!($name, $expecting);
|
||||
};
|
||||
}
|
||||
pub(crate) use serde_string_impl;
|
||||
pub(crate) use serde_string_serialize_impl;
|
||||
pub(crate) use serde_string_deserialize_impl;
|
||||
pub(crate) use {serde_string_deserialize_impl, serde_string_impl, serde_string_serialize_impl};
|
||||
|
||||
/// A combination macro where the human-readable serialization is done like
|
||||
/// serde_string_impl and the non-human-readable impl is done as a struct.
|
||||
|
|
|
@ -47,14 +47,14 @@ impl<E> From<E> for FromHexError<E> {
|
|||
fn from(e: E) -> Self { FromHexError::ParseHex(e) }
|
||||
}
|
||||
|
||||
impl<E: fmt::Display> fmt::Display for FromHexError<E>
|
||||
{
|
||||
impl<E: fmt::Display> fmt::Display for FromHexError<E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::FromHexError::*;
|
||||
|
||||
match *self {
|
||||
ParseHex(ref e) => write_err!(f, "failed to parse hex string"; e),
|
||||
MissingPrefix(ref value) => write_err!(f, "the input value `{}` is missing the `0x` prefix", value; self),
|
||||
MissingPrefix(ref value) =>
|
||||
write_err!(f, "the input value `{}` is missing the `0x` prefix", value; self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,14 +14,13 @@ use bitcoin_internals::write_err;
|
|||
use secp256k1::{self, Scalar, Secp256k1};
|
||||
|
||||
use crate::consensus::Encodable;
|
||||
use crate::hashes::{sha256t_hash_newtype, Hash, HashEngine};
|
||||
use crate::crypto::key::{TapTweak, TweakedPublicKey, UntweakedPublicKey, XOnlyPublicKey};
|
||||
// Re-export these so downstream only has to use one `taproot` module.
|
||||
pub use crate::crypto::taproot::{Error, Signature};
|
||||
use crate::hashes::{sha256t_hash_newtype, Hash, HashEngine};
|
||||
use crate::prelude::*;
|
||||
use crate::{io, Script, ScriptBuf};
|
||||
|
||||
// Re-export these so downstream only has to use one `taproot` module.
|
||||
pub use crate::crypto::taproot::{Signature, Error};
|
||||
|
||||
/// The SHA-256 midstate value for the TapLeaf hash.
|
||||
const MIDSTATE_TAPLEAF: [u8; 32] = [
|
||||
156, 224, 228, 230, 124, 17, 108, 57, 56, 179, 202, 242, 195, 15, 80, 137, 211, 243, 147, 108,
|
||||
|
@ -128,9 +127,7 @@ impl TapNodeHash {
|
|||
/// Similar to [`TapLeafHash::from_byte_array`], but explicitly conveys that the
|
||||
/// hash is constructed from a hidden node. This also has better ergonomics
|
||||
/// because it does not require the caller to import the Hash trait.
|
||||
pub fn assume_hidden(hash: [u8; 32]) -> TapNodeHash {
|
||||
TapNodeHash::from_byte_array(hash)
|
||||
}
|
||||
pub fn assume_hidden(hash: [u8; 32]) -> TapNodeHash { TapNodeHash::from_byte_array(hash) }
|
||||
|
||||
/// Computes the [`TapNodeHash`] from a script and a leaf version.
|
||||
pub fn from_script(script: &Script, ver: LeafVersion) -> TapNodeHash {
|
||||
|
@ -291,12 +288,12 @@ impl TaprootSpendInfo {
|
|||
let mut set = BTreeSet::new();
|
||||
set.insert(value);
|
||||
info.script_map.insert(key, set);
|
||||
},
|
||||
}
|
||||
Some(set) => {
|
||||
set.insert(value);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
info
|
||||
|
@ -385,9 +382,7 @@ impl TaprootBuilder {
|
|||
///
|
||||
/// The size here should be maximum depth of the tree.
|
||||
pub fn with_capacity(size: usize) -> Self {
|
||||
TaprootBuilder {
|
||||
branch: Vec::with_capacity(size),
|
||||
}
|
||||
TaprootBuilder { branch: Vec::with_capacity(size) }
|
||||
}
|
||||
|
||||
/// Creates a new [`TaprootSpendInfo`] from a list of scripts (with default script version) and
|
||||
|
@ -486,9 +481,11 @@ impl TaprootBuilder {
|
|||
if self.branch().len() != 1 {
|
||||
return Err(IncompleteBuilder::NotFinalized(self));
|
||||
}
|
||||
Ok(self.branch.pop()
|
||||
.expect("length checked above")
|
||||
.expect("invariant guarantees node info exists"))
|
||||
Ok(self
|
||||
.branch
|
||||
.pop()
|
||||
.expect("length checked above")
|
||||
.expect("invariant guarantees node info exists"))
|
||||
}
|
||||
|
||||
/// Converts the builder into a [`TapTree`] if the builder is a full tree and
|
||||
|
@ -497,7 +494,9 @@ impl TaprootBuilder {
|
|||
let node = self.try_into_node_info()?;
|
||||
if node.has_hidden_nodes {
|
||||
// Reconstruct the builder as it was if it has hidden nodes
|
||||
return Err(IncompleteBuilder::HiddenParts(TaprootBuilder { branch: vec![Some(node)] }));
|
||||
return Err(IncompleteBuilder::HiddenParts(TaprootBuilder {
|
||||
branch: vec![Some(node)],
|
||||
}));
|
||||
}
|
||||
Ok(TapTree(node))
|
||||
}
|
||||
|
@ -684,20 +683,14 @@ impl From<TapTree> for NodeInfo {
|
|||
|
||||
impl TapTree {
|
||||
/// Gets the reference to inner [`NodeInfo`] of this tree root.
|
||||
pub fn node_info(&self) -> &NodeInfo {
|
||||
&self.0
|
||||
}
|
||||
pub fn node_info(&self) -> &NodeInfo { &self.0 }
|
||||
|
||||
/// Gets the inner [`NodeInfo`] of this tree root.
|
||||
pub fn into_node_info(self) -> NodeInfo {
|
||||
self.0
|
||||
}
|
||||
pub fn into_node_info(self) -> NodeInfo { self.0 }
|
||||
|
||||
/// Returns [`TapTreeIter<'_>`] iterator for a taproot script tree, operating in DFS order over
|
||||
/// tree [`ScriptLeaf`]s.
|
||||
pub fn script_leaves(&self) -> ScriptLeaves {
|
||||
ScriptLeaves { leaf_iter: self.0.leaf_nodes() }
|
||||
}
|
||||
pub fn script_leaves(&self) -> ScriptLeaves { ScriptLeaves { leaf_iter: self.0.leaf_nodes() } }
|
||||
}
|
||||
|
||||
impl TryFrom<TaprootBuilder> for TapTree {
|
||||
|
@ -709,9 +702,7 @@ impl TryFrom<TaprootBuilder> for TapTree {
|
|||
///
|
||||
/// A [`TapTree`] iff the `builder` is complete, otherwise return [`IncompleteBuilder`]
|
||||
/// error with the content of incomplete `builder` instance.
|
||||
fn try_from(builder: TaprootBuilder) -> Result<Self, Self::Error> {
|
||||
builder.try_into_taptree()
|
||||
}
|
||||
fn try_from(builder: TaprootBuilder) -> Result<Self, Self::Error> { builder.try_into_taptree() }
|
||||
}
|
||||
|
||||
impl TryFrom<NodeInfo> for TapTree {
|
||||
|
@ -744,21 +735,19 @@ impl<'tree> Iterator for ScriptLeaves<'tree> {
|
|||
type Item = ScriptLeaf<'tree>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
ScriptLeaf::from_leaf_node(self.leaf_iter.next()?)
|
||||
}
|
||||
fn next(&mut self) -> Option<Self::Item> { ScriptLeaf::from_leaf_node(self.leaf_iter.next()?) }
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.leaf_iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<'tree> ExactSizeIterator for ScriptLeaves<'tree> { }
|
||||
impl<'tree> ExactSizeIterator for ScriptLeaves<'tree> {}
|
||||
|
||||
impl <'tree> FusedIterator for ScriptLeaves<'tree> { }
|
||||
impl<'tree> FusedIterator for ScriptLeaves<'tree> {}
|
||||
|
||||
impl <'tree> DoubleEndedIterator for ScriptLeaves<'tree> {
|
||||
impl<'tree> DoubleEndedIterator for ScriptLeaves<'tree> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
ScriptLeaf::from_leaf_node(self.leaf_iter.next_back()?)
|
||||
ScriptLeaf::from_leaf_node(self.leaf_iter.next_back()?)
|
||||
}
|
||||
}
|
||||
/// Iterator for a taproot script tree, operating in DFS order yielding [`LeafNode`].
|
||||
|
@ -777,11 +766,11 @@ impl<'a> Iterator for LeafNodes<'a> {
|
|||
fn size_hint(&self) -> (usize, Option<usize>) { self.leaf_iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<'tree> ExactSizeIterator for LeafNodes<'tree> { }
|
||||
impl<'tree> ExactSizeIterator for LeafNodes<'tree> {}
|
||||
|
||||
impl <'tree> FusedIterator for LeafNodes<'tree> { }
|
||||
impl<'tree> FusedIterator for LeafNodes<'tree> {}
|
||||
|
||||
impl <'tree> DoubleEndedIterator for LeafNodes<'tree> {
|
||||
impl<'tree> DoubleEndedIterator for LeafNodes<'tree> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> { self.leaf_iter.next_back() }
|
||||
}
|
||||
|
@ -850,9 +839,7 @@ impl NodeInfo {
|
|||
}
|
||||
|
||||
/// Creates an iterator over all leaves (including hidden leaves) in the tree.
|
||||
pub fn leaf_nodes(&self) -> LeafNodes {
|
||||
LeafNodes { leaf_iter: self.leaves.iter() }
|
||||
}
|
||||
pub fn leaf_nodes(&self) -> LeafNodes { LeafNodes { leaf_iter: self.leaves.iter() } }
|
||||
}
|
||||
|
||||
impl TryFrom<TaprootBuilder> for NodeInfo {
|
||||
|
@ -899,27 +886,32 @@ impl<'de> serde::Deserialize<'de> for NodeInfo {
|
|||
where
|
||||
A: serde::de::SeqAccess<'de>,
|
||||
{
|
||||
let size = seq.size_hint()
|
||||
.map(|x| core::mem::size_of::<usize>()*8 - x.leading_zeros() as usize)
|
||||
let size = seq
|
||||
.size_hint()
|
||||
.map(|x| core::mem::size_of::<usize>() * 8 - x.leading_zeros() as usize)
|
||||
.map(|x| x / 2) // Each leaf is serialized as two elements.
|
||||
.unwrap_or(0)
|
||||
.min(TAPROOT_CONTROL_MAX_NODE_COUNT); // no more than 128 nodes
|
||||
let mut builder = TaprootBuilder::with_capacity(size);
|
||||
while let Some(depth) = seq.next_element()? {
|
||||
let tap_leaf : TapLeaf = seq
|
||||
let tap_leaf: TapLeaf = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| serde::de::Error::custom("Missing tap_leaf"))?;
|
||||
match tap_leaf {
|
||||
TapLeaf::Script(script, ver) => {
|
||||
builder = builder.add_leaf_with_ver(depth, script, ver).map_err(|e| {
|
||||
serde::de::Error::custom(format!("Leaf insertion error: {}", e))
|
||||
})?;
|
||||
},
|
||||
builder =
|
||||
builder.add_leaf_with_ver(depth, script, ver).map_err(|e| {
|
||||
serde::de::Error::custom(format!("Leaf insertion error: {}", e))
|
||||
})?;
|
||||
}
|
||||
TapLeaf::Hidden(h) => {
|
||||
builder = builder.add_hidden_node(depth, h).map_err(|e| {
|
||||
serde::de::Error::custom(format!("Hidden node insertion error: {}", e))
|
||||
serde::de::Error::custom(format!(
|
||||
"Hidden node insertion error: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
NodeInfo::try_from(builder).map_err(|e| {
|
||||
|
@ -1009,9 +1001,7 @@ impl LeafNode {
|
|||
#[inline]
|
||||
pub fn node_hash(&self) -> TapNodeHash {
|
||||
match self.leaf {
|
||||
TapLeaf::Script(ref script, ver) => {
|
||||
TapLeafHash::from_script(script, ver).into()
|
||||
}
|
||||
TapLeaf::Script(ref script, ver) => TapLeafHash::from_script(script, ver).into(),
|
||||
TapLeaf::Hidden(ref hash) => *hash,
|
||||
}
|
||||
}
|
||||
|
@ -1031,9 +1021,7 @@ impl LeafNode {
|
|||
|
||||
/// Returns a reference to the leaf of this [`ScriptLeaf`].
|
||||
#[inline]
|
||||
pub fn leaf(&self) -> &TapLeaf {
|
||||
&self.leaf
|
||||
}
|
||||
pub fn leaf(&self) -> &TapLeaf { &self.leaf }
|
||||
}
|
||||
|
||||
/// Script leaf node in a taproot tree along with the merkle proof to get this node.
|
||||
|
@ -1049,30 +1037,19 @@ pub struct ScriptLeaf<'leaf> {
|
|||
}
|
||||
|
||||
impl<'leaf> ScriptLeaf<'leaf> {
|
||||
|
||||
/// Obtains the version of the script leaf.
|
||||
pub fn version(&self) -> LeafVersion {
|
||||
self.version
|
||||
}
|
||||
pub fn version(&self) -> LeafVersion { self.version }
|
||||
|
||||
/// Obtains a reference to the script inside the leaf.
|
||||
pub fn script(&self) -> &Script {
|
||||
self.script
|
||||
}
|
||||
pub fn script(&self) -> &Script { self.script }
|
||||
|
||||
/// Obtains a reference to the merkle proof of the leaf.
|
||||
pub fn merkle_branch(&self) -> &TaprootMerkleBranch {
|
||||
self.merkle_branch
|
||||
}
|
||||
pub fn merkle_branch(&self) -> &TaprootMerkleBranch { self.merkle_branch }
|
||||
|
||||
/// Obtains a script leaf from the leaf node if the leaf is not hidden.
|
||||
pub fn from_leaf_node(leaf_node: &'leaf LeafNode) -> Option<Self> {
|
||||
let (script, ver) = leaf_node.leaf.as_script()?;
|
||||
Some(Self {
|
||||
version: ver,
|
||||
script,
|
||||
merkle_branch: &leaf_node.merkle_branch,
|
||||
})
|
||||
Some(Self { version: ver, script, merkle_branch: &leaf_node.merkle_branch })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1096,9 +1073,7 @@ impl TaprootMerkleBranch {
|
|||
|
||||
/// Decodes bytes from control block.
|
||||
#[deprecated(since = "0.30.0", note = "Use decode instead")]
|
||||
pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> {
|
||||
Self::decode(sl)
|
||||
}
|
||||
pub fn from_slice(sl: &[u8]) -> Result<Self, TaprootError> { Self::decode(sl) }
|
||||
|
||||
/// Decodes bytes from control block.
|
||||
///
|
||||
|
@ -1206,7 +1181,14 @@ macro_rules! impl_try_from_array {
|
|||
//
|
||||
// The reason zero is included is that `TaprootMerkleBranch` doesn't contain the hash of the node
|
||||
// that's being proven - it's not needed because the script is already right before control block.
|
||||
impl_try_from_array!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128);
|
||||
impl_try_from_array!(
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
|
||||
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
|
||||
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
|
||||
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
|
||||
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128
|
||||
);
|
||||
|
||||
impl From<TaprootMerkleBranch> for Vec<TapNodeHash> {
|
||||
fn from(branch: TaprootMerkleBranch) -> Self { branch.0 }
|
||||
|
@ -1230,9 +1212,7 @@ pub struct ControlBlock {
|
|||
impl ControlBlock {
|
||||
/// Constructs a `ControlBlock` from slice.
|
||||
#[deprecated(since = "0.30.0", note = "Use decode instead")]
|
||||
pub fn from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> {
|
||||
Self::decode(sl)
|
||||
}
|
||||
pub fn from_slice(sl: &[u8]) -> Result<ControlBlock, TaprootError> { Self::decode(sl) }
|
||||
|
||||
/// Decodes bytes representing a `ControlBlock`.
|
||||
///
|
||||
|
@ -1998,7 +1978,9 @@ mod test {
|
|||
let expected_spk =
|
||||
ScriptBuf::from_hex(arr["expected"]["scriptPubKey"].as_str().unwrap()).unwrap();
|
||||
let expected_addr =
|
||||
Address::from_str(arr["expected"]["bip350Address"].as_str().unwrap()).unwrap().assume_checked();
|
||||
Address::from_str(arr["expected"]["bip350Address"].as_str().unwrap())
|
||||
.unwrap()
|
||||
.assume_checked();
|
||||
|
||||
let tweak = TapTweakHash::from_key_and_tweak(internal_key, merkle_root);
|
||||
let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//! Tests PSBT integration vectors from BIP 174
|
||||
//! defined at <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#test-vectors>
|
||||
|
||||
use core::convert::TryFrom;
|
||||
use std::collections::BTreeMap;
|
||||
use std::str::FromStr;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
use bitcoin::bip32::{ExtendedPrivKey, ExtendedPubKey, Fingerprint, IntoDerivationPath, KeySource};
|
||||
use bitcoin::blockdata::opcodes::OP_0;
|
||||
|
@ -11,12 +11,12 @@ use bitcoin::blockdata::script;
|
|||
use bitcoin::consensus::encode::{deserialize, serialize_hex};
|
||||
use bitcoin::hashes::hex::FromHex;
|
||||
use bitcoin::psbt::{Psbt, PsbtSighashType};
|
||||
use bitcoin::script::PushBytes;
|
||||
use bitcoin::secp256k1::{self, Secp256k1};
|
||||
use bitcoin::{
|
||||
absolute, Amount, Denomination, Network, OutPoint, PrivateKey, PublicKey, ScriptBuf, Sequence,
|
||||
Transaction, TxIn, TxOut, Witness,
|
||||
};
|
||||
use bitcoin::script::PushBytes;
|
||||
|
||||
const NETWORK: Network = Network::Testnet;
|
||||
|
||||
|
@ -426,7 +426,10 @@ fn finalize_psbt(mut psbt: Psbt) -> Psbt {
|
|||
.push_opcode(OP_0) // OP_CHECKMULTISIG bug pops +1 value when evaluating so push OP_0.
|
||||
.push_slice(sigs[0].serialize())
|
||||
.push_slice(sigs[1].serialize())
|
||||
.push_slice(<&PushBytes>::try_from(psbt.inputs[0].redeem_script.as_ref().unwrap().as_bytes()).unwrap())
|
||||
.push_slice(
|
||||
<&PushBytes>::try_from(psbt.inputs[0].redeem_script.as_ref().unwrap().as_bytes())
|
||||
.unwrap(),
|
||||
)
|
||||
.into_script();
|
||||
|
||||
psbt.inputs[0].final_script_sig = Some(script_sig);
|
||||
|
@ -439,7 +442,10 @@ fn finalize_psbt(mut psbt: Psbt) -> Psbt {
|
|||
// Input 1: SegWit UTXO
|
||||
|
||||
let script_sig = script::Builder::new()
|
||||
.push_slice(<&PushBytes>::try_from(psbt.inputs[1].redeem_script.as_ref().unwrap().as_bytes()).unwrap())
|
||||
.push_slice(
|
||||
<&PushBytes>::try_from(psbt.inputs[1].redeem_script.as_ref().unwrap().as_bytes())
|
||||
.unwrap(),
|
||||
)
|
||||
.into_script();
|
||||
|
||||
psbt.inputs[1].final_script_sig = Some(script_sig);
|
||||
|
|
|
@ -36,7 +36,7 @@ use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
|
|||
use bitcoin::psbt::raw::{self, Key, Pair, ProprietaryKey};
|
||||
use bitcoin::psbt::{Input, Output, Psbt, PsbtSighashType};
|
||||
use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
|
||||
use bitcoin::taproot::{self, ControlBlock, LeafVersion, TaprootBuilder, TapTree};
|
||||
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,
|
||||
|
@ -225,10 +225,13 @@ fn serde_regression_psbt() {
|
|||
lock_time: absolute::LockTime::ZERO,
|
||||
input: vec![TxIn {
|
||||
previous_output: OutPoint {
|
||||
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse::<Txid>().unwrap(),
|
||||
txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389"
|
||||
.parse::<Txid>()
|
||||
.unwrap(),
|
||||
vout: 1,
|
||||
},
|
||||
script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
|
||||
script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985")
|
||||
.unwrap(),
|
||||
sequence: Sequence::from_consensus(4294967295),
|
||||
witness: Witness::from_slice(&[Vec::from_hex(
|
||||
"03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105",
|
||||
|
|
|
@ -47,3 +47,6 @@ git diff-index --check --cached $against -- || exit 1
|
|||
|
||||
# Check that code lints cleanly.
|
||||
cargo clippy --all-features -- -D warnings || exit 1
|
||||
|
||||
# Check that there are no formatting issues.
|
||||
cargo +nightly fmt --check || exit 1
|
||||
|
|
|
@ -89,6 +89,16 @@ if [ "$DO_ASAN" = true ]; then
|
|||
cargo test --lib --no-default-features --features="$FEATURES" -Zbuild-std --target x86_64-unknown-linux-gnu
|
||||
fi
|
||||
|
||||
# Run formatter if told to.
|
||||
if [ "$DO_FMT" = true ]; then
|
||||
if [ "$NIGHTLY" = false ]; then
|
||||
echo "DO_FMT requires a nightly toolchain (consider using RUSTUP_TOOLCHAIN)"
|
||||
exit 1
|
||||
fi
|
||||
rustup component add rustfmt
|
||||
cargo fmt --check
|
||||
fi
|
||||
|
||||
# Bench if told to, only works with non-stable toolchain (nightly, beta).
|
||||
if [ "$DO_BENCH" = true ]
|
||||
then
|
||||
|
|
|
@ -52,3 +52,13 @@ fi
|
|||
if [ "$DO_DOCS" = true ]; then
|
||||
RUSTDOCFLAGS="-D warnings" cargo +stable doc --all-features
|
||||
fi
|
||||
|
||||
# Run formatter if told to.
|
||||
if [ "$DO_FMT" = true ]; then
|
||||
if [ "$NIGHTLY" = false ]; then
|
||||
echo "DO_FMT requires a nightly toolchain (consider using RUSTUP_TOOLCHAIN)"
|
||||
exit 1
|
||||
fi
|
||||
rustup component add rustfmt
|
||||
cargo fmt --check
|
||||
fi
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
//! faster than the usual `write!(f, "{02x}", b)?` in a for loop because it reduces dynamic
|
||||
//! dispatch and decreases the number of allocations if a `String` is being created.
|
||||
|
||||
use core::borrow::Borrow;
|
||||
|
||||
pub use out_bytes::OutBytes;
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use super::Case;
|
||||
|
||||
/// Trait for types that can be soundly converted to `OutBytes`.
|
||||
|
@ -205,13 +206,21 @@ impl<T: AsOutBytes> BufEncoder<T> {
|
|||
/// The method panics if the bytes wouldn't fit the buffer.
|
||||
#[inline]
|
||||
#[cfg_attr(rust_v_1_46, track_caller)]
|
||||
pub fn put_bytes<I>(&mut self, bytes: I, case: Case) where I: IntoIterator, I::Item: Borrow<u8> {
|
||||
pub fn put_bytes<I>(&mut self, bytes: I, case: Case)
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<u8>,
|
||||
{
|
||||
self.put_bytes_inner(bytes.into_iter(), case)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(rust_v_1_46, track_caller)]
|
||||
fn put_bytes_inner<I>(&mut self, bytes: I, case: Case) where I: Iterator, I::Item: Borrow<u8> {
|
||||
fn put_bytes_inner<I>(&mut self, bytes: I, case: Case)
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Borrow<u8>,
|
||||
{
|
||||
// May give the compiler better optimization opportunity
|
||||
if let Some(max) = bytes.size_hint().1 {
|
||||
assert!(max <= self.space_remaining());
|
||||
|
|
|
@ -8,9 +8,9 @@ use core::fmt;
|
|||
|
||||
use super::buf_encoder::{BufEncoder, OutBytes};
|
||||
use super::Case;
|
||||
use crate::hex::buf_encoder::FixedLenBuf;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::prelude::*;
|
||||
use crate::hex::buf_encoder::FixedLenBuf;
|
||||
|
||||
/// Extension trait for types that can be displayed as hex.
|
||||
///
|
||||
|
@ -153,34 +153,30 @@ impl<'a> DisplayByteSlice<'a> {
|
|||
}
|
||||
|
||||
impl<'a> fmt::LowerHex for DisplayByteSlice<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.display(f, Case::Lower)
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Lower) }
|
||||
}
|
||||
|
||||
impl<'a> fmt::UpperHex for DisplayByteSlice<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.display(f, Case::Upper)
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Upper) }
|
||||
}
|
||||
|
||||
/// Displays byte array as hex.
|
||||
///
|
||||
/// Created by [`<&[u8; LEN] as DisplayHex>::as_hex`](DisplayHex::as_hex).
|
||||
pub struct DisplayArray<A: Clone + IntoIterator, B: FixedLenBuf> where A::Item: Borrow<u8> {
|
||||
pub struct DisplayArray<A: Clone + IntoIterator, B: FixedLenBuf>
|
||||
where
|
||||
A::Item: Borrow<u8>,
|
||||
{
|
||||
array: A,
|
||||
_buffer_marker: core::marker::PhantomData<B>,
|
||||
}
|
||||
|
||||
|
||||
impl<A: Clone + IntoIterator, B: FixedLenBuf> DisplayArray<A, B> where A::Item: Borrow<u8> {
|
||||
impl<A: Clone + IntoIterator, B: FixedLenBuf> DisplayArray<A, B>
|
||||
where
|
||||
A::Item: Borrow<u8>,
|
||||
{
|
||||
/// Creates the wrapper.
|
||||
pub fn new(array: A) -> Self {
|
||||
DisplayArray {
|
||||
array,
|
||||
_buffer_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
pub fn new(array: A) -> Self { DisplayArray { array, _buffer_marker: Default::default() } }
|
||||
|
||||
fn display(&self, f: &mut fmt::Formatter, case: Case) -> fmt::Result {
|
||||
let mut buf = B::uninit();
|
||||
|
@ -190,16 +186,18 @@ impl<A: Clone + IntoIterator, B: FixedLenBuf> DisplayArray<A, B> where A::Item:
|
|||
}
|
||||
}
|
||||
|
||||
impl<A: Clone + IntoIterator, B: FixedLenBuf> fmt::LowerHex for DisplayArray<A, B> where A::Item: Borrow<u8> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.display(f, Case::Lower)
|
||||
}
|
||||
impl<A: Clone + IntoIterator, B: FixedLenBuf> fmt::LowerHex for DisplayArray<A, B>
|
||||
where
|
||||
A::Item: Borrow<u8>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Lower) }
|
||||
}
|
||||
|
||||
impl<A: Clone + IntoIterator, B: FixedLenBuf> fmt::UpperHex for DisplayArray<A, B> where A::Item: Borrow<u8> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.display(f, Case::Upper)
|
||||
}
|
||||
impl<A: Clone + IntoIterator, B: FixedLenBuf> fmt::UpperHex for DisplayArray<A, B>
|
||||
where
|
||||
A::Item: Borrow<u8>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.display(f, Case::Upper) }
|
||||
}
|
||||
|
||||
/// Format known-length array as hex.
|
||||
|
@ -243,7 +241,9 @@ pub fn fmt_hex_exact_fn<I>(
|
|||
bytes: I,
|
||||
case: Case,
|
||||
) -> fmt::Result
|
||||
where I: IntoIterator, I::Item: Borrow<u8>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<u8>,
|
||||
{
|
||||
let mut encoder = BufEncoder::new(buf);
|
||||
encoder.put_bytes(bytes, case);
|
||||
|
|
|
@ -30,15 +30,11 @@ macro_rules! impl_array_newtype {
|
|||
}
|
||||
|
||||
impl<'a> core::convert::From<[$ty; $len]> for $thing {
|
||||
fn from(data: [$ty; $len]) -> Self {
|
||||
$thing(data)
|
||||
}
|
||||
fn from(data: [$ty; $len]) -> Self { $thing(data) }
|
||||
}
|
||||
|
||||
impl<'a> core::convert::From<&'a [$ty; $len]> for $thing {
|
||||
fn from(data: &'a [$ty; $len]) -> Self {
|
||||
$thing(*data)
|
||||
}
|
||||
fn from(data: &'a [$ty; $len]) -> Self { $thing(*data) }
|
||||
}
|
||||
|
||||
impl<'a> core::convert::TryFrom<&'a [$ty]> for $thing {
|
||||
|
@ -52,52 +48,36 @@ macro_rules! impl_array_newtype {
|
|||
}
|
||||
|
||||
impl AsRef<[$ty; $len]> for $thing {
|
||||
fn as_ref(&self) -> &[$ty; $len] {
|
||||
&self.0
|
||||
}
|
||||
fn as_ref(&self) -> &[$ty; $len] { &self.0 }
|
||||
}
|
||||
|
||||
impl AsMut<[$ty; $len]> for $thing {
|
||||
fn as_mut(&mut self) -> &mut [$ty; $len] {
|
||||
&mut self.0
|
||||
}
|
||||
fn as_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
|
||||
}
|
||||
|
||||
impl AsRef<[$ty]> for $thing {
|
||||
fn as_ref(&self) -> &[$ty] {
|
||||
&self.0
|
||||
}
|
||||
fn as_ref(&self) -> &[$ty] { &self.0 }
|
||||
}
|
||||
|
||||
impl AsMut<[$ty]> for $thing {
|
||||
fn as_mut(&mut self) -> &mut [$ty] {
|
||||
&mut self.0
|
||||
}
|
||||
fn as_mut(&mut self) -> &mut [$ty] { &mut self.0 }
|
||||
}
|
||||
|
||||
impl core::borrow::Borrow<[$ty; $len]> for $thing {
|
||||
fn borrow(&self) -> &[$ty; $len] {
|
||||
&self.0
|
||||
}
|
||||
fn borrow(&self) -> &[$ty; $len] { &self.0 }
|
||||
}
|
||||
|
||||
impl core::borrow::BorrowMut<[$ty; $len]> for $thing {
|
||||
fn borrow_mut(&mut self) -> &mut [$ty; $len] {
|
||||
&mut self.0
|
||||
}
|
||||
fn borrow_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
|
||||
}
|
||||
|
||||
// The following two are valid because `[T; N]: Borrow<[T]>`
|
||||
impl core::borrow::Borrow<[$ty]> for $thing {
|
||||
fn borrow(&self) -> &[$ty] {
|
||||
&self.0
|
||||
}
|
||||
fn borrow(&self) -> &[$ty] { &self.0 }
|
||||
}
|
||||
|
||||
impl core::borrow::BorrowMut<[$ty]> for $thing {
|
||||
fn borrow_mut(&mut self) -> &mut [$ty] {
|
||||
&mut self.0
|
||||
}
|
||||
fn borrow_mut(&mut self) -> &mut [$ty] { &mut self.0 }
|
||||
}
|
||||
|
||||
impl<I> core::ops::Index<I> for $thing
|
||||
|
|
|
@ -58,7 +58,7 @@ enum_discrim_align_threshold = 0
|
|||
match_arm_blocks = false # Default true
|
||||
match_arm_leading_pipes = "Never"
|
||||
force_multiline_blocks = false
|
||||
fn_args_layout = "Tall"
|
||||
fn_params_layout = "Tall"
|
||||
brace_style = "SameLineWhere"
|
||||
control_brace_style = "AlwaysSameLine"
|
||||
trailing_semicolon = true
|
||||
|
|
Loading…
Reference in New Issue