Merge rust-bitcoin/rust-bitcoin#1531: Remove `ToHex`
1b0988833a
Remove `ToHex` (Martin Habovstiak) Pull request description: The `ToHex` trait was replaced by either simple `Display`/`LowerHex` where appropriate or `DisplayHex` from `bitcoin_internals` which is faster. This change replaces the usages and removes the trait. ACKs for top commit: tcharding: ACK1b0988833a
apoelstra: ACK1b0988833a
Tree-SHA512: a1b508e24ac247a0692c01b7cb1e7fa8f23fbfa3d6c3d5dfe669eec01f940a96c3f88508cb0b2e3529eebd9cb51e7d41435dbd5f4cbaf3bc14b9c7e7d790308b
This commit is contained in:
commit
1f7affbc95
|
@ -885,7 +885,6 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
use crate::crypto::key::PublicKey;
|
||||
use crate::hashes::hex::ToHex;
|
||||
use crate::internal_macros::{hex, hex_into, hex_script};
|
||||
use crate::network::constants::Network::{Bitcoin, Testnet};
|
||||
|
||||
|
@ -1078,7 +1077,7 @@ mod tests {
|
|||
];
|
||||
for vector in &valid_vectors {
|
||||
let addr: Address = vector.0.parse().unwrap();
|
||||
assert_eq!(&addr.script_pubkey().as_bytes().to_hex(), vector.1);
|
||||
assert_eq!(&addr.script_pubkey().to_hex_string(), vector.1);
|
||||
roundtrips(&addr);
|
||||
}
|
||||
|
||||
|
|
|
@ -192,7 +192,6 @@ impl ChainHash {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::hashes::hex::ToHex;
|
||||
use crate::network::constants::Network;
|
||||
use crate::consensus::encode::serialize;
|
||||
use crate::blockdata::locktime::absolute;
|
||||
|
@ -216,7 +215,7 @@ mod test {
|
|||
assert_eq!(gen.output[0].value, 50 * COIN_VALUE);
|
||||
assert_eq!(gen.lock_time, absolute::LockTime::ZERO);
|
||||
|
||||
assert_eq!(gen.wtxid().to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
assert_eq!(gen.wtxid().to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -225,12 +224,12 @@ mod test {
|
|||
|
||||
assert_eq!(gen.header.version, block::Version::ONE);
|
||||
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
||||
assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
assert_eq!(gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
|
||||
assert_eq!(gen.header.time, 1231006505);
|
||||
assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff));
|
||||
assert_eq!(gen.header.nonce, 2083236893);
|
||||
assert_eq!(gen.header.block_hash().to_hex(), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
assert_eq!(gen.header.block_hash().to_string(), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -238,11 +237,11 @@ mod test {
|
|||
let gen = genesis_block(Network::Testnet);
|
||||
assert_eq!(gen.header.version, block::Version::ONE);
|
||||
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
||||
assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
assert_eq!(gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
assert_eq!(gen.header.time, 1296688602);
|
||||
assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff));
|
||||
assert_eq!(gen.header.nonce, 414098458);
|
||||
assert_eq!(gen.header.block_hash().to_hex(), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
|
||||
assert_eq!(gen.header.block_hash().to_string(), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -250,11 +249,11 @@ mod test {
|
|||
let gen = genesis_block(Network::Signet);
|
||||
assert_eq!(gen.header.version, block::Version::ONE);
|
||||
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
|
||||
assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
assert_eq!(gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
|
||||
assert_eq!(gen.header.time, 1598918400);
|
||||
assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1e0377ae));
|
||||
assert_eq!(gen.header.nonce, 52613770);
|
||||
assert_eq!(gen.header.block_hash().to_hex(), "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6");
|
||||
assert_eq!(gen.header.block_hash().to_string(), "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6");
|
||||
}
|
||||
|
||||
// The *_chain_hash tests are sanity/regression tests, they verify that the const byte array
|
||||
|
@ -304,7 +303,7 @@ mod test {
|
|||
// Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md
|
||||
#[test]
|
||||
fn mainnet_chain_hash_test_vector() {
|
||||
let got = ChainHash::using_genesis_block(Network::Bitcoin).to_hex();
|
||||
let got = ChainHash::using_genesis_block(Network::Bitcoin).to_string();
|
||||
let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000";
|
||||
assert_eq!(got, want);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ use crate::prelude::*;
|
|||
use alloc::rc::Rc;
|
||||
use alloc::sync::Arc;
|
||||
use bitcoin_internals::debug_from_display;
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
use crate::io;
|
||||
use core::cmp::Ordering;
|
||||
use core::convert::TryFrom;
|
||||
|
@ -61,7 +62,6 @@ use core::{fmt, default::Default};
|
|||
use core::ops::{Deref, DerefMut, Index, Range, RangeFull, RangeFrom, RangeTo, RangeInclusive, RangeToInclusive};
|
||||
#[cfg(feature = "rust_v_1_53")]
|
||||
use core::ops::Bound;
|
||||
use bitcoin_hashes::hex::ToHex;
|
||||
|
||||
#[cfg(feature = "serde")] use serde;
|
||||
|
||||
|
@ -485,6 +485,15 @@ impl Script {
|
|||
buf
|
||||
}
|
||||
|
||||
/// Formats the script as lower-case hex.
|
||||
///
|
||||
/// This is a more convenient and performant way to write `format!("{:x}", script)`.
|
||||
/// For better performance you should generally prefer displaying the script but if `String` is
|
||||
/// required (this is common in tests) this method is can be used.
|
||||
pub fn to_hex_string(&self) -> String {
|
||||
self.as_bytes().to_lower_hex_string()
|
||||
}
|
||||
|
||||
/// Returns the first opcode of the script (if there is any).
|
||||
pub fn first_opcode(&self) -> Option<opcodes::All> {
|
||||
self.as_bytes().first().copied().map(From::from)
|
||||
|
@ -553,13 +562,6 @@ impl<'a> From<&'a Script> for Rc<Script> {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToHex for Script {
|
||||
#[inline]
|
||||
fn to_hex(&self) -> String {
|
||||
self.0.to_hex()
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over bytes of a script
|
||||
pub struct Bytes<'a>(core::iter::Copied<core::slice::Iter<'a, u8>>);
|
||||
|
||||
|
@ -662,19 +664,13 @@ impl fmt::Display for Script {
|
|||
|
||||
impl fmt::LowerHex for Script {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for ch in self.bytes() {
|
||||
write!(f, "{:02x}", ch)?;
|
||||
}
|
||||
Ok(())
|
||||
fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::UpperHex for Script {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
for ch in self.bytes() {
|
||||
write!(f, "{:02X}", ch)?;
|
||||
}
|
||||
Ok(())
|
||||
fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1873,7 +1869,7 @@ impl serde::Serialize for Script {
|
|||
S: serde::Serializer,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
serializer.serialize_str(&self.to_hex())
|
||||
serializer.collect_str(&format_args!("{:x}", self))
|
||||
} else {
|
||||
serializer.serialize_bytes(self.as_bytes())
|
||||
}
|
||||
|
@ -2011,7 +2007,7 @@ mod test {
|
|||
use super::*;
|
||||
use super::write_scriptint;
|
||||
|
||||
use crate::hashes::hex::{FromHex, ToHex};
|
||||
use crate::hashes::hex::FromHex;
|
||||
use crate::consensus::encode::{deserialize, serialize};
|
||||
use crate::blockdata::opcodes;
|
||||
use crate::crypto::key::PublicKey;
|
||||
|
@ -2209,7 +2205,7 @@ mod test {
|
|||
.push_opcode(OP_EQUALVERIFY)
|
||||
.push_opcode(OP_CHECKSIG)
|
||||
.into_script();
|
||||
assert_eq!(script.to_hex(), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac");
|
||||
assert_eq!(script.to_hex_string(), "76a91416e1ae70ff0fa102905d4af297f6912bda6cce1988ac");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2241,7 +2237,7 @@ mod test {
|
|||
let data = Vec::<u8>::from_hex("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a").unwrap();
|
||||
let op_return = ScriptBuf::new_op_return(&data);
|
||||
assert!(op_return.is_op_return());
|
||||
assert_eq!(op_return.to_hex(), "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
|
||||
assert_eq!(op_return.to_hex_string(), "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2249,71 +2245,71 @@ mod test {
|
|||
let simple = Builder::new()
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(simple.to_hex(), "69");
|
||||
assert_eq!(simple.to_hex_string(), "69");
|
||||
let simple2 = Builder::from(vec![])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(simple2.to_hex(), "69");
|
||||
assert_eq!(simple2.to_hex_string(), "69");
|
||||
|
||||
let nonverify = Builder::new()
|
||||
.push_verify()
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(nonverify.to_hex(), "6969");
|
||||
assert_eq!(nonverify.to_hex_string(), "6969");
|
||||
let nonverify2 = Builder::from(vec![0x69])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(nonverify2.to_hex(), "6969");
|
||||
assert_eq!(nonverify2.to_hex_string(), "6969");
|
||||
|
||||
let equal = Builder::new()
|
||||
.push_opcode(OP_EQUAL)
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(equal.to_hex(), "88");
|
||||
assert_eq!(equal.to_hex_string(), "88");
|
||||
let equal2 = Builder::from(vec![0x87])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(equal2.to_hex(), "88");
|
||||
assert_eq!(equal2.to_hex_string(), "88");
|
||||
|
||||
let numequal = Builder::new()
|
||||
.push_opcode(OP_NUMEQUAL)
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(numequal.to_hex(), "9d");
|
||||
assert_eq!(numequal.to_hex_string(), "9d");
|
||||
let numequal2 = Builder::from(vec![0x9c])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(numequal2.to_hex(), "9d");
|
||||
assert_eq!(numequal2.to_hex_string(), "9d");
|
||||
|
||||
let checksig = Builder::new()
|
||||
.push_opcode(OP_CHECKSIG)
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(checksig.to_hex(), "ad");
|
||||
assert_eq!(checksig.to_hex_string(), "ad");
|
||||
let checksig2 = Builder::from(vec![0xac])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(checksig2.to_hex(), "ad");
|
||||
assert_eq!(checksig2.to_hex_string(), "ad");
|
||||
|
||||
let checkmultisig = Builder::new()
|
||||
.push_opcode(OP_CHECKMULTISIG)
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(checkmultisig.to_hex(), "af");
|
||||
assert_eq!(checkmultisig.to_hex_string(), "af");
|
||||
let checkmultisig2 = Builder::from(vec![0xae])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(checkmultisig2.to_hex(), "af");
|
||||
assert_eq!(checkmultisig2.to_hex_string(), "af");
|
||||
|
||||
let trick_slice = Builder::new()
|
||||
.push_slice(&[0xae]) // OP_CHECKMULTISIG
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(trick_slice.to_hex(), "01ae69");
|
||||
assert_eq!(trick_slice.to_hex_string(), "01ae69");
|
||||
let trick_slice2 = Builder::from(vec![0x01, 0xae])
|
||||
.push_verify()
|
||||
.into_script();
|
||||
assert_eq!(trick_slice2.to_hex(), "01ae69");
|
||||
assert_eq!(trick_slice2.to_hex_string(), "01ae69");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2361,10 +2357,10 @@ mod test {
|
|||
#[test]
|
||||
fn script_hashes() {
|
||||
let script = hex_script!("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac");
|
||||
assert_eq!(script.script_hash().to_hex(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea");
|
||||
assert_eq!(script.wscript_hash().to_hex(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324");
|
||||
assert_eq!(script.script_hash().to_string(), "8292bcfbef1884f73c813dfe9c82fd7e814291ea");
|
||||
assert_eq!(script.wscript_hash().to_string(), "3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324");
|
||||
assert_eq!(
|
||||
hex_script!("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac").tapscript_leaf_hash().to_hex(),
|
||||
hex_script!("20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac").tapscript_leaf_hash().to_string(),
|
||||
"5b75adecf53548f3ec6ad7d78383bf84cc57b55a3127c72b9a2481752dd88b21"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -388,7 +388,6 @@ impl serde::Serialize for Witness {
|
|||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use crate::hashes::hex::ToHex;
|
||||
use serde::ser::SerializeSeq;
|
||||
|
||||
let human_readable = serializer.is_human_readable();
|
||||
|
@ -396,7 +395,7 @@ impl serde::Serialize for Witness {
|
|||
|
||||
for elem in self.iter() {
|
||||
if human_readable {
|
||||
seq.serialize_element(&elem.to_hex())?;
|
||||
seq.serialize_element(&crate::serde_utils::SerializeBytesAsHex(elem))?;
|
||||
} else {
|
||||
seq.serialize_element(&elem)?;
|
||||
}
|
||||
|
@ -490,8 +489,8 @@ impl From<Vec<&[u8]>> for Witness {
|
|||
mod test {
|
||||
use super::*;
|
||||
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
use crate::consensus::{deserialize, serialize};
|
||||
use crate::hashes::hex::ToHex;
|
||||
use crate::internal_macros::hex;
|
||||
use crate::Transaction;
|
||||
use crate::secp256k1::ecdsa;
|
||||
|
@ -654,15 +653,15 @@ mod test {
|
|||
|
||||
let expected_wit = ["304502210084622878c94f4c356ce49c8e33a063ec90f6ee9c0208540888cfab056cd1fca9022014e8dbfdfa46d318c6887afd92dcfa54510e057565e091d64d2ee3a66488f82c01", "026e181ffb98ebfe5a64c983073398ea4bcd1548e7b971b4c175346a25a1c12e95"];
|
||||
for (i, wit_el) in tx.input[0].witness.iter().enumerate() {
|
||||
assert_eq!(expected_wit[i], wit_el.to_hex());
|
||||
assert_eq!(expected_wit[i], wit_el.to_lower_hex_string());
|
||||
}
|
||||
assert_eq!(expected_wit[1], tx.input[0].witness.last().unwrap().to_hex());
|
||||
assert_eq!(expected_wit[0], tx.input[0].witness.second_to_last().unwrap().to_hex());
|
||||
assert_eq!(expected_wit[0], tx.input[0].witness.nth(0).unwrap().to_hex());
|
||||
assert_eq!(expected_wit[1], tx.input[0].witness.nth(1).unwrap().to_hex());
|
||||
assert_eq!(expected_wit[1], tx.input[0].witness.last().unwrap().to_lower_hex_string());
|
||||
assert_eq!(expected_wit[0], tx.input[0].witness.second_to_last().unwrap().to_lower_hex_string());
|
||||
assert_eq!(expected_wit[0], tx.input[0].witness.nth(0).unwrap().to_lower_hex_string());
|
||||
assert_eq!(expected_wit[1], tx.input[0].witness.nth(1).unwrap().to_lower_hex_string());
|
||||
assert_eq!(None, tx.input[0].witness.nth(2));
|
||||
assert_eq!(expected_wit[0], tx.input[0].witness[0].to_hex());
|
||||
assert_eq!(expected_wit[1], tx.input[0].witness[1].to_hex());
|
||||
assert_eq!(expected_wit[0], tx.input[0].witness[0].to_lower_hex_string());
|
||||
assert_eq!(expected_wit[1], tx.input[0].witness[1].to_lower_hex_string());
|
||||
|
||||
let tx_bytes_back = serialize(&tx);
|
||||
assert_eq!(tx_bytes_back, tx_bytes);
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::prelude::*;
|
|||
use core::{fmt, mem, u32, convert::From};
|
||||
|
||||
use bitcoin_internals::write_err;
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
|
||||
use crate::hashes::{sha256d, Hash, sha256};
|
||||
use crate::hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader};
|
||||
|
@ -29,7 +30,6 @@ use crate::io::{self, Cursor, Read};
|
|||
use crate::psbt;
|
||||
use crate::bip152::{ShortId, PrefilledTransaction};
|
||||
use crate::taproot::TapLeafHash;
|
||||
use crate::hashes::hex::ToHex;
|
||||
|
||||
use crate::blockdata::transaction::{TxOut, Transaction, TxIn};
|
||||
#[cfg(feature = "std")]
|
||||
|
@ -73,7 +73,7 @@ impl fmt::Display for Error {
|
|||
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()),
|
||||
"invalid checksum: expected {:x}, actual {:x}", e.as_hex(), a.as_hex()),
|
||||
Error::NonMinimalVarInt => write!(f, "non-minimal varint"),
|
||||
Error::ParseFailed(ref s) => write!(f, "parse failed: {}", s),
|
||||
Error::UnsupportedSegwitFlag(ref swflag) => write!(f,
|
||||
|
@ -124,7 +124,7 @@ pub fn serialize<T: Encodable + ?Sized>(data: &T) -> Vec<u8> {
|
|||
|
||||
/// Encodes an object into a hex-encoded string.
|
||||
pub fn serialize_hex<T: Encodable + ?Sized>(data: &T) -> String {
|
||||
serialize(data)[..].to_hex()
|
||||
serialize(data).to_lower_hex_string()
|
||||
}
|
||||
|
||||
/// Deserializes an object from a vector, will error if said deserialization
|
||||
|
|
|
@ -9,6 +9,7 @@ use core::str::FromStr;
|
|||
use core::{fmt, iter};
|
||||
|
||||
use bitcoin_internals::write_err;
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
use secp256k1;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
@ -58,8 +59,8 @@ impl Signature {
|
|||
|
||||
impl fmt::Display for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
hex::format_hex(&self.sig.serialize_der(), f)?;
|
||||
hex::format_hex(&[self.hash_ty as u8], f)
|
||||
fmt::LowerHex::fmt(&self.sig.serialize_der().as_hex(), f)?;
|
||||
fmt::LowerHex::fmt(&[self.hash_ty as u8].as_hex(), f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -548,7 +548,7 @@ mod tests {
|
|||
use super::{PrivateKey, PublicKey, SortKey};
|
||||
use secp256k1::Secp256k1;
|
||||
use std::str::FromStr;
|
||||
use crate::hashes::hex::{FromHex, ToHex};
|
||||
use crate::hashes::hex::FromHex;
|
||||
use crate::network::constants::Network::Testnet;
|
||||
use crate::network::constants::Network::Bitcoin;
|
||||
use crate::address::Address;
|
||||
|
@ -593,15 +593,15 @@ mod tests {
|
|||
fn test_pubkey_hash() {
|
||||
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
|
||||
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
||||
assert_eq!(pk.pubkey_hash().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||
assert_eq!(upk.pubkey_hash().to_hex(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
|
||||
assert_eq!(pk.pubkey_hash().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||
assert_eq!(upk.pubkey_hash().to_string(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wpubkey_hash() {
|
||||
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
|
||||
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
||||
assert_eq!(pk.wpubkey_hash().unwrap().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||
assert_eq!(pk.wpubkey_hash().unwrap().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||
assert_eq!(upk.wpubkey_hash(), None);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,8 @@ mod test_macros {
|
|||
|
||||
/// Implements several traits for byte-based newtypes.
|
||||
/// Implements:
|
||||
/// - core::fmt::LowerHex (implies hashes::hex::ToHex)
|
||||
/// - core::fmt::LowerHex
|
||||
/// - core::fmt::UpperHex
|
||||
/// - core::fmt::Display
|
||||
/// - core::str::FromStr
|
||||
/// - hashes::hex::FromHex
|
||||
|
@ -134,10 +135,15 @@ macro_rules! impl_bytes_newtype {
|
|||
|
||||
impl core::fmt::LowerHex for $t {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
for &ch in self.0.iter() {
|
||||
write!(f, "{:02x}", ch)?;
|
||||
}
|
||||
Ok(())
|
||||
use bitcoin_internals::hex::{Case, display};
|
||||
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};
|
||||
display::fmt_hex_exact!(f, $len, &self.0, Case::Upper)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +190,7 @@ macro_rules! impl_bytes_newtype {
|
|||
impl $crate::serde::Serialize for $t {
|
||||
fn serialize<S: $crate::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
|
||||
if s.is_human_readable() {
|
||||
s.serialize_str(&$crate::hashes::hex::ToHex::to_hex(self))
|
||||
s.collect_str(self)
|
||||
} else {
|
||||
s.serialize_bytes(&self[..])
|
||||
}
|
||||
|
|
|
@ -499,6 +499,7 @@ impl Decodable for MerkleBlock {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
#[cfg(feature = "rand-std")]
|
||||
use secp256k1::rand::prelude::*;
|
||||
|
||||
|
@ -506,7 +507,7 @@ mod tests {
|
|||
use crate::consensus::encode::{deserialize, serialize};
|
||||
#[cfg(feature = "rand-std")]
|
||||
use crate::hash_types::TxMerkleNode;
|
||||
use crate::hashes::hex::{FromHex, ToHex};
|
||||
use crate::hashes::hex::FromHex;
|
||||
#[cfg(feature = "rand-std")]
|
||||
use crate::hashes::Hash;
|
||||
use crate::internal_macros::hex;
|
||||
|
@ -656,7 +657,7 @@ mod tests {
|
|||
mb.txn.extract_matches(&mut vec![], &mut vec![]).unwrap()
|
||||
);
|
||||
// Serialize again and check that it matches the original bytes
|
||||
assert_eq!(MB_HEX, serialize(&mb).to_hex().as_str());
|
||||
assert_eq!(MB_HEX, serialize(&mb).to_lower_hex_string().as_str());
|
||||
}
|
||||
|
||||
/// Create a CMerkleBlock using a list of txids which will be found in the
|
||||
|
|
|
@ -774,21 +774,16 @@ impl fmt::Debug for U256 {
|
|||
}
|
||||
|
||||
macro_rules! impl_hex {
|
||||
($hex:ident, $fmt:literal) => {
|
||||
($hex:ident, $case:expr) => {
|
||||
impl $hex for U256 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if f.alternate() {
|
||||
write!(f, "0x")?;
|
||||
}
|
||||
write!(f, $fmt, self.0)?;
|
||||
write!(f, $fmt, self.1)?;
|
||||
Ok(())
|
||||
bitcoin_internals::hex::display::fmt_hex_exact!(f, 32, &self.to_be_bytes(), $case)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
impl_hex!(LowerHex, "{:032x}");
|
||||
impl_hex!(UpperHex, "{:032X}");
|
||||
impl_hex!(LowerHex, bitcoin_internals::hex::Case::Lower);
|
||||
impl_hex!(UpperHex, bitcoin_internals::hex::Case::Upper);
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||
|
@ -797,12 +792,17 @@ impl crate::serde::Serialize for U256 {
|
|||
where
|
||||
S: crate::serde::Serializer,
|
||||
{
|
||||
use crate::hashes::hex::ToHex;
|
||||
let bytes = self.to_be_bytes();
|
||||
struct DisplayHex(U256);
|
||||
|
||||
impl fmt::Display for DisplayHex {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}", self.0) }
|
||||
}
|
||||
|
||||
if serializer.is_human_readable() {
|
||||
// TODO: fast hex encoding.
|
||||
serializer.serialize_str(&bytes.to_hex())
|
||||
serializer.collect_str(&DisplayHex(*self))
|
||||
} else {
|
||||
let bytes = self.to_be_bytes();
|
||||
serializer.serialize_bytes(&bytes)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
//! <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki>.
|
||||
//!
|
||||
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
use crate::prelude::*;
|
||||
use core::fmt;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
use crate::io::{self, Cursor};
|
||||
use crate::consensus::encode::{self, ReadExt, WriteExt, Decodable, Encodable, VarInt, serialize, deserialize, MAX_VEC_SIZE};
|
||||
use crate::hashes::hex;
|
||||
use crate::psbt::Error;
|
||||
|
||||
use super::serialize::{Serialize, Deserialize};
|
||||
|
@ -66,8 +66,7 @@ pub struct ProprietaryKey<Subtype=ProprietaryType> where Subtype: Copy + From<u8
|
|||
|
||||
impl fmt::Display for Key {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "type: {:#x}, key: ", self.type_value)?;
|
||||
hex::format_hex(&self.key[..], f)
|
||||
write!(f, "type: {:#x}, key: {:x}", self.type_value, self.key.as_hex())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ pub(crate) trait Deserialize: Sized {
|
|||
impl PartiallySignedTransaction {
|
||||
/// Serialize a value as bytes in hex.
|
||||
pub fn serialize_hex(&self) -> String {
|
||||
bitcoin_hashes::hex::ToHex::to_hex(&self.serialize()[..])
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
self.serialize().to_lower_hex_string()
|
||||
}
|
||||
|
||||
/// Serialize as raw binary data
|
||||
|
|
|
@ -5,6 +5,20 @@
|
|||
//! This module is for special serde serializations.
|
||||
//!
|
||||
|
||||
pub(crate) struct SerializeBytesAsHex<'a>(pub(crate) &'a [u8]);
|
||||
|
||||
impl<'a> serde::Serialize for SerializeBytesAsHex<'a> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
|
||||
serializer.collect_str(&format_args!("{:x}", self.0.as_hex()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub mod btreemap_byte_values {
|
||||
//! Module for serialization of BTreeMaps with hex byte values.
|
||||
#![allow(missing_docs)]
|
||||
|
@ -13,7 +27,7 @@ pub mod btreemap_byte_values {
|
|||
|
||||
use serde;
|
||||
|
||||
use crate::hashes::hex::{FromHex, ToHex};
|
||||
use crate::hashes::hex::FromHex;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn serialize<S, T>(v: &BTreeMap<T, Vec<u8>>, s: S) -> Result<S::Ok, S::Error>
|
||||
|
@ -29,7 +43,7 @@ pub mod btreemap_byte_values {
|
|||
} else {
|
||||
let mut map = s.serialize_map(Some(v.len()))?;
|
||||
for (key, value) in v.iter() {
|
||||
map.serialize_entry(key, &value.to_hex())?;
|
||||
map.serialize_entry(key, &super::SerializeBytesAsHex(value))?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
|
@ -237,7 +251,7 @@ pub mod hex_bytes {
|
|||
|
||||
use serde;
|
||||
|
||||
use crate::hashes::hex::{FromHex, ToHex};
|
||||
use crate::hashes::hex::FromHex;
|
||||
|
||||
pub fn serialize<T, S>(bytes: &T, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
@ -248,7 +262,7 @@ pub mod hex_bytes {
|
|||
if !s.is_human_readable() {
|
||||
serde::Serialize::serialize(bytes, s)
|
||||
} else {
|
||||
s.serialize_str(&bytes.as_ref().to_hex())
|
||||
serde::Serialize::serialize(&super::SerializeBytesAsHex(bytes.as_ref()), s)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1387,10 +1387,10 @@ mod tests {
|
|||
})
|
||||
}
|
||||
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
use secp256k1::{self, SecretKey, XOnlyPublicKey};
|
||||
|
||||
use crate::consensus::serde as con_serde;
|
||||
use crate::hashes::hex::ToHex;
|
||||
use crate::taproot::{TapBranchHash, TapTweakHash};
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
|
@ -1551,7 +1551,7 @@ mod tests {
|
|||
|
||||
assert_eq!(expected.internal_pubkey, internal_key);
|
||||
assert_eq!(expected.tweak, tweak);
|
||||
assert_eq!(expected.sig_msg, sig_msg.to_hex());
|
||||
assert_eq!(expected.sig_msg, sig_msg.to_lower_hex_string());
|
||||
assert_eq!(expected.sig_hash, sighash);
|
||||
assert_eq!(expected_hash_ty, hash_ty);
|
||||
assert_eq!(expected_key_spend_sig, key_spend_sig);
|
||||
|
|
|
@ -213,13 +213,12 @@ pub fn signed_msg_hash(msg: &str) -> sha256d::Hash {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::hashes::hex::ToHex;
|
||||
|
||||
#[test]
|
||||
fn test_signed_msg_hash() {
|
||||
let hash = signed_msg_hash("test");
|
||||
assert_eq!(
|
||||
hash.to_hex(),
|
||||
hash.to_string(),
|
||||
"a6f87fe6d58a032c320ff8d1541656f0282c2c7bfcc69d61af4c8e8ed528e49c"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1094,11 +1094,12 @@ impl std::error::Error for TaprootError {
|
|||
mod test {
|
||||
use core::str::FromStr;
|
||||
|
||||
use bitcoin_internals::hex::display::DisplayHex;
|
||||
use secp256k1::{VerifyOnly, XOnlyPublicKey};
|
||||
|
||||
use super::*;
|
||||
use crate::crypto::schnorr::TapTweak;
|
||||
use crate::hashes::hex::{FromHex, ToHex};
|
||||
use crate::hashes::hex::FromHex;
|
||||
use crate::hashes::sha256t::Tag;
|
||||
use crate::hashes::{sha256, Hash, HashEngine};
|
||||
use crate::{Address, Network};
|
||||
|
@ -1149,19 +1150,19 @@ mod test {
|
|||
// CHashWriter writer = HasherTapLeaf;
|
||||
// writer.GetSHA256().GetHex()
|
||||
assert_eq!(
|
||||
TapLeafHash::from_engine(TapLeafTag::engine()).to_hex(),
|
||||
TapLeafHash::from_engine(TapLeafTag::engine()).to_string(),
|
||||
"5212c288a377d1f8164962a5a13429f9ba6a7b84e59776a52c6637df2106facb"
|
||||
);
|
||||
assert_eq!(
|
||||
TapBranchHash::from_engine(TapBranchTag::engine()).to_hex(),
|
||||
TapBranchHash::from_engine(TapBranchTag::engine()).to_string(),
|
||||
"53c373ec4d6f3c53c1f5fb2ff506dcefe1a0ed74874f93fa93c8214cbe9ffddf"
|
||||
);
|
||||
assert_eq!(
|
||||
TapTweakHash::from_engine(TapTweakTag::engine()).to_hex(),
|
||||
TapTweakHash::from_engine(TapTweakTag::engine()).to_string(),
|
||||
"8aa4229474ab0100b2d6f0687f031d1fc9d8eef92a042ad97d279bff456b15e4"
|
||||
);
|
||||
assert_eq!(
|
||||
TapSighashHash::from_engine(TapSighashTag::engine()).to_hex(),
|
||||
TapSighashHash::from_engine(TapSighashTag::engine()).to_string(),
|
||||
"dabc11914abcd8072900042a2681e52f8dba99ce82e224f97b5fdb7cd4b9c803"
|
||||
);
|
||||
|
||||
|
@ -1171,19 +1172,19 @@ mod test {
|
|||
// writer.GetSHA256().GetHex()
|
||||
// Note that Core writes the 0 length prefix when an empty vector is written.
|
||||
assert_eq!(
|
||||
TapLeafHash::hash(&[0]).to_hex(),
|
||||
TapLeafHash::hash(&[0]).to_string(),
|
||||
"ed1382037800c9dd938dd8854f1a8863bcdeb6705069b4b56a66ec22519d5829"
|
||||
);
|
||||
assert_eq!(
|
||||
TapBranchHash::hash(&[0]).to_hex(),
|
||||
TapBranchHash::hash(&[0]).to_string(),
|
||||
"92534b1960c7e6245af7d5fda2588db04aa6d646abc2b588dab2b69e5645eb1d"
|
||||
);
|
||||
assert_eq!(
|
||||
TapTweakHash::hash(&[0]).to_hex(),
|
||||
TapTweakHash::hash(&[0]).to_string(),
|
||||
"cd8737b5e6047fc3f16f03e8b9959e3440e1bdf6dd02f7bb899c352ad490ea1e"
|
||||
);
|
||||
assert_eq!(
|
||||
TapSighashHash::hash(&[0]).to_hex(),
|
||||
TapSighashHash::hash(&[0]).to_string(),
|
||||
"c2fd0de003889a09c4afcf676656a0d8a1fb706313ff7d509afb00c323c010cd"
|
||||
);
|
||||
}
|
||||
|
@ -1199,7 +1200,7 @@ mod test {
|
|||
let script = ScriptBuf::from_hex(script_hex).unwrap();
|
||||
let control_block =
|
||||
ControlBlock::from_slice(&Vec::<u8>::from_hex(control_block_hex).unwrap()).unwrap();
|
||||
assert_eq!(control_block_hex, control_block.serialize().to_hex());
|
||||
assert_eq!(control_block_hex, control_block.serialize().to_lower_hex_string());
|
||||
assert!(control_block.verify_taproot_commitment(secp, out_pk.to_inner(), &script));
|
||||
}
|
||||
|
||||
|
@ -1429,7 +1430,7 @@ mod test {
|
|||
|
||||
let leaf_hash = TapLeafHash::from_script(&script_ver.0, script_ver.1);
|
||||
let ctrl_blk = spend_info.control_block(script_ver).unwrap();
|
||||
assert_eq!(leaf_hash.to_hex(), expected_leaf_hash);
|
||||
assert_eq!(leaf_hash.to_string(), expected_leaf_hash);
|
||||
assert_eq!(ctrl_blk, expected_ctrl_blk);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ edition = "2018"
|
|||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
std = ["internals/alloc"]
|
||||
schemars = ["actual-schemars", "dyn-clone"]
|
||||
# If you disable std, you can still use a Write trait via the core2 feature.
|
||||
# You can also use ToHex via the alloc feature, as it requires Vec/String.
|
||||
# And you can still just disable std by disabling default features, without enabling these two.
|
||||
alloc = ["core2/alloc"]
|
||||
alloc = ["core2/alloc", "internals/alloc"]
|
||||
serde-std = ["serde/std"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -9,7 +9,7 @@ extern crate bitcoin_hashes;
|
|||
#[cfg(feature = "alloc")] use alloc_cortex_m::CortexMHeap;
|
||||
#[cfg(feature = "alloc")] use core::alloc::Layout;
|
||||
#[cfg(feature = "alloc")] use cortex_m::asm;
|
||||
#[cfg(feature = "alloc")] use bitcoin_hashes::hex::ToHex;
|
||||
#[cfg(feature = "alloc")] use alloc::string::ToString;
|
||||
|
||||
use bitcoin_hashes::{sha256, Hash, HashEngine};
|
||||
use core2::io::Write;
|
||||
|
@ -57,7 +57,7 @@ fn check_result(engine: sha256::HashEngine) {
|
|||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
if hash.to_hex() != hash_check.to_hex() {
|
||||
if hash.to_string() != hash_check.to_string() {
|
||||
debug::exit(debug::EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::{hash160, Hash, HashEngine};
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
|
@ -89,7 +89,7 @@ mod tests {
|
|||
let hash = hash160::Hash::hash(&test.input[..]);
|
||||
assert_eq!(hash, hash160::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = hash160::Hash::engine();
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use crate::alloc::{string::String, vec::Vec};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::alloc::format;
|
||||
|
||||
#[cfg(any(test, feature = "std"))]
|
||||
use std::io;
|
||||
|
@ -49,14 +47,6 @@ impl fmt::Display for Error {
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait for objects that can be serialized as hex strings.
|
||||
#[cfg(any(test, feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(test, feature = "std", feature = "alloc"))))]
|
||||
pub trait ToHex {
|
||||
/// Converts to a hexadecimal representation of the object.
|
||||
fn to_hex(&self) -> String;
|
||||
}
|
||||
|
||||
/// Trait for objects that can be deserialized from hex strings.
|
||||
pub trait FromHex: Sized {
|
||||
/// Produces an object from a byte iterator.
|
||||
|
@ -70,15 +60,6 @@ pub trait FromHex: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(test, feature = "std", feature = "alloc"))))]
|
||||
impl<T: fmt::LowerHex> ToHex for T {
|
||||
/// Outputs the hash in hexadecimal form.
|
||||
fn to_hex(&self) -> String {
|
||||
format!("{:x}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash> FromHex for T {
|
||||
fn from_byte_iter<I>(iter: I) -> Result<Self, Error>
|
||||
where
|
||||
|
@ -170,65 +151,8 @@ impl<'a> DoubleEndedIterator for HexIterator<'a> {
|
|||
|
||||
impl<'a> ExactSizeIterator for HexIterator<'a> {}
|
||||
|
||||
/// Outputs hex into an object implementing `fmt::Write`.
|
||||
///
|
||||
/// This is usually more efficient than going through a `String` using [`ToHex`].
|
||||
pub fn format_hex(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let prec = f.precision().unwrap_or(2 * data.len());
|
||||
let width = f.width().unwrap_or(2 * data.len());
|
||||
for _ in (2 * data.len())..width {
|
||||
f.write_str("0")?;
|
||||
}
|
||||
for ch in data.iter().take(prec / 2) {
|
||||
write!(f, "{:02x}", *ch)?;
|
||||
}
|
||||
if prec < 2 * data.len() && prec % 2 == 1 {
|
||||
write!(f, "{:x}", data[prec / 2] / 16)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Outputs hex in reverse order.
|
||||
///
|
||||
/// Used for `sha256d::Hash` whose standard hex encoding has the bytes reversed.
|
||||
pub fn format_hex_reverse(data: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let prec = f.precision().unwrap_or(2 * data.len());
|
||||
let width = f.width().unwrap_or(2 * data.len());
|
||||
for _ in (2 * data.len())..width {
|
||||
f.write_str("0")?;
|
||||
}
|
||||
for ch in data.iter().rev().take(prec / 2) {
|
||||
write!(f, "{:02x}", *ch)?;
|
||||
}
|
||||
if prec < 2 * data.len() && prec % 2 == 1 {
|
||||
write!(f, "{:x}", data[data.len() - 1 - prec / 2] / 16)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(test, feature = "std", feature = "alloc"))))]
|
||||
impl ToHex for [u8] {
|
||||
fn to_hex(&self) -> String {
|
||||
use core::fmt::Write;
|
||||
let mut ret = String::with_capacity(2 * self.len());
|
||||
for ch in self {
|
||||
write!(ret, "{:02x}", ch).expect("writing to string");
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct implementing [`io::Write`] that converts what's written to it into
|
||||
/// a hex String.
|
||||
///
|
||||
/// If you already have the data to be converted in a `Vec<u8>` use [`ToHex`]
|
||||
/// but if you have an encodable object, by using this you avoid the
|
||||
/// serialization to `Vec<u8>` by going directly to `String`.
|
||||
///
|
||||
/// Note that to achieve better perfomance than [`ToHex`] the struct must be
|
||||
/// created with the right `capacity` of the final hex string so that the inner
|
||||
/// `String` doesn't re-allocate.
|
||||
#[cfg(any(test, feature = "std", feature = "alloc"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(test, feature = "std", feature = "alloc"))))]
|
||||
pub struct HexWriter(String);
|
||||
|
@ -319,8 +243,9 @@ impl_fromhex_array!(512);
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use internals::hex::exts::DisplayHex;
|
||||
|
||||
use core::fmt;
|
||||
use std::io::Write;
|
||||
|
||||
#[test]
|
||||
|
@ -331,86 +256,20 @@ mod tests {
|
|||
|
||||
let parse: Vec<u8> = FromHex::from_hex(expected).expect("parse lowercase string");
|
||||
assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
|
||||
let ser = parse.to_hex();
|
||||
let ser = parse.to_lower_hex_string();
|
||||
assert_eq!(ser, expected);
|
||||
|
||||
let parse: Vec<u8> = FromHex::from_hex(expected_up).expect("parse uppercase string");
|
||||
assert_eq!(parse, vec![0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
|
||||
let ser = parse.to_hex();
|
||||
let ser = parse.to_lower_hex_string();
|
||||
assert_eq!(ser, expected);
|
||||
|
||||
let parse: [u8; 8] = FromHex::from_hex(expected_up).expect("parse uppercase string");
|
||||
assert_eq!(parse, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
|
||||
let ser = parse.to_hex();
|
||||
let ser = parse.to_lower_hex_string();
|
||||
assert_eq!(ser, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hex_truncate() {
|
||||
struct HexBytes(Vec<u8>);
|
||||
impl fmt::LowerHex for HexBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
format_hex(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
let bytes = HexBytes(vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
|
||||
assert_eq!(
|
||||
format!("{:x}", bytes),
|
||||
"0102030405060708090a"
|
||||
);
|
||||
|
||||
for i in 0..20 {
|
||||
assert_eq!(
|
||||
format!("{:.prec$x}", bytes, prec = i),
|
||||
&"0102030405060708090a"[0..i]
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
format!("{:25x}", bytes),
|
||||
"000000102030405060708090a"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:26x}", bytes),
|
||||
"0000000102030405060708090a"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hex_truncate_rev() {
|
||||
struct HexBytes(Vec<u8>);
|
||||
impl fmt::LowerHex for HexBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
format_hex_reverse(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
let bytes = HexBytes(vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
|
||||
assert_eq!(
|
||||
format!("{:x}", bytes),
|
||||
"0a090807060504030201"
|
||||
);
|
||||
|
||||
for i in 0..20 {
|
||||
assert_eq!(
|
||||
format!("{:.prec$x}", bytes, prec = i),
|
||||
&"0a090807060504030201"[0..i]
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
format!("{:25x}", bytes),
|
||||
"000000a090807060504030201"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:26x}", bytes),
|
||||
"0000000a090807060504030201"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn hex_error() {
|
||||
|
@ -447,18 +306,19 @@ mod tests {
|
|||
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn hex_writer() {
|
||||
let vec: Vec<_> = (0u8..32).collect();
|
||||
let mut writer = HexWriter::new(64);
|
||||
writer.write_all(&vec[..]).unwrap();
|
||||
assert_eq!(vec.to_hex(), writer.result());
|
||||
assert_eq!(vec.to_lower_hex_string(), writer.result());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(bench)]
|
||||
mod benches {
|
||||
use test::{Bencher, black_box};
|
||||
use super::{ToHex, HexWriter};
|
||||
use super::HexWriter;
|
||||
use std::io::Write;
|
||||
use crate::{sha256, Hash};
|
||||
|
||||
|
@ -466,7 +326,7 @@ mod benches {
|
|||
fn bench_to_hex(bh: &mut Bencher) {
|
||||
let hash = sha256::Hash::hash(&[0; 1]);
|
||||
bh.iter(|| {
|
||||
black_box(hash.to_hex());
|
||||
black_box(hash.to_string());
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -408,7 +408,7 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::{Hash, HashEngine, ripemd160};
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
|
@ -472,7 +472,7 @@ mod tests {
|
|||
let hash = ripemd160::Hash::hash(test.input.as_bytes());
|
||||
assert_eq!(hash, ripemd160::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = ripemd160::Hash::engine();
|
||||
|
|
|
@ -146,7 +146,7 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::{sha1, Hash, HashEngine};
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
|
@ -198,7 +198,7 @@ mod tests {
|
|||
let hash = sha1::Hash::hash(test.input.as_bytes());
|
||||
assert_eq!(hash, sha1::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = sha1::Hash::engine();
|
||||
|
|
|
@ -326,7 +326,7 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
|
@ -374,7 +374,7 @@ mod tests {
|
|||
let hash = sha256::Hash::hash(test.input.as_bytes());
|
||||
assert_eq!(hash, sha256::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = sha256::Hash::engine();
|
||||
|
|
|
@ -49,7 +49,7 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::{sha256d, Hash, HashEngine};
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
|
@ -77,7 +77,7 @@ mod tests {
|
|||
let hash = sha256d::Hash::hash(test.input.as_bytes());
|
||||
assert_eq!(hash, sha256d::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = sha256d::Hash::engine();
|
||||
|
|
|
@ -123,8 +123,6 @@ macro_rules! sha256t_hash_newtype {
|
|||
mod tests {
|
||||
use crate::{sha256, sha256t};
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use crate::hex::ToHex;
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use crate::Hash;
|
||||
|
||||
const TEST_MIDSTATE: [u8; 32] = [
|
||||
|
@ -154,11 +152,11 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test_sha256t() {
|
||||
assert_eq!(
|
||||
TestHash::hash(&[0]).to_hex(),
|
||||
TestHash::hash(&[0]).to_string(),
|
||||
"29589d5122ec666ab5b4695070b6debc63881a4f85d88d93ddc90078038213ed"
|
||||
);
|
||||
assert_eq!(
|
||||
NewTypeHash::hash(&[0]).to_hex(),
|
||||
NewTypeHash::hash(&[0]).to_string(),
|
||||
"29589d5122ec666ab5b4695070b6debc63881a4f85d88d93ddc90078038213ed"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -311,7 +311,7 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::{sha512, Hash, HashEngine};
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
|
@ -371,7 +371,7 @@ mod tests {
|
|||
let hash = sha512::Hash::hash(test.input.as_bytes());
|
||||
assert_eq!(hash, sha512::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = sha512::Hash::engine();
|
||||
|
|
|
@ -89,7 +89,7 @@ mod tests {
|
|||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn test() {
|
||||
use crate::{sha512_256, Hash, HashEngine};
|
||||
use crate::hex::{FromHex, ToHex};
|
||||
use crate::hex::FromHex;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Test {
|
||||
|
@ -157,7 +157,7 @@ mod tests {
|
|||
let hash = sha512_256::Hash::hash(test.input.as_bytes());
|
||||
assert_eq!(hash, sha512_256::Hash::from_hex(test.output_str).expect("parse hex"));
|
||||
assert_eq!(&hash[..], &test.output[..]);
|
||||
assert_eq!(&hash.to_hex(), &test.output_str);
|
||||
assert_eq!(&hash.to_string(), &test.output_str);
|
||||
|
||||
// Hash through engine, checking that we can input byte by byte
|
||||
let mut engine = sha512_256::Hash::engine();
|
||||
|
|
|
@ -111,6 +111,23 @@ impl<'a> DisplayHex for &'a [u8] {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(docsrs, doc(feature = "alloc"))]
|
||||
impl<'a> DisplayHex for &'a alloc::vec::Vec<u8> {
|
||||
type Display = DisplayByteSlice<'a>;
|
||||
|
||||
#[inline]
|
||||
fn as_hex(self) -> Self::Display { DisplayByteSlice { bytes: self } }
|
||||
|
||||
#[inline]
|
||||
fn hex_reserve_suggestion(self) -> usize {
|
||||
// Since the string wouldn't fit into address space if this overflows (actually even for
|
||||
// smaller amounts) it's better to panic right away. It should also give the optimizer
|
||||
// better opportunities.
|
||||
self.len().checked_mul(2).expect("the string wouldn't fit into address space")
|
||||
}
|
||||
}
|
||||
|
||||
/// Displays byte slice as hex.
|
||||
///
|
||||
/// Created by [`<&[u8] as DisplayHex>::display_hex`](DisplayHex::display_hex).
|
||||
|
|
Loading…
Reference in New Issue