Merge pull request #308 from elichai/2019-08-clippy
Cargo clippy changes
This commit is contained in:
commit
8d859cf54c
|
@ -78,7 +78,7 @@ impl Block {
|
||||||
if self.txdata.iter().all(|t| t.input.iter().all(|i| i.witness.is_empty())) {
|
if self.txdata.iter().all(|t| t.input.iter().all(|i| i.witness.is_empty())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if self.txdata.len() > 0 {
|
if !self.txdata.is_empty() {
|
||||||
let coinbase = &self.txdata[0];
|
let coinbase = &self.txdata[0];
|
||||||
if coinbase.is_coin_base() {
|
if coinbase.is_coin_base() {
|
||||||
// commitment is in the last output that starts with below magic
|
// commitment is in the last output that starts with below magic
|
||||||
|
|
|
@ -658,29 +658,29 @@ impl fmt::Debug for All {
|
||||||
impl All {
|
impl All {
|
||||||
/// Classifies an Opcode into a broad class
|
/// Classifies an Opcode into a broad class
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn classify(&self) -> Class {
|
pub fn classify(self) -> Class {
|
||||||
// 17 opcodes
|
// 17 opcodes
|
||||||
if *self == all::OP_VERIF || *self == all::OP_VERNOTIF ||
|
if self == all::OP_VERIF || self == all::OP_VERNOTIF ||
|
||||||
*self == all::OP_CAT || *self == all::OP_SUBSTR ||
|
self == all::OP_CAT || self == all::OP_SUBSTR ||
|
||||||
*self == all::OP_LEFT || *self == all::OP_RIGHT ||
|
self == all::OP_LEFT || self == all::OP_RIGHT ||
|
||||||
*self == all::OP_INVERT || *self == all::OP_AND ||
|
self == all::OP_INVERT || self == all::OP_AND ||
|
||||||
*self == all::OP_OR || *self == all::OP_XOR ||
|
self == all::OP_OR || self == all::OP_XOR ||
|
||||||
*self == all::OP_2MUL || *self == all::OP_2DIV ||
|
self == all::OP_2MUL || self == all::OP_2DIV ||
|
||||||
*self == all::OP_MUL || *self == all::OP_DIV || *self == all::OP_MOD ||
|
self == all::OP_MUL || self == all::OP_DIV || self == all::OP_MOD ||
|
||||||
*self == all::OP_LSHIFT || *self == all::OP_RSHIFT {
|
self == all::OP_LSHIFT || self == all::OP_RSHIFT {
|
||||||
Class::IllegalOp
|
Class::IllegalOp
|
||||||
// 11 opcodes
|
// 11 opcodes
|
||||||
} else if *self == all::OP_NOP ||
|
} else if self == all::OP_NOP ||
|
||||||
(all::OP_NOP1.code <= self.code &&
|
(all::OP_NOP1.code <= self.code &&
|
||||||
self.code <= all::OP_NOP10.code) {
|
self.code <= all::OP_NOP10.code) {
|
||||||
Class::NoOp
|
Class::NoOp
|
||||||
// 75 opcodes
|
// 75 opcodes
|
||||||
} else if *self == all::OP_RESERVED || *self == all::OP_VER || *self == all::OP_RETURN ||
|
} else if self == all::OP_RESERVED || self == all::OP_VER || self == all::OP_RETURN ||
|
||||||
*self == all::OP_RESERVED1 || *self == all::OP_RESERVED2 ||
|
self == all::OP_RESERVED1 || self == all::OP_RESERVED2 ||
|
||||||
self.code >= all::OP_RETURN_186.code {
|
self.code >= all::OP_RETURN_186.code {
|
||||||
Class::ReturnOp
|
Class::ReturnOp
|
||||||
// 1 opcode
|
// 1 opcode
|
||||||
} else if *self == all::OP_PUSHNUM_NEG1 {
|
} else if self == all::OP_PUSHNUM_NEG1 {
|
||||||
Class::PushNum(-1)
|
Class::PushNum(-1)
|
||||||
// 16 opcodes
|
// 16 opcodes
|
||||||
} else if all::OP_PUSHNUM_1.code <= self.code &&
|
} else if all::OP_PUSHNUM_1.code <= self.code &&
|
||||||
|
@ -691,13 +691,13 @@ impl All {
|
||||||
Class::PushBytes(self.code as u32)
|
Class::PushBytes(self.code as u32)
|
||||||
// 60 opcodes
|
// 60 opcodes
|
||||||
} else {
|
} else {
|
||||||
Class::Ordinary(Ordinary::try_from_all(*self).unwrap())
|
Class::Ordinary(Ordinary::try_from_all(self).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encode as a byte
|
/// Encode as a byte
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_u8(&self) -> u8 {
|
pub fn into_u8(self) -> u8 {
|
||||||
self.code
|
self.code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,8 +809,8 @@ ordinary_opcode! {
|
||||||
impl Ordinary {
|
impl Ordinary {
|
||||||
/// Encode as a byte
|
/// Encode as a byte
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_u8(&self) -> u8 {
|
pub fn into_u8(self) -> u8 {
|
||||||
*self as u8
|
self as u8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -598,8 +598,8 @@ pub enum SigHashType {
|
||||||
|
|
||||||
impl SigHashType {
|
impl SigHashType {
|
||||||
/// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean
|
/// Break the sighash flag into the "real" sighash flag and the ANYONECANPAY boolean
|
||||||
pub(crate) fn split_anyonecanpay_flag(&self) -> (SigHashType, bool) {
|
pub(crate) fn split_anyonecanpay_flag(self) -> (SigHashType, bool) {
|
||||||
match *self {
|
match self {
|
||||||
SigHashType::All => (SigHashType::All, false),
|
SigHashType::All => (SigHashType::All, false),
|
||||||
SigHashType::None => (SigHashType::None, false),
|
SigHashType::None => (SigHashType::None, false),
|
||||||
SigHashType::Single => (SigHashType::Single, false),
|
SigHashType::Single => (SigHashType::Single, false),
|
||||||
|
@ -626,7 +626,7 @@ impl SigHashType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts to a u32
|
/// Converts to a u32
|
||||||
pub fn as_u32(&self) -> u32 { *self as u32 }
|
pub fn as_u32(self) -> u32 { self as u32 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -162,7 +162,7 @@ pub fn serialize_hex<T: Encodable + ?Sized>(data: &T) -> String {
|
||||||
|
|
||||||
/// Deserialize an object from a vector, will error if said deserialization
|
/// Deserialize an object from a vector, will error if said deserialization
|
||||||
/// doesn't consume the entire vector.
|
/// doesn't consume the entire vector.
|
||||||
pub fn deserialize<'a, T: Decodable>(data: &'a [u8]) -> Result<T, Error> {
|
pub fn deserialize<T: Decodable>(data: &[u8]) -> Result<T, Error> {
|
||||||
let (rv, consumed) = deserialize_partial(data)?;
|
let (rv, consumed) = deserialize_partial(data)?;
|
||||||
|
|
||||||
// Fail if data are not consumed entirely.
|
// Fail if data are not consumed entirely.
|
||||||
|
@ -175,8 +175,8 @@ pub fn deserialize<'a, T: Decodable>(data: &'a [u8]) -> Result<T, Error> {
|
||||||
|
|
||||||
/// Deserialize an object from a vector, but will not report an error if said deserialization
|
/// Deserialize an object from a vector, but will not report an error if said deserialization
|
||||||
/// doesn't consume the entire vector.
|
/// doesn't consume the entire vector.
|
||||||
pub fn deserialize_partial<'a, T: Decodable>(
|
pub fn deserialize_partial<T: Decodable>(
|
||||||
data: &'a [u8],
|
data: &[u8],
|
||||||
) -> Result<(T, usize), Error> {
|
) -> Result<(T, usize), Error> {
|
||||||
let mut decoder = Cursor::new(data);
|
let mut decoder = Cursor::new(data);
|
||||||
let rv = Decodable::consensus_decode(&mut decoder)?;
|
let rv = Decodable::consensus_decode(&mut decoder)?;
|
||||||
|
@ -543,8 +543,8 @@ impl Decodable for [u16; 8] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, Error> {
|
||||||
let mut res = [0; 8];
|
let mut res = [0; 8];
|
||||||
for i in 0..8 {
|
for item in &mut res {
|
||||||
res[i] = Decodable::consensus_decode(&mut d)?;
|
*item = Decodable::consensus_decode(&mut d)?;
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,9 +41,9 @@ const ONION : [u16; 3] = [0xFD87, 0xD87E, 0xEB43];
|
||||||
impl Address {
|
impl Address {
|
||||||
/// Create an address message for a socket
|
/// Create an address message for a socket
|
||||||
pub fn new (socket :&SocketAddr, services: ServiceFlags) -> Address {
|
pub fn new (socket :&SocketAddr, services: ServiceFlags) -> Address {
|
||||||
let (address, port) = match socket {
|
let (address, port) = match *socket {
|
||||||
&SocketAddr::V4(ref addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()),
|
SocketAddr::V4(addr) => (addr.ip().to_ipv6_mapped().segments(), addr.port()),
|
||||||
&SocketAddr::V6(ref addr) => (addr.ip().segments(), addr.port())
|
SocketAddr::V6(addr) => (addr.ip().segments(), addr.port())
|
||||||
};
|
};
|
||||||
Address { address: address, port: port, services: services }
|
Address { address: address, port: port, services: services }
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,9 +89,9 @@ impl Network {
|
||||||
/// let network = Network::Bitcoin;
|
/// let network = Network::Bitcoin;
|
||||||
/// assert_eq!(network.magic(), 0xD9B4BEF9);
|
/// assert_eq!(network.magic(), 0xD9B4BEF9);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn magic(&self) -> u32 {
|
pub fn magic(self) -> u32 {
|
||||||
// Note: any new entries here must be added to `from_magic` above
|
// Note: any new entries here must be added to `from_magic` above
|
||||||
match *self {
|
match self {
|
||||||
Network::Bitcoin => 0xD9B4BEF9,
|
Network::Bitcoin => 0xD9B4BEF9,
|
||||||
Network::Testnet => 0x0709110B,
|
Network::Testnet => 0x0709110B,
|
||||||
Network::Regtest => 0xDAB5BFFA,
|
Network::Regtest => 0xDAB5BFFA,
|
||||||
|
@ -154,12 +154,12 @@ impl ServiceFlags {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether [ServiceFlags] are included in this one.
|
/// Check whether [ServiceFlags] are included in this one.
|
||||||
pub fn has(&self, flags: ServiceFlags) -> bool {
|
pub fn has(self, flags: ServiceFlags) -> bool {
|
||||||
(self.0 | flags.0) == self.0
|
(self.0 | flags.0) == self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the integer representation of this [ServiceFlags].
|
/// Get the integer representation of this [ServiceFlags].
|
||||||
pub fn as_u64(&self) -> u64 {
|
pub fn as_u64(self) -> u64 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,11 +178,10 @@ impl fmt::UpperHex for ServiceFlags {
|
||||||
|
|
||||||
impl fmt::Display for ServiceFlags {
|
impl fmt::Display for ServiceFlags {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if *self == ServiceFlags::NONE {
|
let mut flags = *self;
|
||||||
|
if flags == ServiceFlags::NONE {
|
||||||
return write!(f, "ServiceFlags(NONE)");
|
return write!(f, "ServiceFlags(NONE)");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut flags = self.clone();
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
macro_rules! write_flag {
|
macro_rules! write_flag {
|
||||||
($f:ident) => {
|
($f:ident) => {
|
||||||
|
|
|
@ -72,9 +72,7 @@ impl Encodable for CommandString {
|
||||||
if strbytes.len() > 12 {
|
if strbytes.len() > 12 {
|
||||||
return Err(encode::Error::UnrecognizedNetworkCommand(self.0.clone().into_owned()));
|
return Err(encode::Error::UnrecognizedNetworkCommand(self.0.clone().into_owned()));
|
||||||
}
|
}
|
||||||
for x in 0..strbytes.len() {
|
rawbytes[..strbytes.len()].clone_from_slice(&strbytes[..]);
|
||||||
rawbytes[x] = strbytes[x];
|
|
||||||
}
|
|
||||||
rawbytes.consensus_encode(s)
|
rawbytes.consensus_encode(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ impl GetBlocksMessage {
|
||||||
pub fn new(locator_hashes: Vec<BlockHash>, stop_hash: BlockHash) -> GetBlocksMessage {
|
pub fn new(locator_hashes: Vec<BlockHash>, stop_hash: BlockHash) -> GetBlocksMessage {
|
||||||
GetBlocksMessage {
|
GetBlocksMessage {
|
||||||
version: constants::PROTOCOL_VERSION,
|
version: constants::PROTOCOL_VERSION,
|
||||||
locator_hashes: locator_hashes.clone(),
|
locator_hashes: locator_hashes,
|
||||||
stop_hash: stop_hash
|
stop_hash: stop_hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,16 +18,13 @@
|
||||||
//! # Example: creating a new address from a randomly-generated key pair
|
//! # Example: creating a new address from a randomly-generated key pair
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! extern crate secp256k1;
|
|
||||||
//! extern crate bitcoin;
|
|
||||||
//!
|
//!
|
||||||
//! use bitcoin::network::constants::Network;
|
//! use bitcoin::network::constants::Network;
|
||||||
//! use bitcoin::util::address::Address;
|
//! use bitcoin::util::address::Address;
|
||||||
//! use bitcoin::util::key;
|
//! use bitcoin::util::key;
|
||||||
//! use secp256k1::Secp256k1;
|
//! use bitcoin::secp256k1::Secp256k1;
|
||||||
//! use secp256k1::rand::thread_rng;
|
//! use bitcoin::secp256k1::rand::thread_rng;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
|
||||||
//! // Generate random key pair
|
//! // Generate random key pair
|
||||||
//! let s = Secp256k1::new();
|
//! let s = Secp256k1::new();
|
||||||
//! let public_key = key::PublicKey {
|
//! let public_key = key::PublicKey {
|
||||||
|
@ -37,7 +34,6 @@
|
||||||
//!
|
//!
|
||||||
//! // Generate pay-to-pubkey-hash address
|
//! // Generate pay-to-pubkey-hash address
|
||||||
//! let address = Address::p2pkh(&public_key, Network::Bitcoin);
|
//! let address = Address::p2pkh(&public_key, Network::Bitcoin);
|
||||||
//! }
|
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
@ -219,7 +215,7 @@ impl Payload {
|
||||||
assert!(ver.to_u8() <= 16);
|
assert!(ver.to_u8() <= 16);
|
||||||
let mut verop = ver.to_u8();
|
let mut verop = ver.to_u8();
|
||||||
if verop > 0 {
|
if verop > 0 {
|
||||||
verop = 0x50 + verop;
|
verop += 0x50;
|
||||||
}
|
}
|
||||||
script::Builder::new().push_opcode(verop.into()).push_slice(&prog)
|
script::Builder::new().push_opcode(verop.into()).push_slice(&prog)
|
||||||
}
|
}
|
||||||
|
@ -406,7 +402,7 @@ impl Display for Address {
|
||||||
/// Returns the same slice when no prefix is found.
|
/// Returns the same slice when no prefix is found.
|
||||||
fn find_bech32_prefix(bech32: &str) -> &str {
|
fn find_bech32_prefix(bech32: &str) -> &str {
|
||||||
// Split at the last occurrence of the separator character '1'.
|
// Split at the last occurrence of the separator character '1'.
|
||||||
match bech32.rfind("1") {
|
match bech32.rfind('1') {
|
||||||
None => bech32,
|
None => bech32,
|
||||||
Some(sep) => bech32.split_at(sep).0,
|
Some(sep) => bech32.split_at(sep).0,
|
||||||
}
|
}
|
||||||
|
@ -427,7 +423,7 @@ impl FromStr for Address {
|
||||||
if let Some(network) = bech32_network {
|
if let Some(network) = bech32_network {
|
||||||
// decode as bech32
|
// decode as bech32
|
||||||
let (_, payload) = bech32::decode(s)?;
|
let (_, payload) = bech32::decode(s)?;
|
||||||
if payload.len() == 0 {
|
if payload.is_empty() {
|
||||||
return Err(Error::EmptyBech32Payload);
|
return Err(Error::EmptyBech32Payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::error;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
/// A set of denominations in which amounts can be expressed.
|
/// A set of denominations in which amounts can be expressed.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
|
@ -131,7 +132,7 @@ impl error::Error for ParseAmountError {
|
||||||
|
|
||||||
|
|
||||||
fn is_too_precise(s: &str, precision: usize) -> bool {
|
fn is_too_precise(s: &str, precision: usize) -> bool {
|
||||||
s.contains(".") || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0')
|
s.contains('.') || precision >= s.len() || s.chars().rev().take(precision).any(|d| d != '0')
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse decimal string in the given denomination into a satoshi value and a
|
/// Parse decimal string in the given denomination into a satoshi value and a
|
||||||
|
@ -140,14 +141,14 @@ fn parse_signed_to_satoshi(
|
||||||
mut s: &str,
|
mut s: &str,
|
||||||
denom: Denomination,
|
denom: Denomination,
|
||||||
) -> Result<(bool, u64), ParseAmountError> {
|
) -> Result<(bool, u64), ParseAmountError> {
|
||||||
if s.len() == 0 {
|
if s.is_empty() {
|
||||||
return Err(ParseAmountError::InvalidFormat);
|
return Err(ParseAmountError::InvalidFormat);
|
||||||
}
|
}
|
||||||
if s.len() > 50 {
|
if s.len() > 50 {
|
||||||
return Err(ParseAmountError::InputTooLarge);
|
return Err(ParseAmountError::InputTooLarge);
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_negative = s.chars().next().unwrap() == '-';
|
let is_negative = s.starts_with('-');
|
||||||
if is_negative {
|
if is_negative {
|
||||||
if s.len() == 1 {
|
if s.len() == 1 {
|
||||||
return Err(ParseAmountError::InvalidFormat);
|
return Err(ParseAmountError::InvalidFormat);
|
||||||
|
@ -229,13 +230,16 @@ fn fmt_satoshi_in(
|
||||||
f.write_str("-")?;
|
f.write_str("-")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if denom.precision() > 0 {
|
let precision = denom.precision();
|
||||||
|
match precision.cmp(&0) {
|
||||||
|
Ordering::Greater => {
|
||||||
// add zeroes in the end
|
// add zeroes in the end
|
||||||
let width = denom.precision() as usize;
|
let width = precision as usize;
|
||||||
write!(f, "{}{:0width$}", satoshi, 0, width = width)?;
|
write!(f, "{}{:0width$}", satoshi, 0, width = width)?;
|
||||||
} else if denom.precision() < 0 {
|
}
|
||||||
|
Ordering::Less => {
|
||||||
// need to inject a comma in the number
|
// need to inject a comma in the number
|
||||||
let nb_decimals = denom.precision().abs() as usize;
|
let nb_decimals = precision.abs() as usize;
|
||||||
let real = format!("{:0width$}", satoshi, width = nb_decimals);
|
let real = format!("{:0width$}", satoshi, width = nb_decimals);
|
||||||
if real.len() == nb_decimals {
|
if real.len() == nb_decimals {
|
||||||
write!(f, "0.{}", &real[real.len() - nb_decimals..])?;
|
write!(f, "0.{}", &real[real.len() - nb_decimals..])?;
|
||||||
|
@ -247,9 +251,8 @@ fn fmt_satoshi_in(
|
||||||
&real[real.len() - nb_decimals..]
|
&real[real.len() - nb_decimals..]
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// denom.precision() == 0
|
Ordering::Equal => write!(f, "{}", satoshi)?,
|
||||||
write!(f, "{}", satoshi)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -271,7 +274,7 @@ fn fmt_satoshi_in(
|
||||||
/// zero is considered an underflow and will cause a panic if you're not using
|
/// zero is considered an underflow and will cause a panic if you're not using
|
||||||
/// the checked arithmetic methods.
|
/// the checked arithmetic methods.
|
||||||
///
|
///
|
||||||
#[derive(Copy, Clone, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Amount(u64);
|
pub struct Amount(u64);
|
||||||
|
|
||||||
impl Amount {
|
impl Amount {
|
||||||
|
@ -327,7 +330,7 @@ impl Amount {
|
||||||
/// If you want to parse only the amount without the denomination,
|
/// If you want to parse only the amount without the denomination,
|
||||||
/// use [from_str_in].
|
/// use [from_str_in].
|
||||||
pub fn from_str_with_denomination(s: &str) -> Result<Amount, ParseAmountError> {
|
pub fn from_str_with_denomination(s: &str) -> Result<Amount, ParseAmountError> {
|
||||||
let mut split = s.splitn(3, " ");
|
let mut split = s.splitn(3, ' ');
|
||||||
let amt_str = split.next().unwrap();
|
let amt_str = split.next().unwrap();
|
||||||
let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
|
let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
|
||||||
if split.next().is_some() {
|
if split.next().is_some() {
|
||||||
|
@ -340,7 +343,7 @@ impl Amount {
|
||||||
/// Express this [Amount] as a floating-point value in the given denomination.
|
/// Express this [Amount] as a floating-point value in the given denomination.
|
||||||
///
|
///
|
||||||
/// Please be aware of the risk of using floating-point numbers.
|
/// Please be aware of the risk of using floating-point numbers.
|
||||||
pub fn to_float_in(&self, denom: Denomination) -> f64 {
|
pub fn to_float_in(self, denom: Denomination) -> f64 {
|
||||||
f64::from_str(&self.to_string_in(denom)).unwrap()
|
f64::from_str(&self.to_string_in(denom)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +352,7 @@ impl Amount {
|
||||||
/// Equivalent to `to_float_in(Denomination::Bitcoin)`.
|
/// Equivalent to `to_float_in(Denomination::Bitcoin)`.
|
||||||
///
|
///
|
||||||
/// Please be aware of the risk of using floating-point numbers.
|
/// Please be aware of the risk of using floating-point numbers.
|
||||||
pub fn as_btc(&self) -> f64 {
|
pub fn as_btc(self) -> f64 {
|
||||||
self.to_float_in(Denomination::Bitcoin)
|
self.to_float_in(Denomination::Bitcoin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,14 +373,14 @@ impl Amount {
|
||||||
/// Format the value of this [Amount] in the given denomination.
|
/// Format the value of this [Amount] in the given denomination.
|
||||||
///
|
///
|
||||||
/// Does not include the denomination.
|
/// Does not include the denomination.
|
||||||
pub fn fmt_value_in(&self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result {
|
pub fn fmt_value_in(self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result {
|
||||||
fmt_satoshi_in(self.as_sat(), false, f, denom)
|
fmt_satoshi_in(self.as_sat(), false, f, denom)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a string number of this [Amount] in the given denomination.
|
/// Get a string number of this [Amount] in the given denomination.
|
||||||
///
|
///
|
||||||
/// Does not include the denomination.
|
/// Does not include the denomination.
|
||||||
pub fn to_string_in(&self, denom: Denomination) -> String {
|
pub fn to_string_in(self, denom: Denomination) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.fmt_value_in(&mut buf, denom).unwrap();
|
self.fmt_value_in(&mut buf, denom).unwrap();
|
||||||
buf
|
buf
|
||||||
|
@ -385,7 +388,7 @@ impl Amount {
|
||||||
|
|
||||||
/// Get a formatted string of this [Amount] in the given denomination,
|
/// Get a formatted string of this [Amount] in the given denomination,
|
||||||
/// suffixed with the abbreviation for the denomination.
|
/// suffixed with the abbreviation for the denomination.
|
||||||
pub fn to_string_with_denomination(&self, denom: Denomination) -> String {
|
pub fn to_string_with_denomination(self, denom: Denomination) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.fmt_value_in(&mut buf, denom).unwrap();
|
self.fmt_value_in(&mut buf, denom).unwrap();
|
||||||
write!(buf, " {}", denom).unwrap();
|
write!(buf, " {}", denom).unwrap();
|
||||||
|
@ -442,25 +445,6 @@ impl default::Default for Amount {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Amount {
|
|
||||||
fn eq(&self, other: &Amount) -> bool {
|
|
||||||
PartialEq::eq(&self.0, &other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Eq for Amount {}
|
|
||||||
|
|
||||||
impl PartialOrd for Amount {
|
|
||||||
fn partial_cmp(&self, other: &Amount) -> Option<::std::cmp::Ordering> {
|
|
||||||
PartialOrd::partial_cmp(&self.0, &other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for Amount {
|
|
||||||
fn cmp(&self, other: &Amount) -> ::std::cmp::Ordering {
|
|
||||||
Ord::cmp(&self.0, &other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Amount {
|
impl fmt::Debug for Amount {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "Amount({} satoshi)", self.as_sat())
|
write!(f, "Amount({} satoshi)", self.as_sat())
|
||||||
|
@ -568,7 +552,7 @@ impl FromStr for Amount {
|
||||||
/// start with `checked_`. The operations from [std::ops] that [Amount]
|
/// start with `checked_`. The operations from [std::ops] that [Amount]
|
||||||
/// implements will panic when overflow or underflow occurs.
|
/// implements will panic when overflow or underflow occurs.
|
||||||
///
|
///
|
||||||
#[derive(Copy, Clone, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct SignedAmount(i64);
|
pub struct SignedAmount(i64);
|
||||||
|
|
||||||
impl SignedAmount {
|
impl SignedAmount {
|
||||||
|
@ -614,7 +598,7 @@ impl SignedAmount {
|
||||||
return Err(ParseAmountError::TooBig);
|
return Err(ParseAmountError::TooBig);
|
||||||
}
|
}
|
||||||
Ok(match negative {
|
Ok(match negative {
|
||||||
true => SignedAmount(-1 * satoshi as i64),
|
true => SignedAmount(-(satoshi as i64)),
|
||||||
false => SignedAmount(satoshi as i64),
|
false => SignedAmount(satoshi as i64),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -624,7 +608,7 @@ impl SignedAmount {
|
||||||
/// If you want to parse only the amount without the denomination,
|
/// If you want to parse only the amount without the denomination,
|
||||||
/// use [from_str_in].
|
/// use [from_str_in].
|
||||||
pub fn from_str_with_denomination(s: &str) -> Result<SignedAmount, ParseAmountError> {
|
pub fn from_str_with_denomination(s: &str) -> Result<SignedAmount, ParseAmountError> {
|
||||||
let mut split = s.splitn(3, " ");
|
let mut split = s.splitn(3, ' ');
|
||||||
let amt_str = split.next().unwrap();
|
let amt_str = split.next().unwrap();
|
||||||
let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
|
let denom_str = split.next().ok_or(ParseAmountError::InvalidFormat)?;
|
||||||
if split.next().is_some() {
|
if split.next().is_some() {
|
||||||
|
@ -637,7 +621,7 @@ impl SignedAmount {
|
||||||
/// Express this [SignedAmount] as a floating-point value in the given denomination.
|
/// Express this [SignedAmount] as a floating-point value in the given denomination.
|
||||||
///
|
///
|
||||||
/// Please be aware of the risk of using floating-point numbers.
|
/// Please be aware of the risk of using floating-point numbers.
|
||||||
pub fn to_float_in(&self, denom: Denomination) -> f64 {
|
pub fn to_float_in(self, denom: Denomination) -> f64 {
|
||||||
f64::from_str(&self.to_string_in(denom)).unwrap()
|
f64::from_str(&self.to_string_in(denom)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +630,7 @@ impl SignedAmount {
|
||||||
/// Equivalent to `to_float_in(Denomination::Bitcoin)`.
|
/// Equivalent to `to_float_in(Denomination::Bitcoin)`.
|
||||||
///
|
///
|
||||||
/// Please be aware of the risk of using floating-point numbers.
|
/// Please be aware of the risk of using floating-point numbers.
|
||||||
pub fn as_btc(&self) -> f64 {
|
pub fn as_btc(self) -> f64 {
|
||||||
self.to_float_in(Denomination::Bitcoin)
|
self.to_float_in(Denomination::Bitcoin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +651,7 @@ impl SignedAmount {
|
||||||
/// Format the value of this [SignedAmount] in the given denomination.
|
/// Format the value of this [SignedAmount] in the given denomination.
|
||||||
///
|
///
|
||||||
/// Does not include the denomination.
|
/// Does not include the denomination.
|
||||||
pub fn fmt_value_in(&self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result {
|
pub fn fmt_value_in(self, f: &mut fmt::Write, denom: Denomination) -> fmt::Result {
|
||||||
let sats = self.as_sat().checked_abs().map(|a: i64| a as u64).unwrap_or_else(|| {
|
let sats = self.as_sat().checked_abs().map(|a: i64| a as u64).unwrap_or_else(|| {
|
||||||
// We could also hard code this into `9223372036854775808`
|
// We could also hard code this into `9223372036854775808`
|
||||||
u64::max_value() - self.as_sat() as u64 +1
|
u64::max_value() - self.as_sat() as u64 +1
|
||||||
|
@ -678,7 +662,7 @@ impl SignedAmount {
|
||||||
/// Get a string number of this [SignedAmount] in the given denomination.
|
/// Get a string number of this [SignedAmount] in the given denomination.
|
||||||
///
|
///
|
||||||
/// Does not include the denomination.
|
/// Does not include the denomination.
|
||||||
pub fn to_string_in(&self, denom: Denomination) -> String {
|
pub fn to_string_in(self, denom: Denomination) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.fmt_value_in(&mut buf, denom).unwrap();
|
self.fmt_value_in(&mut buf, denom).unwrap();
|
||||||
buf
|
buf
|
||||||
|
@ -686,7 +670,7 @@ impl SignedAmount {
|
||||||
|
|
||||||
/// Get a formatted string of this [SignedAmount] in the given denomination,
|
/// Get a formatted string of this [SignedAmount] in the given denomination,
|
||||||
/// suffixed with the abbreviation for the denomination.
|
/// suffixed with the abbreviation for the denomination.
|
||||||
pub fn to_string_with_denomination(&self, denom: Denomination) -> String {
|
pub fn to_string_with_denomination(self, denom: Denomination) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
self.fmt_value_in(&mut buf, denom).unwrap();
|
self.fmt_value_in(&mut buf, denom).unwrap();
|
||||||
write!(buf, " {}", denom).unwrap();
|
write!(buf, " {}", denom).unwrap();
|
||||||
|
@ -786,25 +770,6 @@ impl default::Default for SignedAmount {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for SignedAmount {
|
|
||||||
fn eq(&self, other: &SignedAmount) -> bool {
|
|
||||||
PartialEq::eq(&self.0, &other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Eq for SignedAmount {}
|
|
||||||
|
|
||||||
impl PartialOrd for SignedAmount {
|
|
||||||
fn partial_cmp(&self, other: &SignedAmount) -> Option<::std::cmp::Ordering> {
|
|
||||||
PartialOrd::partial_cmp(&self.0, &other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for SignedAmount {
|
|
||||||
fn cmp(&self, other: &SignedAmount) -> ::std::cmp::Ordering {
|
|
||||||
Ord::cmp(&self.0, &other.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for SignedAmount {
|
impl fmt::Debug for SignedAmount {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "SignedAmount({} satoshi)", self.as_sat())
|
write!(f, "SignedAmount({} satoshi)", self.as_sat())
|
||||||
|
@ -1313,12 +1278,12 @@ mod tests {
|
||||||
use super::Denomination as D;
|
use super::Denomination as D;
|
||||||
let amt = Amount::from_sat(42);
|
let amt = Amount::from_sat(42);
|
||||||
let denom = Amount::to_string_with_denomination;
|
let denom = Amount::to_string_with_denomination;
|
||||||
assert_eq!(Amount::from_str(&denom(&amt, D::Bitcoin)), Ok(amt));
|
assert_eq!(Amount::from_str(&denom(amt, D::Bitcoin)), Ok(amt));
|
||||||
assert_eq!(Amount::from_str(&denom(&amt, D::MilliBitcoin)), Ok(amt));
|
assert_eq!(Amount::from_str(&denom(amt, D::MilliBitcoin)), Ok(amt));
|
||||||
assert_eq!(Amount::from_str(&denom(&amt, D::MicroBitcoin)), Ok(amt));
|
assert_eq!(Amount::from_str(&denom(amt, D::MicroBitcoin)), Ok(amt));
|
||||||
assert_eq!(Amount::from_str(&denom(&amt, D::Bit)), Ok(amt));
|
assert_eq!(Amount::from_str(&denom(amt, D::Bit)), Ok(amt));
|
||||||
assert_eq!(Amount::from_str(&denom(&amt, D::Satoshi)), Ok(amt));
|
assert_eq!(Amount::from_str(&denom(amt, D::Satoshi)), Ok(amt));
|
||||||
assert_eq!(Amount::from_str(&denom(&amt, D::MilliSatoshi)), Ok(amt));
|
assert_eq!(Amount::from_str(&denom(amt, D::MilliSatoshi)), Ok(amt));
|
||||||
|
|
||||||
assert_eq!(Amount::from_str("42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
|
assert_eq!(Amount::from_str("42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
|
||||||
assert_eq!(SignedAmount::from_str("-42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
|
assert_eq!(SignedAmount::from_str("-42 satoshi BTC"), Err(ParseAmountError::InvalidFormat));
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl<T: Default + Copy> SmallVec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BASE58_CHARS: &'static [u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
static BASE58_CHARS: &[u8] = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
static BASE58_DIGITS: [Option<u8>; 128] = [
|
static BASE58_DIGITS: [Option<u8>; 128] = [
|
||||||
None, None, None, None, None, None, None, None, // 0-7
|
None, None, None, None, None, None, None, None, // 0-7
|
||||||
|
|
|
@ -49,6 +49,8 @@ use std::collections::HashSet;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
|
||||||
use hashes::{Hash, siphash24};
|
use hashes::{Hash, siphash24};
|
||||||
use hash_types::{BlockHash, FilterHash};
|
use hash_types::{BlockHash, FilterHash};
|
||||||
|
@ -241,7 +243,7 @@ impl GCSFilterReader {
|
||||||
pub fn match_any(&self, reader: &mut io::Read, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
pub fn match_any(&self, reader: &mut io::Read, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
||||||
let mut decoder = reader;
|
let mut decoder = reader;
|
||||||
let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0));
|
let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0));
|
||||||
let ref mut reader = decoder;
|
let reader = &mut decoder;
|
||||||
// map hashes to [0, n_elements << grp]
|
// map hashes to [0, n_elements << grp]
|
||||||
let nm = n_elements.0 * self.m;
|
let nm = n_elements.0 * self.m;
|
||||||
let mut mapped = query.map(|e| map_to_range(self.filter.hash(e), nm)).collect::<Vec<_>>();
|
let mut mapped = query.map(|e| map_to_range(self.filter.hash(e), nm)).collect::<Vec<_>>();
|
||||||
|
@ -260,17 +262,17 @@ impl GCSFilterReader {
|
||||||
let mut remaining = n_elements.0 - 1;
|
let mut remaining = n_elements.0 - 1;
|
||||||
for p in mapped {
|
for p in mapped {
|
||||||
loop {
|
loop {
|
||||||
if data == p {
|
match data.cmp(&p) {
|
||||||
return Ok(true);
|
Ordering::Equal => return Ok(true),
|
||||||
} else if data < p {
|
Ordering::Less => {
|
||||||
if remaining > 0 {
|
if remaining > 0 {
|
||||||
data += self.filter.golomb_rice_decode(&mut reader)?;
|
data += self.filter.golomb_rice_decode(&mut reader)?;
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
} else {
|
} else {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
break;
|
Ordering::Greater => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +283,7 @@ impl GCSFilterReader {
|
||||||
pub fn match_all(&self, reader: &mut io::Read, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
pub fn match_all(&self, reader: &mut io::Read, query: &mut Iterator<Item=&[u8]>) -> Result<bool, Error> {
|
||||||
let mut decoder = reader;
|
let mut decoder = reader;
|
||||||
let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0));
|
let n_elements: VarInt = Decodable::consensus_decode(&mut decoder).unwrap_or(VarInt(0));
|
||||||
let ref mut reader = decoder;
|
let reader = &mut decoder;
|
||||||
// map hashes to [0, n_elements << grp]
|
// map hashes to [0, n_elements << grp]
|
||||||
let nm = n_elements.0 * self.m;
|
let nm = n_elements.0 * self.m;
|
||||||
let mut mapped = query.map(|e| map_to_range(self.filter.hash(e), nm)).collect::<Vec<_>>();
|
let mut mapped = query.map(|e| map_to_range(self.filter.hash(e), nm)).collect::<Vec<_>>();
|
||||||
|
@ -301,17 +303,17 @@ impl GCSFilterReader {
|
||||||
let mut remaining = n_elements.0 - 1;
|
let mut remaining = n_elements.0 - 1;
|
||||||
for p in mapped {
|
for p in mapped {
|
||||||
loop {
|
loop {
|
||||||
if data == p {
|
match data.cmp(&p) {
|
||||||
break;
|
Ordering::Equal => break,
|
||||||
} else if data < p {
|
Ordering::Less => {
|
||||||
if remaining > 0 {
|
if remaining > 0 {
|
||||||
data += self.filter.golomb_rice_decode(&mut reader)?;
|
data += self.filter.golomb_rice_decode(&mut reader)?;
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
} else {
|
} else {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
return Ok(false);
|
Ordering::Greater => return Ok(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,7 +425,7 @@ impl GCSFilter {
|
||||||
q += 1;
|
q += 1;
|
||||||
}
|
}
|
||||||
let r = reader.read(self.p)?;
|
let r = reader.read(self.p)?;
|
||||||
return Ok((q << self.p) + r);
|
Ok((q << self.p) + r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hash an arbitrary slice with siphash using parameters of this filter
|
/// Hash an arbitrary slice with siphash using parameters of this filter
|
||||||
|
|
|
@ -124,15 +124,15 @@ impl ChildNumber {
|
||||||
/// Returns `true` if the child number is a [`Normal`] value.
|
/// Returns `true` if the child number is a [`Normal`] value.
|
||||||
///
|
///
|
||||||
/// [`Normal`]: #variant.Normal
|
/// [`Normal`]: #variant.Normal
|
||||||
pub fn is_normal(&self) -> bool {
|
pub fn is_normal(self) -> bool {
|
||||||
!self.is_hardened()
|
!self.is_hardened()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the child number is a [`Hardened`] value.
|
/// Returns `true` if the child number is a [`Hardened`] value.
|
||||||
///
|
///
|
||||||
/// [`Hardened`]: #variant.Hardened
|
/// [`Hardened`]: #variant.Hardened
|
||||||
pub fn is_hardened(&self) -> bool {
|
pub fn is_hardened(self) -> bool {
|
||||||
match *self {
|
match self {
|
||||||
ChildNumber::Hardened {..} => true,
|
ChildNumber::Hardened {..} => true,
|
||||||
ChildNumber::Normal {..} => false,
|
ChildNumber::Normal {..} => false,
|
||||||
}
|
}
|
||||||
|
@ -179,13 +179,11 @@ impl FromStr for ChildNumber {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(inp: &str) -> Result<ChildNumber, Error> {
|
fn from_str(inp: &str) -> Result<ChildNumber, Error> {
|
||||||
Ok(match inp.chars().last().map_or(false, |l| l == '\'' || l == 'h') {
|
let is_hardened = inp.chars().last().map_or(false, |l| l == '\'' || l == 'h');
|
||||||
true => ChildNumber::from_hardened_idx(
|
Ok(if is_hardened {
|
||||||
inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?
|
ChildNumber::from_hardened_idx(inp[0..inp.len() - 1].parse().map_err(|_| Error::InvalidChildNumberFormat)?)?
|
||||||
)?,
|
} else {
|
||||||
false => ChildNumber::from_normal_idx(
|
ChildNumber::from_normal_idx(inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?)?
|
||||||
inp.parse().map_err(|_| Error::InvalidChildNumberFormat)?
|
|
||||||
)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,7 +256,7 @@ impl FromStr for DerivationPath {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(path: &str) -> Result<DerivationPath, Error> {
|
fn from_str(path: &str) -> Result<DerivationPath, Error> {
|
||||||
let mut parts = path.split("/");
|
let mut parts = path.split('/');
|
||||||
// First parts must be `m`.
|
// First parts must be `m`.
|
||||||
if parts.next().unwrap() != "m" {
|
if parts.next().unwrap() != "m" {
|
||||||
return Err(Error::InvalidDerivationPathFormat);
|
return Err(Error::InvalidDerivationPathFormat);
|
||||||
|
@ -292,11 +290,7 @@ impl<'a> Iterator for DerivationPathIterator<'a> {
|
||||||
type Item = DerivationPath;
|
type Item = DerivationPath;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.next_child.is_none() {
|
let ret = self.next_child?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ret = self.next_child.unwrap();
|
|
||||||
self.next_child = ret.increment().ok();
|
self.next_child = ret.increment().ok();
|
||||||
Some(self.base.child(ret))
|
Some(self.base.child(ret))
|
||||||
}
|
}
|
||||||
|
@ -548,7 +542,7 @@ impl ExtendedPubKey {
|
||||||
i: ChildNumber,
|
i: ChildNumber,
|
||||||
) -> Result<ExtendedPubKey, Error> {
|
) -> Result<ExtendedPubKey, Error> {
|
||||||
let (sk, chain_code) = self.ckd_pub_tweak(i)?;
|
let (sk, chain_code) = self.ckd_pub_tweak(i)?;
|
||||||
let mut pk = self.public_key.clone();
|
let mut pk = self.public_key;
|
||||||
pk.key.add_exp_assign(secp, &sk[..]).map_err(Error::Ecdsa)?;
|
pk.key.add_exp_assign(secp, &sk[..]).map_err(Error::Ecdsa)?;
|
||||||
|
|
||||||
Ok(ExtendedPubKey {
|
Ok(ExtendedPubKey {
|
||||||
|
@ -604,9 +598,9 @@ impl FromStr for ExtendedPrivKey {
|
||||||
let cn_int: u32 = endian::slice_to_u32_be(&data[9..13]);
|
let cn_int: u32 = endian::slice_to_u32_be(&data[9..13]);
|
||||||
let child_number: ChildNumber = ChildNumber::from(cn_int);
|
let child_number: ChildNumber = ChildNumber::from(cn_int);
|
||||||
|
|
||||||
let network = if &data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] {
|
let network = if data[0..4] == [0x04u8, 0x88, 0xAD, 0xE4] {
|
||||||
Network::Bitcoin
|
Network::Bitcoin
|
||||||
} else if &data[0..4] == [0x04u8, 0x35, 0x83, 0x94] {
|
} else if data[0..4] == [0x04u8, 0x35, 0x83, 0x94] {
|
||||||
Network::Testnet
|
Network::Testnet
|
||||||
} else {
|
} else {
|
||||||
return Err(base58::Error::InvalidVersion((&data[0..4]).to_vec()));
|
return Err(base58::Error::InvalidVersion((&data[0..4]).to_vec()));
|
||||||
|
@ -661,9 +655,9 @@ impl FromStr for ExtendedPubKey {
|
||||||
let child_number: ChildNumber = ChildNumber::from(cn_int);
|
let child_number: ChildNumber = ChildNumber::from(cn_int);
|
||||||
|
|
||||||
Ok(ExtendedPubKey {
|
Ok(ExtendedPubKey {
|
||||||
network: if &data[0..4] == [0x04u8, 0x88, 0xB2, 0x1E] {
|
network: if data[0..4] == [0x04u8, 0x88, 0xB2, 0x1E] {
|
||||||
Network::Bitcoin
|
Network::Bitcoin
|
||||||
} else if &data[0..4] == [0x04u8, 0x35, 0x87, 0xCF] {
|
} else if data[0..4] == [0x04u8, 0x35, 0x87, 0xCF] {
|
||||||
Network::Testnet
|
Network::Testnet
|
||||||
} else {
|
} else {
|
||||||
return Err(base58::Error::InvalidVersion((&data[0..4]).to_vec()));
|
return Err(base58::Error::InvalidVersion((&data[0..4]).to_vec()));
|
||||||
|
|
|
@ -30,7 +30,7 @@ pub fn bitcoin_merkle_root_inline<T>(data: &mut [T]) -> T
|
||||||
<T as Hash>::Engine: io::Write,
|
<T as Hash>::Engine: io::Write,
|
||||||
{
|
{
|
||||||
// Base case
|
// Base case
|
||||||
if data.len() < 1 {
|
if data.is_empty() {
|
||||||
return Default::default();
|
return Default::default();
|
||||||
}
|
}
|
||||||
if data.len() < 2 {
|
if data.len() < 2 {
|
||||||
|
|
|
@ -25,12 +25,10 @@
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! extern crate bitcoin;
|
|
||||||
//! use bitcoin::hash_types::Txid;
|
//! use bitcoin::hash_types::Txid;
|
||||||
//! use bitcoin::hashes::hex::FromHex;
|
//! use bitcoin::hashes::hex::FromHex;
|
||||||
//! use bitcoin::{Block, MerkleBlock};
|
//! use bitcoin::{Block, MerkleBlock};
|
||||||
//!
|
//!
|
||||||
//! # fn main() {
|
|
||||||
//! // Get the proof from a bitcoind by running in the terminal:
|
//! // Get the proof from a bitcoind by running in the terminal:
|
||||||
//! // $ TXID="5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2"
|
//! // $ TXID="5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2"
|
||||||
//! // $ bitcoin-cli gettxoutproof [\"$TXID\"]
|
//! // $ bitcoin-cli gettxoutproof [\"$TXID\"]
|
||||||
|
@ -52,7 +50,6 @@
|
||||||
//! );
|
//! );
|
||||||
//! assert_eq!(1, index.len());
|
//! assert_eq!(1, index.len());
|
||||||
//! assert_eq!(1, index[0]);
|
//! assert_eq!(1, index[0]);
|
||||||
//! # }
|
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
@ -133,12 +130,10 @@ impl PartialMerkleTree {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate bitcoin;
|
|
||||||
/// use bitcoin::hash_types::Txid;
|
/// use bitcoin::hash_types::Txid;
|
||||||
/// use bitcoin::hashes::hex::FromHex;
|
/// use bitcoin::hashes::hex::FromHex;
|
||||||
/// use bitcoin::util::merkleblock::PartialMerkleTree;
|
/// use bitcoin::util::merkleblock::PartialMerkleTree;
|
||||||
///
|
///
|
||||||
/// # fn main() {
|
|
||||||
/// // Block 80000
|
/// // Block 80000
|
||||||
/// let txids: Vec<Txid> = [
|
/// let txids: Vec<Txid> = [
|
||||||
/// "c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25",
|
/// "c06fbab289f723c6261d3030ddb6be121f7d2508d77862bb1e484f5cd7f92b25",
|
||||||
|
@ -152,7 +147,6 @@ impl PartialMerkleTree {
|
||||||
/// let matches = vec![false, true];
|
/// let matches = vec![false, true];
|
||||||
/// let tree = PartialMerkleTree::from_txids(&txids, &matches);
|
/// let tree = PartialMerkleTree::from_txids(&txids, &matches);
|
||||||
/// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok());
|
/// assert!(tree.extract_matches(&mut vec![], &mut vec![]).is_ok());
|
||||||
/// # }
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self {
|
pub fn from_txids(txids: &[Txid], matches: &[bool]) -> Self {
|
||||||
// We can never have zero txs in a merkle block, we always need the coinbase tx
|
// We can never have zero txs in a merkle block, we always need the coinbase tx
|
||||||
|
@ -271,7 +265,7 @@ impl PartialMerkleTree {
|
||||||
if height == 0 || !parent_of_match {
|
if height == 0 || !parent_of_match {
|
||||||
// If at height 0, or nothing interesting below, store hash and stop
|
// If at height 0, or nothing interesting below, store hash and stop
|
||||||
let hash = self.calc_hash(height, pos, txids);
|
let hash = self.calc_hash(height, pos, txids);
|
||||||
self.hashes.push(hash.into());
|
self.hashes.push(hash);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, don't store any hash, but descend into the subtrees
|
// Otherwise, don't store any hash, but descend into the subtrees
|
||||||
self.traverse_and_build(height - 1, pos * 2, txids, matches);
|
self.traverse_and_build(height - 1, pos * 2, txids, matches);
|
||||||
|
@ -407,12 +401,10 @@ impl MerkleBlock {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate bitcoin;
|
|
||||||
/// use bitcoin::hash_types::Txid;
|
/// use bitcoin::hash_types::Txid;
|
||||||
/// use bitcoin::hashes::hex::FromHex;
|
/// use bitcoin::hashes::hex::FromHex;
|
||||||
/// use bitcoin::{Block, MerkleBlock};
|
/// use bitcoin::{Block, MerkleBlock};
|
||||||
///
|
///
|
||||||
/// # fn main() {
|
|
||||||
/// // Block 80000
|
/// // Block 80000
|
||||||
/// let block_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad2\
|
/// let block_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad2\
|
||||||
/// 7b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33\
|
/// 7b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38f33\
|
||||||
|
@ -437,7 +429,6 @@ impl MerkleBlock {
|
||||||
/// let mut index: Vec<u32> = vec![];
|
/// let mut index: Vec<u32> = vec![];
|
||||||
/// assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
/// assert!(mb.extract_matches(&mut matches, &mut index).is_ok());
|
||||||
/// assert_eq!(txid, matches[0]);
|
/// assert_eq!(txid, matches[0]);
|
||||||
/// # }
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_block(block: &Block, match_txids: &HashSet<Txid>) -> Self {
|
pub fn from_block(block: &Block, match_txids: &HashSet<Txid>) -> Self {
|
||||||
let header = block.header;
|
let header = block.header;
|
||||||
|
|
|
@ -20,14 +20,14 @@ use hashes::{sha256d, Hash};
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use consensus::encode;
|
use consensus::encode;
|
||||||
|
|
||||||
static MSG_SIGN_PREFIX: &'static [u8] = b"\x18Bitcoin Signed Message:\n";
|
static MSG_SIGN_PREFIX: &[u8] = b"\x18Bitcoin Signed Message:\n";
|
||||||
|
|
||||||
/// Search for `needle` in the vector `haystack` and remove every
|
/// Search for `needle` in the vector `haystack` and remove every
|
||||||
/// instance of it, returning the number of instances removed.
|
/// instance of it, returning the number of instances removed.
|
||||||
/// Loops through the vector opcode by opcode, skipping pushed data.
|
/// Loops through the vector opcode by opcode, skipping pushed data.
|
||||||
pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
|
pub fn script_find_and_remove(haystack: &mut Vec<u8>, needle: &[u8]) -> usize {
|
||||||
if needle.len() > haystack.len() { return 0; }
|
if needle.len() > haystack.len() { return 0; }
|
||||||
if needle.len() == 0 { return 0; }
|
if needle.is_empty() { return 0; }
|
||||||
|
|
||||||
let mut top = haystack.len() - needle.len();
|
let mut top = haystack.len() - needle.len();
|
||||||
let mut n_deleted = 0;
|
let mut n_deleted = 0;
|
||||||
|
|
|
@ -104,7 +104,7 @@ macro_rules! impl_psbtmap_consensus_enc_dec_oding {
|
||||||
macro_rules! impl_psbt_insert_pair {
|
macro_rules! impl_psbt_insert_pair {
|
||||||
($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => {
|
($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => {
|
||||||
if $raw_key.key.is_empty() {
|
if $raw_key.key.is_empty() {
|
||||||
if let None = $slf.$unkeyed_name {
|
if $slf.$unkeyed_name.is_none() {
|
||||||
let val: $unkeyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?;
|
let val: $unkeyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?;
|
||||||
|
|
||||||
$slf.$unkeyed_name = Some(val)
|
$slf.$unkeyed_name = Some(val)
|
||||||
|
@ -119,12 +119,12 @@ macro_rules! impl_psbt_insert_pair {
|
||||||
if !$raw_key.key.is_empty() {
|
if !$raw_key.key.is_empty() {
|
||||||
let key_val: $keyed_key_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?;
|
let key_val: $keyed_key_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?;
|
||||||
|
|
||||||
if $slf.$keyed_name.contains_key(&key_val) {
|
match $slf.$keyed_name.entry(key_val) {
|
||||||
return Err(::util::psbt::Error::DuplicateKey($raw_key).into());
|
::std::collections::btree_map::Entry::Vacant(empty_key) => {
|
||||||
} else {
|
|
||||||
let val: $keyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?;
|
let val: $keyed_value_type = ::util::psbt::serialize::Deserialize::deserialize(&$raw_value)?;
|
||||||
|
empty_key.insert(val);
|
||||||
$slf.$keyed_name.insert(key_val, val);
|
}
|
||||||
|
::std::collections::btree_map::Entry::Occupied(_) => return Err(::util::psbt::Error::DuplicateKey($raw_key).into()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(::util::psbt::Error::InvalidKey($raw_key).into());
|
return Err(::util::psbt::Error::InvalidKey($raw_key).into());
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::collections::btree_map::Entry;
|
||||||
use std::io::{self, Cursor};
|
use std::io::{self, Cursor};
|
||||||
|
|
||||||
use blockdata::transaction::Transaction;
|
use blockdata::transaction::Transaction;
|
||||||
|
@ -60,15 +61,10 @@ impl Map for Global {
|
||||||
} = pair;
|
} = pair;
|
||||||
|
|
||||||
match raw_key.type_value {
|
match raw_key.type_value {
|
||||||
0u8 => {
|
0u8 => return Err(Error::DuplicateKey(raw_key).into()),
|
||||||
return Err(Error::DuplicateKey(raw_key).into());
|
_ => match self.unknown.entry(raw_key) {
|
||||||
}
|
Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
|
||||||
_ => {
|
Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
|
||||||
if self.unknown.contains_key(&raw_key) {
|
|
||||||
return Err(Error::DuplicateKey(raw_key).into());
|
|
||||||
} else {
|
|
||||||
self.unknown.insert(raw_key, raw_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,12 +154,9 @@ impl Decodable for Global {
|
||||||
return Err(Error::InvalidKey(pair.key).into())
|
return Err(Error::InvalidKey(pair.key).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => match unknowns.entry(pair.key) {
|
||||||
if unknowns.contains_key(&pair.key) {
|
Entry::Vacant(empty_key) => {empty_key.insert(pair.value);},
|
||||||
return Err(Error::DuplicateKey(pair.key).into());
|
Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
|
||||||
} else {
|
|
||||||
unknowns.insert(pair.key, pair.value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,12 +112,9 @@ impl Map for Input {
|
||||||
self.hd_keypaths <= <raw_key: PublicKey>|<raw_value: (Fingerprint, DerivationPath)>
|
self.hd_keypaths <= <raw_key: PublicKey>|<raw_value: (Fingerprint, DerivationPath)>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => match self.unknown.entry(raw_key) {
|
||||||
if self.unknown.contains_key(&raw_key) {
|
::std::collections::btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
|
||||||
return Err(Error::DuplicateKey(raw_key).into());
|
::std::collections::btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
|
||||||
} else {
|
|
||||||
self.unknown.insert(raw_key, raw_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::collections::btree_map::Entry;
|
||||||
|
|
||||||
use blockdata::script::Script;
|
use blockdata::script::Script;
|
||||||
use consensus::encode;
|
use consensus::encode;
|
||||||
|
@ -61,12 +62,9 @@ impl Map for Output {
|
||||||
self.hd_keypaths <= <raw_key: PublicKey>|<raw_value: (Fingerprint, DerivationPath)>
|
self.hd_keypaths <= <raw_key: PublicKey>|<raw_value: (Fingerprint, DerivationPath)>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => match self.unknown.entry(raw_key) {
|
||||||
if self.unknown.contains_key(&raw_key) {
|
Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
|
||||||
return Err(Error::DuplicateKey(raw_key).into());
|
Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
|
||||||
} else {
|
|
||||||
self.unknown.insert(raw_key, raw_value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,8 @@ impl PartiallySignedTransaction {
|
||||||
let mut tx: Transaction = self.global.unsigned_tx;
|
let mut tx: Transaction = self.global.unsigned_tx;
|
||||||
|
|
||||||
for (vin, psbtin) in tx.input.iter_mut().zip(self.inputs.into_iter()) {
|
for (vin, psbtin) in tx.input.iter_mut().zip(self.inputs.into_iter()) {
|
||||||
vin.script_sig = psbtin.final_script_sig.unwrap_or_else(|| Script::new());
|
vin.script_sig = psbtin.final_script_sig.unwrap_or_else(Script::new);
|
||||||
vin.witness = psbtin.final_script_witness.unwrap_or_else(|| Vec::new());
|
vin.witness = psbtin.final_script_witness.unwrap_or_else(Vec::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
tx
|
tx
|
||||||
|
|
Loading…
Reference in New Issue