Introduce `hex_lit` crate
So far we deserialized hex into `Vec<u8>` at run time. This was mainly in tests where it had negligible performance cost. However moving the computation to compile time has a few benefits: it allows proving the length of the decoded bytes and identifies potential typos before the code goes through LLVM and other compilation machinery which makes feedback faster. This change uses the `hex_lit` crate to move computation to compile time. It is implemented as `const` declarative macro which doesn't blow up compilation time.
This commit is contained in:
parent
794ddde657
commit
bb2c7ec790
|
@ -44,6 +44,7 @@ bitcoinconsensus = { version = "0.20.2-0.5.0", optional = true, default-features
|
||||||
core2 = { version = "0.3.0", default-features = false, features = ["alloc"], optional = true }
|
core2 = { version = "0.3.0", default-features = false, features = ["alloc"], optional = true }
|
||||||
# Do NOT use this as a feature! Use the `serde` feature instead.
|
# Do NOT use this as a feature! Use the `serde` feature instead.
|
||||||
actual-serde = { package = "serde", version = "1.0.103", default-features = false, features = [ "derive", "alloc" ], optional = true }
|
actual-serde = { package = "serde", version = "1.0.103", default-features = false, features = [ "derive", "alloc" ], optional = true }
|
||||||
|
hex_lit = "0.1.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1.0.0"
|
serde_json = "1.0.0"
|
||||||
|
|
|
@ -1139,7 +1139,7 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::crypto::key::PublicKey;
|
use crate::crypto::key::PublicKey;
|
||||||
use crate::internal_macros::hex;
|
use hex_lit::hex;
|
||||||
use crate::network::constants::Network::{Bitcoin, Testnet};
|
use crate::network::constants::Network::{Bitcoin, Testnet};
|
||||||
|
|
||||||
fn roundtrips(addr: &Address) {
|
fn roundtrips(addr: &Address) {
|
||||||
|
@ -1272,10 +1272,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_non_existent_segwit_version() {
|
fn test_non_existent_segwit_version() {
|
||||||
// 40-byte program
|
// 40-byte program
|
||||||
let program = hex!(
|
let program = hex!("654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4");
|
||||||
"654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4"
|
let witness_prog = WitnessProgram::new(WitnessVersion::V13, program.to_vec()).unwrap();
|
||||||
);
|
|
||||||
let witness_prog = WitnessProgram::new(WitnessVersion::V13, program).unwrap();
|
|
||||||
let addr = Address::new(Bitcoin, Payload::WitnessProgram(witness_prog));
|
let addr = Address::new(Bitcoin, Payload::WitnessProgram(witness_prog));
|
||||||
roundtrips(&addr);
|
roundtrips(&addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,11 @@
|
||||||
//! single transaction.
|
//! single transaction.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
|
|
||||||
use bitcoin_internals::impl_array_newtype;
|
use bitcoin_internals::impl_array_newtype;
|
||||||
|
use hex_lit::hex;
|
||||||
|
|
||||||
use crate::hashes::hex::{self, HexIterator};
|
|
||||||
use crate::hashes::{Hash, sha256d};
|
use crate::hashes::{Hash, sha256d};
|
||||||
use crate::blockdata::script;
|
use crate::blockdata::script;
|
||||||
use crate::blockdata::opcodes::all::*;
|
use crate::blockdata::opcodes::all::*;
|
||||||
|
@ -85,11 +83,9 @@ fn bitcoin_genesis_tx() -> Transaction {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
let script_bytes: Result<Vec<u8>, hex::Error> =
|
let script_bytes = hex!("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
|
||||||
HexIterator::new("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap()
|
|
||||||
.collect();
|
|
||||||
let out_script = script::Builder::new()
|
let out_script = script::Builder::new()
|
||||||
.push_slice(script_bytes.unwrap().as_slice())
|
.push_slice(&script_bytes)
|
||||||
.push_opcode(OP_CHECKSIG)
|
.push_opcode(OP_CHECKSIG)
|
||||||
.into_script();
|
.into_script();
|
||||||
ret.output.push(TxOut {
|
ret.output.push(TxOut {
|
||||||
|
|
|
@ -3,13 +3,12 @@ use core::str::FromStr;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::hashes::Hash;
|
use crate::hashes::Hash;
|
||||||
use crate::hashes::hex::FromHex;
|
|
||||||
use crate::hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash};
|
use crate::hash_types::{PubkeyHash, WPubkeyHash, ScriptHash, WScriptHash};
|
||||||
use crate::consensus::encode::{deserialize, serialize};
|
use crate::consensus::encode::{deserialize, serialize};
|
||||||
use crate::blockdata::opcodes;
|
use crate::blockdata::opcodes;
|
||||||
use crate::crypto::key::{PublicKey, XOnlyPublicKey};
|
use crate::crypto::key::{PublicKey, XOnlyPublicKey};
|
||||||
use crate::psbt::serialize::Serialize;
|
use crate::psbt::serialize::Serialize;
|
||||||
use crate::internal_macros::hex;
|
use hex_lit::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn script() {
|
fn script() {
|
||||||
|
@ -32,7 +31,7 @@ fn script() {
|
||||||
script = script.push_int(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]);
|
script = script.push_int(-10000000); comp.extend([4u8, 128, 150, 152, 128].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]);
|
||||||
|
|
||||||
// data
|
// data
|
||||||
script = script.push_slice("NRA4VR".as_bytes()); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]);
|
script = script.push_slice(b"NRA4VR"); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().cloned()); assert_eq!(script.as_bytes(), &comp[..]);
|
||||||
|
|
||||||
// keys
|
// keys
|
||||||
const KEYSTR1: &str = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af";
|
const KEYSTR1: &str = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af";
|
||||||
|
@ -88,9 +87,9 @@ fn p2pk_pubkey_bytes_different_op_code_returns_none() {
|
||||||
#[test]
|
#[test]
|
||||||
fn p2pk_pubkey_bytes_incorrect_key_size_returns_none() {
|
fn p2pk_pubkey_bytes_incorrect_key_size_returns_none() {
|
||||||
// 63 byte key
|
// 63 byte key
|
||||||
let malformed_key = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1";
|
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1";
|
||||||
let invalid_p2pk_script = Script::builder()
|
let invalid_p2pk_script = Script::builder()
|
||||||
.push_slice(malformed_key.as_bytes())
|
.push_slice(malformed_key)
|
||||||
.push_opcode(OP_CHECKSIG)
|
.push_opcode(OP_CHECKSIG)
|
||||||
.into_script();
|
.into_script();
|
||||||
assert!(invalid_p2pk_script.p2pk_pubkey_bytes().is_none());
|
assert!(invalid_p2pk_script.p2pk_pubkey_bytes().is_none());
|
||||||
|
@ -154,9 +153,9 @@ fn p2pk_public_key_different_op_code_returns_none() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn p2pk_public_key_incorrect_size_returns_none() {
|
fn p2pk_public_key_incorrect_size_returns_none() {
|
||||||
let malformed_key = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1";
|
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1";
|
||||||
let malformed_key_script = Script::builder()
|
let malformed_key_script = Script::builder()
|
||||||
.push_slice(malformed_key.as_bytes())
|
.push_slice(malformed_key)
|
||||||
.push_opcode(OP_CHECKSIG)
|
.push_opcode(OP_CHECKSIG)
|
||||||
.into_script();
|
.into_script();
|
||||||
assert!(malformed_key_script.p2pk_public_key().is_none());
|
assert!(malformed_key_script.p2pk_public_key().is_none());
|
||||||
|
@ -165,9 +164,9 @@ fn p2pk_public_key_incorrect_size_returns_none() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn p2pk_public_key_invalid_key_returns_none() {
|
fn p2pk_public_key_invalid_key_returns_none() {
|
||||||
let malformed_key = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1ux";
|
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1ux";
|
||||||
let invalid_key_script = Script::builder()
|
let invalid_key_script = Script::builder()
|
||||||
.push_slice(malformed_key.as_bytes())
|
.push_slice(malformed_key)
|
||||||
.push_opcode(OP_CHECKSIG)
|
.push_opcode(OP_CHECKSIG)
|
||||||
.into_script();
|
.into_script();
|
||||||
assert!(invalid_key_script.p2pk_public_key().is_none());
|
assert!(invalid_key_script.p2pk_public_key().is_none());
|
||||||
|
@ -190,7 +189,7 @@ fn script_x_only_key() {
|
||||||
const KEYSTR: &str = "209997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be";
|
const KEYSTR: &str = "209997a497d964fc1a62885b05a51166a65a90df00492c8d7cf61d6accf54803be";
|
||||||
let x_only_key = XOnlyPublicKey::from_str(&KEYSTR[2..]).unwrap();
|
let x_only_key = XOnlyPublicKey::from_str(&KEYSTR[2..]).unwrap();
|
||||||
let script = Builder::new().push_x_only_key(&x_only_key);
|
let script = Builder::new().push_x_only_key(&x_only_key);
|
||||||
assert_eq!(script.into_bytes(), hex!(KEYSTR));
|
assert_eq!(script.into_bytes(), &hex!(KEYSTR) as &[u8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -231,7 +230,7 @@ fn script_generators() {
|
||||||
|
|
||||||
// Test data are taken from the second output of
|
// Test data are taken from the second output of
|
||||||
// 2ccb3a1f745eb4eefcf29391460250adda5fab78aaddb902d25d3cd97d9d8e61 transaction
|
// 2ccb3a1f745eb4eefcf29391460250adda5fab78aaddb902d25d3cd97d9d8e61 transaction
|
||||||
let data = Vec::<u8>::from_hex("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a").unwrap();
|
let data = hex!("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
|
||||||
let op_return = ScriptBuf::new_op_return(&data);
|
let op_return = ScriptBuf::new_op_return(&data);
|
||||||
assert!(op_return.is_op_return());
|
assert!(op_return.is_op_return());
|
||||||
assert_eq!(op_return.to_hex_string(), "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
|
assert_eq!(op_return.to_hex_string(), "6a24aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
|
||||||
|
@ -314,7 +313,7 @@ fn script_serialize() {
|
||||||
let hex_script = hex!("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52");
|
let hex_script = hex!("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52");
|
||||||
let script: Result<ScriptBuf, _> = deserialize(&hex_script);
|
let script: Result<ScriptBuf, _> = deserialize(&hex_script);
|
||||||
assert!(script.is_ok());
|
assert!(script.is_ok());
|
||||||
assert_eq!(serialize(&script.unwrap()), hex_script);
|
assert_eq!(serialize(&script.unwrap()), &hex_script as &[u8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -547,9 +546,10 @@ fn script_ord() {
|
||||||
#[cfg(feature = "bitcoinconsensus")]
|
#[cfg(feature = "bitcoinconsensus")]
|
||||||
fn test_bitcoinconsensus () {
|
fn test_bitcoinconsensus () {
|
||||||
// a random segwit transaction from the blockchain using native segwit
|
// a random segwit transaction from the blockchain using native segwit
|
||||||
let spent = Builder::from(hex!("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d")).into_script();
|
let spent_bytes = hex!("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d");
|
||||||
|
let spent = Script::from_bytes(&spent_bytes);
|
||||||
let spending = hex!("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000");
|
let spending = hex!("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000");
|
||||||
spent.verify(0, crate::Amount::from_sat(18393430), spending.as_slice()).unwrap();
|
spent.verify(0, crate::Amount::from_sat(18393430), &spending).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue