From 725884bab5fcb5e946764d55d548f82cf18d05ea Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 10:53:50 +0100 Subject: [PATCH 1/7] Introduce key::Error --- src/consensus/encode.rs | 11 ------- src/util/key.rs | 65 ++++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 63a91227..b3b7c4a8 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -41,7 +41,6 @@ use hashes::{sha256d, Hash as HashTrait}; use secp256k1; use util::endian; -use util::base58; use util::psbt; use blockdata::transaction::{TxOut, Transaction, TxIn}; @@ -53,8 +52,6 @@ use network::address::Address; pub enum Error { /// And I/O error Io(io::Error), - /// Base58 encoding error - Base58(base58::Error), /// Error from the `byteorder` crate ByteOrder(io::Error), /// secp-related error @@ -98,7 +95,6 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Io(ref e) => fmt::Display::fmt(e, f), - Error::Base58(ref e) => fmt::Display::fmt(e, f), Error::ByteOrder(ref e) => fmt::Display::fmt(e, f), Error::Secp256k1(ref e) => fmt::Display::fmt(e, f), Error::Psbt(ref e) => fmt::Display::fmt(e, f), @@ -118,7 +114,6 @@ impl error::Error for Error { fn cause(&self) -> Option<&error::Error> { match *self { Error::Io(ref e) => Some(e), - Error::Base58(ref e) => Some(e), Error::ByteOrder(ref e) => Some(e), Error::Secp256k1(ref e) => Some(e), Error::Psbt(ref e) => Some(e), @@ -136,7 +131,6 @@ impl error::Error for Error { fn description(&self) -> &str { match *self { Error::Io(ref e) => e.description(), - Error::Base58(ref e) => e.description(), Error::ByteOrder(ref e) => e.description(), Error::Secp256k1(ref e) => e.description(), Error::Psbt(ref e) => e.description(), @@ -153,11 +147,6 @@ impl error::Error for Error { } #[doc(hidden)] -impl From for Error { - fn from(e: base58::Error) -> Error { - Error::Base58(e) - } -} #[doc(hidden)] impl From for Error { diff --git a/src/util/key.rs b/src/util/key.rs index 07dfb017..c9f81faf 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -17,14 +17,59 @@ //! use std::fmt::{self, Write}; -use std::{io, ops}; +use std::{io, ops, error}; use std::str::FromStr; use secp256k1::{self, Secp256k1}; -use consensus::encode; use network::constants::Network; use util::base58; +/// A key-related error. +#[derive(Debug)] +pub enum Error { + /// Base58 encoding error + Base58(base58::Error), + /// secp256k1-related error + Secp256k1(secp256k1::Error), +} + + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::Base58(ref e) => write!(f, "base58 error: {}", e), + Error::Secp256k1(ref e) => write!(f, "secp256k1 error: {}", e), + } + } +} + +impl error::Error for Error { + fn cause(&self) -> Option<&error::Error> { + match *self { + Error::Base58(ref e) => Some(e), + Error::Secp256k1(ref e) => Some(e), + } + } + + fn description(&self) -> &str { + "Bitcoin key error" + } +} + +#[doc(hidden)] +impl From for Error { + fn from(e: base58::Error) -> Error { + Error::Base58(e) + } +} + +#[doc(hidden)] +impl From for Error { + fn from(e: secp256k1::Error) -> Error { + Error::Secp256k1(e) + } +} + /// A Bitcoin ECDSA public key #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PublicKey { @@ -53,7 +98,7 @@ impl PublicKey { } /// Deserialize a public key from a slice - pub fn from_slice(data: &[u8]) -> Result { + pub fn from_slice(data: &[u8]) -> Result { let compressed: bool = match data.len() { 33 => true, 65 => false, @@ -88,8 +133,8 @@ impl fmt::Display for PublicKey { } impl FromStr for PublicKey { - type Err = encode::Error; - fn from_str(s: &str) -> Result { + type Err = Error; + fn from_str(s: &str) -> Result { let key = secp256k1::PublicKey::from_str(s)?; Ok(PublicKey { key: key, @@ -149,19 +194,19 @@ impl PrivateKey { } /// Parse WIF encoded private key. - pub fn from_wif(wif: &str) -> Result { + pub fn from_wif(wif: &str) -> Result { let data = base58::from_check(wif)?; let compressed = match data.len() { 33 => false, 34 => true, - _ => { return Err(encode::Error::Base58(base58::Error::InvalidLength(data.len()))); } + _ => { return Err(Error::Base58(base58::Error::InvalidLength(data.len()))); } }; let network = match data[0] { 128 => Network::Bitcoin, 239 => Network::Testnet, - x => { return Err(encode::Error::Base58(base58::Error::InvalidVersion(vec![x]))); } + x => { return Err(Error::Base58(base58::Error::InvalidVersion(vec![x]))); } }; Ok(PrivateKey { @@ -185,8 +230,8 @@ impl fmt::Debug for PrivateKey { } impl FromStr for PrivateKey { - type Err = encode::Error; - fn from_str(s: &str) -> Result { + type Err = Error; + fn from_str(s: &str) -> Result { PrivateKey::from_wif(s) } } From 5373428510cc4d8c635a08f253f1212cd33c8668 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 10:59:12 +0100 Subject: [PATCH 2/7] Drop unused encode::Error::Secp256k1 variant --- src/consensus/encode.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index b3b7c4a8..bdb26c9e 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -38,7 +38,6 @@ use std::io::{Cursor, Read, Write}; use hashes::hex::ToHex; use hashes::{sha256d, Hash as HashTrait}; -use secp256k1; use util::endian; use util::psbt; @@ -54,8 +53,6 @@ pub enum Error { Io(io::Error), /// Error from the `byteorder` crate ByteOrder(io::Error), - /// secp-related error - Secp256k1(secp256k1::Error), /// PSBT-related error Psbt(psbt::Error), /// Network magic was not expected @@ -96,7 +93,6 @@ impl fmt::Display for Error { match *self { Error::Io(ref e) => fmt::Display::fmt(e, f), Error::ByteOrder(ref e) => fmt::Display::fmt(e, f), - Error::Secp256k1(ref e) => fmt::Display::fmt(e, f), Error::Psbt(ref e) => fmt::Display::fmt(e, f), Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e, a), Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "{}: requested {}, maximum {}", error::Error::description(self), r, m), @@ -115,7 +111,6 @@ impl error::Error for Error { match *self { Error::Io(ref e) => Some(e), Error::ByteOrder(ref e) => Some(e), - Error::Secp256k1(ref e) => Some(e), Error::Psbt(ref e) => Some(e), Error::UnexpectedNetworkMagic { .. } | Error::OversizedVectorAllocation { .. } @@ -132,7 +127,6 @@ impl error::Error for Error { match *self { Error::Io(ref e) => e.description(), Error::ByteOrder(ref e) => e.description(), - Error::Secp256k1(ref e) => e.description(), Error::Psbt(ref e) => e.description(), Error::UnexpectedNetworkMagic { .. } => "unexpected network magic", Error::OversizedVectorAllocation { .. } => "allocation of oversized vector requested", @@ -148,13 +142,6 @@ impl error::Error for Error { #[doc(hidden)] -#[doc(hidden)] -impl From for Error { - fn from(e: secp256k1::Error) -> Error { - Error::Secp256k1(e) - } -} - #[doc(hidden)] impl From for Error { fn from(error: io::Error) -> Self { From d02318f423e47a3966422f2dfe4530db22fe38f0 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 11:06:38 +0100 Subject: [PATCH 3/7] Remove deprecated std::error::Error::description --- src/consensus/encode.rs | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index bdb26c9e..07a47b97 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -91,17 +91,22 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::Io(ref e) => fmt::Display::fmt(e, f), - Error::ByteOrder(ref e) => fmt::Display::fmt(e, f), - Error::Psbt(ref e) => fmt::Display::fmt(e, f), - Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e, a), - Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "{}: requested {}, maximum {}", error::Error::description(self), r, m), - Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "{}: expected {}, actual {}", error::Error::description(self), e[..].to_hex(), a[..].to_hex()), - Error::UnknownNetworkMagic(ref m) => write!(f, "{}: {}", error::Error::description(self), m), - Error::ParseFailed(ref e) => write!(f, "{}: {}", error::Error::description(self), e), - Error::UnsupportedSegwitFlag(ref swflag) => write!(f, "{}: {}", error::Error::description(self), swflag), - Error::UnrecognizedNetworkCommand(ref nwcmd) => write!(f, "{}: {}", error::Error::description(self), nwcmd), - Error::UnexpectedHexDigit(ref d) => write!(f, "{}: {}", error::Error::description(self), d), + Error::Io(ref e) => write!(f, "I/O error: {}", e), + Error::ByteOrder(ref e) => write!(f, "byteorder error: {}", e), + Error::Psbt(ref e) => write!(f, "PSBT error: {}", e), + Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, + "unexpected network magic: expected {}, actual {}", e, a), + Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, + "allocation of oversized vector: requested {}, maximum {}", r, m), + Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, + "invalid checksum: expected {}, actual {}", e.to_hex(), a.to_hex()), + Error::UnknownNetworkMagic(ref m) => write!(f, "unknown network magic: {}", m), + Error::ParseFailed(ref e) => write!(f, "parse failed: {}", e), + Error::UnsupportedSegwitFlag(ref swflag) => write!(f, + "unsupported segwit version: {}", swflag), + Error::UnrecognizedNetworkCommand(ref nwcmd) => write!(f, + "unrecognized network command: {}", nwcmd), + Error::UnexpectedHexDigit(ref d) => write!(f, "unexpected hex digit: {}", d), } } } @@ -124,19 +129,7 @@ impl error::Error for Error { } fn description(&self) -> &str { - match *self { - Error::Io(ref e) => e.description(), - Error::ByteOrder(ref e) => e.description(), - Error::Psbt(ref e) => e.description(), - Error::UnexpectedNetworkMagic { .. } => "unexpected network magic", - Error::OversizedVectorAllocation { .. } => "allocation of oversized vector requested", - Error::InvalidChecksum { .. } => "invalid checksum", - Error::UnknownNetworkMagic(..) => "unknown network magic", - Error::ParseFailed(..) => "parse failed", - Error::UnsupportedSegwitFlag(..) => "unsupported segwit version", - Error::UnrecognizedNetworkCommand(..) => "unrecognized network command", - Error::UnexpectedHexDigit(..) => "unexpected hex digit", - } + "Bitcoin encoding error" } } From 1eeaccc92eec90ab377372253322b79dad93667e Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 11:12:34 +0100 Subject: [PATCH 4/7] Add encode::Error::NonMinimalVarInt variant --- src/consensus/encode.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index 07a47b97..af129c09 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -76,6 +76,8 @@ pub enum Error { /// The invalid checksum actual: [u8; 4], }, + /// VarInt was encoded in a non-minimal way + NonMinimalVarInt, /// Network magic was unknown UnknownNetworkMagic(u32), /// Parsing error @@ -100,6 +102,7 @@ impl fmt::Display for Error { "allocation of oversized vector: requested {}, maximum {}", r, m), Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, "invalid checksum: expected {}, actual {}", e.to_hex(), a.to_hex()), + Error::NonMinimalVarInt => write!(f, "non-minimal varint"), Error::UnknownNetworkMagic(ref m) => write!(f, "unknown network magic: {}", m), Error::ParseFailed(ref e) => write!(f, "parse failed: {}", e), Error::UnsupportedSegwitFlag(ref swflag) => write!(f, @@ -120,6 +123,7 @@ impl error::Error for Error { Error::UnexpectedNetworkMagic { .. } | Error::OversizedVectorAllocation { .. } | Error::InvalidChecksum { .. } + | Error::NonMinimalVarInt | Error::UnknownNetworkMagic(..) | Error::ParseFailed(..) | Error::UnsupportedSegwitFlag(..) @@ -425,7 +429,7 @@ impl Decodable for VarInt { 0xFF => { let x = ReadExt::read_u64(&mut d)?; if x < 0x100000000 { - Err(self::Error::ParseFailed("non-minimal varint")) + Err(self::Error::NonMinimalVarInt) } else { Ok(VarInt(x)) } @@ -433,7 +437,7 @@ impl Decodable for VarInt { 0xFE => { let x = ReadExt::read_u32(&mut d)?; if x < 0x10000 { - Err(self::Error::ParseFailed("non-minimal varint")) + Err(self::Error::NonMinimalVarInt) } else { Ok(VarInt(x as u64)) } @@ -441,7 +445,7 @@ impl Decodable for VarInt { 0xFD => { let x = ReadExt::read_u16(&mut d)?; if x < 0xFD { - Err(self::Error::ParseFailed("non-minimal varint")) + Err(self::Error::NonMinimalVarInt) } else { Ok(VarInt(x as u64)) } @@ -791,27 +795,27 @@ mod tests { #[test] fn deserialize_nonminimal_vec() { match deserialize::>(&[0xfd, 0x00, 0x00]) { - Err(Error::ParseFailed("non-minimal varint")) => {}, + Err(Error::NonMinimalVarInt) => {}, x => panic!(x) } match deserialize::>(&[0xfd, 0xfc, 0x00]) { - Err(Error::ParseFailed("non-minimal varint")) => {}, + Err(Error::NonMinimalVarInt) => {}, x => panic!(x) } match deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]) { - Err(Error::ParseFailed("non-minimal varint")) => {}, + Err(Error::NonMinimalVarInt) => {}, x => panic!(x) } match deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]) { - Err(Error::ParseFailed("non-minimal varint")) => {}, + Err(Error::NonMinimalVarInt) => {}, x => panic!(x) } match deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) { - Err(Error::ParseFailed("non-minimal varint")) => {}, + Err(Error::NonMinimalVarInt) => {}, x => panic!(x) } match deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]) { - Err(Error::ParseFailed("non-minimal varint")) => {}, + Err(Error::NonMinimalVarInt) => {}, x => panic!(x) } From 0469453da67b8133170b70abb170589fb75163b9 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 11:40:23 +0100 Subject: [PATCH 5/7] Use psbt::Error in PartiallySignedTransaction::from_unsigned_tx --- src/util/psbt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 62dd4365..6e631719 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -53,7 +53,7 @@ pub struct PartiallySignedTransaction { impl PartiallySignedTransaction { /// Create a PartiallySignedTransaction from an unsigned transaction, error /// if not unsigned - pub fn from_unsigned_tx(tx: Transaction) -> Result { + pub fn from_unsigned_tx(tx: Transaction) -> Result { Ok(PartiallySignedTransaction { inputs: vec![Default::default(); tx.input.len()], outputs: vec![Default::default(); tx.output.len()], From 5f4555bfac04c73dba94dd05321af7986fb9ce28 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 11:49:35 +0100 Subject: [PATCH 6/7] Remove util::misc::hex_bytes in favor of bitcoin_hashes::hex --- src/blockdata/constants.rs | 5 +- src/blockdata/transaction.rs | 25 ++++---- src/consensus/encode.rs | 6 +- src/util/bip143.rs | 8 +-- src/util/misc.rs | 112 ----------------------------------- 5 files changed, 20 insertions(+), 136 deletions(-) diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 7bf0b6d0..9fc7562f 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -21,12 +21,13 @@ use std::default::Default; +use hashes::hex::FromHex; + use blockdata::opcodes; use blockdata::script; use blockdata::transaction::{OutPoint, Transaction, TxOut, TxIn}; use blockdata::block::{Block, BlockHeader}; use network::constants::Network; -use util::misc::hex_bytes; use util::uint::Uint256; /// The maximum allowable sequence number @@ -81,7 +82,7 @@ fn bitcoin_genesis_tx() -> Transaction { // Outputs let out_script = script::Builder::new() - .push_slice(&hex_bytes("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap()) + .push_slice(&Vec::::from_hex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap()) .push_opcode(opcodes::all::OP_CHECKSIG) .into_script(); ret.output.push(TxOut { diff --git a/src/blockdata/transaction.rs b/src/blockdata/transaction.rs index 8ae4eda8..57027eb2 100644 --- a/src/blockdata/transaction.rs +++ b/src/blockdata/transaction.rs @@ -626,7 +626,6 @@ mod tests { use consensus::encode::serialize; use consensus::encode::deserialize; use util::hash::BitcoinHash; - use util::misc::hex_bytes; use hashes::{sha256d, Hash}; use hashes::hex::FromHex; @@ -666,7 +665,7 @@ mod tests { #[test] fn test_txin() { - let txin: Result = deserialize(&hex_bytes("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff").unwrap()); + let txin: Result = deserialize(&Vec::::from_hex("a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff").unwrap()); assert!(txin.is_ok()); } @@ -687,14 +686,14 @@ mod tests { let genesis = constants::genesis_block(Network::Bitcoin); assert! (genesis.txdata[0].is_coin_base()); - let hex_tx = hex_bytes("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap(); assert!(!tx.is_coin_base()); } #[test] fn test_transaction() { - let hex_tx = hex_bytes("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Result = deserialize(&hex_tx); assert!(tx.is_ok()); let realtx = tx.unwrap(); @@ -717,7 +716,7 @@ mod tests { #[test] fn tx_no_input_deserialization() { - let hex_tx = hex_bytes( + let hex_tx = Vec::::from_hex( "010000000001000100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000" ).unwrap(); let tx: Transaction = deserialize(&hex_tx).expect("deserialize tx"); @@ -731,7 +730,7 @@ mod tests { #[test] fn test_ntxid() { - let hex_tx = hex_bytes("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let mut tx: Transaction = deserialize(&hex_tx).unwrap(); let old_ntxid = tx.ntxid(); @@ -747,7 +746,7 @@ mod tests { #[test] fn test_txid() { // segwit tx from Liquid integration tests, txid/hash from Core decoderawtransaction - let hex_tx = hex_bytes( + let hex_tx = Vec::::from_hex( "01000000000102ff34f95a672bb6a4f6ff4a7e90fa8c7b3be7e70ffc39bc99be3bda67942e836c00000000\ 23220020cde476664d3fa347b8d54ef3aee33dcb686a65ced2b5207cbf4ec5eda6b9b46e4f414d4c934ad8\ 1d330314e888888e3bd22c7dde8aac2ca9227b30d7c40093248af7812201000000232200200af6f6a071a6\ @@ -784,7 +783,7 @@ mod tests { assert_eq!(tx.get_weight(), 2718); // non-segwit tx from my mempool - let hex_tx = hex_bytes( + let hex_tx = Vec::::from_hex( "01000000010c7196428403d8b0c88fcb3ee8d64f56f55c8973c9ab7dd106bb4f3527f5888d000000006a47\ 30440220503a696f55f2c00eee2ac5e65b17767cd88ed04866b5637d3c1d5d996a70656d02202c9aff698f\ 343abb6d176704beda63fcdec503133ea4f6a5216b7f925fa9910c0121024d89b5a13d6521388969209df2\ @@ -801,15 +800,15 @@ mod tests { #[test] #[cfg(feature = "serde")] fn test_txn_encode_decode() { - let hex_tx = hex_bytes("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap(); serde_round_trip!(tx); } fn run_test_sighash(tx: &str, script: &str, input_index: usize, hash_type: i32, expected_result: &str) { - let tx: Transaction = deserialize(&hex_bytes(tx).unwrap()[..]).unwrap(); - let script = Script::from(hex_bytes(script).unwrap()); - let mut raw_expected = hex_bytes(expected_result).unwrap(); + let tx: Transaction = deserialize(&Vec::::from_hex(tx).unwrap()[..]).unwrap(); + let script = Script::from(Vec::::from_hex(script).unwrap()); + let mut raw_expected = Vec::::from_hex(expected_result).unwrap(); raw_expected.reverse(); let expected_result = sha256d::Hash::from_slice(&raw_expected[..]).unwrap(); @@ -822,7 +821,7 @@ mod tests { #[test] #[cfg(feature = "serde")] fn test_segwit_tx_decode() { - let hex_tx = hex_bytes("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let hex_tx = Vec::::from_hex("010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a39837040120000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); let tx: Transaction = deserialize(&hex_tx).unwrap(); assert_eq!(tx.get_weight(), 780); serde_round_trip!(tx); diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index af129c09..cbacf401 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -86,8 +86,6 @@ pub enum Error { UnsupportedSegwitFlag(u8), /// Unrecognized network command UnrecognizedNetworkCommand(String), - /// Unexpected hex digit - UnexpectedHexDigit(char), } impl fmt::Display for Error { @@ -109,7 +107,6 @@ impl fmt::Display for Error { "unsupported segwit version: {}", swflag), Error::UnrecognizedNetworkCommand(ref nwcmd) => write!(f, "unrecognized network command: {}", nwcmd), - Error::UnexpectedHexDigit(ref d) => write!(f, "unexpected hex digit: {}", d), } } } @@ -127,8 +124,7 @@ impl error::Error for Error { | Error::UnknownNetworkMagic(..) | Error::ParseFailed(..) | Error::UnsupportedSegwitFlag(..) - | Error::UnrecognizedNetworkCommand(..) - | Error::UnexpectedHexDigit(..) => None, + | Error::UnrecognizedNetworkCommand(..) => None, } } diff --git a/src/util/bip143.rs b/src/util/bip143.rs index cdf794de..397084fa 100644 --- a/src/util/bip143.rs +++ b/src/util/bip143.rs @@ -105,9 +105,9 @@ mod tests { use blockdata::transaction::Transaction; use consensus::encode::deserialize; use network::constants::Network; - use util::misc::hex_bytes; use util::address::Address; use util::key::PublicKey; + use hashes::hex::FromHex; use hex; use super::*; @@ -122,7 +122,7 @@ mod tests { #[test] fn bip143_p2wpkh() { let tx = deserialize::( - &hex_bytes( + &Vec::::from_hex( "0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f000000\ 0000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a01000000\ 00ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093\ @@ -160,7 +160,7 @@ mod tests { #[test] fn bip143_p2wpkh_nested_in_p2sh() { let tx = deserialize::( - &hex_bytes( + &Vec::::from_hex( "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000\ 0000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac00\ 08af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000", @@ -197,7 +197,7 @@ mod tests { #[test] fn bip143_p2wsh_nested_in_p2sh() { let tx = deserialize::( - &hex_bytes( + &Vec::::from_hex( "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\ ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\ 05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000").unwrap()[..], diff --git a/src/util/misc.rs b/src/util/misc.rs index 784994e0..f5c2a545 100644 --- a/src/util/misc.rs +++ b/src/util/misc.rs @@ -22,59 +22,6 @@ use consensus::encode; static MSG_SIGN_PREFIX: &'static [u8] = b"\x18Bitcoin Signed Message:\n"; -/// Helper function to convert hex nibble characters to their respective value -#[inline] -fn hex_val(c: u8) -> Result { - let res = match c { - b'0' ... b'9' => c - '0' as u8, - b'a' ... b'f' => c - 'a' as u8 + 10, - b'A' ... b'F' => c - 'A' as u8 + 10, - _ => return Err(encode::Error::UnexpectedHexDigit(c as char)), - }; - Ok(res) -} - -/// Convert a hexadecimal-encoded string to its corresponding bytes -pub fn hex_bytes(data: &str) -> Result, encode::Error> { - // This code is optimized to be as fast as possible without using unsafe or platform specific - // features. If you want to refactor it please make sure you don't introduce performance - // regressions (run the benchmark with `cargo bench --features unstable`). - - // If the hex string has an uneven length fail early - if data.len() % 2 != 0 { - return Err(encode::Error::ParseFailed("hexstring of odd length")); - } - - // Preallocate the uninitialized memory for the byte array - let mut res = Vec::with_capacity(data.len() / 2); - - let mut hex_it = data.bytes(); - loop { - // Get most significant nibble of current byte or end iteration - let msn = match hex_it.next() { - None => break, - Some(x) => x, - }; - - // Get least significant nibble of current byte - let lsn = match hex_it.next() { - None => unreachable!("len % 2 == 0"), - Some(x) => x, - }; - - // Convert bytes representing characters to their represented value and combine lsn and msn. - // The and_then and map are crucial for performance, in comparison to using ? and then - // using the results of that for the calculation it's nearly twice as fast. Using bit - // shifting and or instead of multiply and add on the other hand doesn't show a significant - // increase in performance. - match hex_val(msn).and_then(|msn_val| hex_val(lsn).map(|lsn_val| msn_val * 16 + lsn_val)) { - Ok(x) => res.push(x), - Err(e) => return Err(e), - } - } - Ok(res) -} - /// Search for `needle` in the vector `haystack` and remove every /// instance of it, returning the number of instances removed. /// Loops through the vector opcode by opcode, skipping pushed data. @@ -122,61 +69,10 @@ pub fn signed_msg_hash(msg: &str) -> sha256d::Hash { ) } -#[cfg(all(test, feature="unstable"))] -mod benches { - use secp256k1::rand::{Rng, thread_rng}; - use secp256k1::rand::distributions::Standard; - use super::hex_bytes; - use test::Bencher; - - fn join, IT: AsRef>(iter: I, expected_len: usize) -> String { - let mut res = String::with_capacity(expected_len); - for s in iter { - res.push_str(s.as_ref()); - } - res - } - - fn bench_from_hex(b: &mut Bencher, data_size: usize) { - let data_bytes = thread_rng() - .sample_iter(&Standard) - .take(data_size) - .collect::>(); - let data = join(data_bytes.iter().map(|x| format!("{:02x}", x)), data_size * 2); - - assert_eq!(hex_bytes(&data).unwrap(), data_bytes); - - b.iter(|| { - hex_bytes(&data).unwrap() - }) - } - - #[bench] - fn from_hex_16_bytes(b: &mut Bencher) { - bench_from_hex(b, 16); - } - - #[bench] - fn from_hex_64_bytes(b: &mut Bencher) { - bench_from_hex(b, 64); - } - - #[bench] - fn from_hex_256_bytes(b: &mut Bencher) { - bench_from_hex(b, 256); - } - - #[bench] - fn from_hex_4m_bytes(b: &mut Bencher) { - bench_from_hex(b, 1024 * 1024 * 4); - } -} - #[cfg(test)] mod tests { use hashes::hex::ToHex; use super::script_find_and_remove; - use super::hex_bytes; use super::signed_msg_hash; #[test] @@ -218,14 +114,6 @@ mod tests { assert_eq!(s, vec![33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 33, 3, 132, 121, 160, 250, 153, 140, 211, 82, 89, 162, 239, 10, 122, 92, 104, 102, 44, 20, 116, 248, 140, 203, 109, 8, 167, 103, 123, 190, 199, 242, 32, 65, 173, 81]); } - #[test] - fn test_hex_bytes() { - assert_eq!(&hex_bytes("abcd").unwrap(), &[171u8, 205]); - assert!(hex_bytes("abcde").is_err()); - assert!(hex_bytes("aBcDeF").is_ok()); - assert!(hex_bytes("aBcD4eFL").is_err()); - } - #[test] fn test_signed_msg_hash() { let hash = signed_msg_hash("test"); From 617c07d7960c5cd6c0335e812d7426e7025c0140 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Mon, 9 Sep 2019 14:05:54 +0100 Subject: [PATCH 7/7] Remove encode::Error::ByteOrder Functions from the byteorder crate only return downstream io errors on io calls. --- src/consensus/encode.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index cbacf401..b409c88b 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -51,8 +51,6 @@ use network::address::Address; pub enum Error { /// And I/O error Io(io::Error), - /// Error from the `byteorder` crate - ByteOrder(io::Error), /// PSBT-related error Psbt(psbt::Error), /// Network magic was not expected @@ -92,7 +90,6 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Io(ref e) => write!(f, "I/O error: {}", e), - Error::ByteOrder(ref e) => write!(f, "byteorder error: {}", e), Error::Psbt(ref e) => write!(f, "PSBT error: {}", e), Error::UnexpectedNetworkMagic { expected: ref e, actual: ref a } => write!(f, "unexpected network magic: expected {}, actual {}", e, a), @@ -115,7 +112,6 @@ impl error::Error for Error { fn cause(&self) -> Option<&error::Error> { match *self { Error::Io(ref e) => Some(e), - Error::ByteOrder(ref e) => Some(e), Error::Psbt(ref e) => Some(e), Error::UnexpectedNetworkMagic { .. } | Error::OversizedVectorAllocation { .. }