Skip to content

Commit 2e39df4

Browse files
committed
Merge #272: Update to hex-conservative 1.1; drop hex module
44a6974 rename hex_conservative to hex, re-export it, delete old hex module (Andrew Poelstra) f30b28a re-export 'hex_conservative' as hex (Andrew Poelstra) 1c37bb1 serde_utils: remove old hex module (Andrew Poelstra) de8927c serde: remove old hex module from 'hex_bytes' module (Andrew Poelstra) 0e28e22 serde_utils: change deserialization bound on hex_bytes from FromHex to From<Vec<u8>> (Andrew Poelstra) c307d35 replace ToHex with hex-conservative 1.1 functions (Andrew Poelstra) 3a1a2a1 script: replace from_hex and from_str with from_hex_no_prefix (Andrew Poelstra) 0b6ef57 confidential: replace FromHex with FromStr for abf and vbf (Andrew Poelstra) b4ab7c3 replace Vec::<u8>::from_hex with hex-conservative functions (Andrew Poelstra) a152b04 bump hex-conservative dependency to 1.1.0 (Andrew Poelstra) Pull request description: We have a `hex` module which is loosely based on the `hashes::hex` module from `bitcoin_hashes` 0.11 or so. rust-bitcoin has updated to the `hex-conservative` crate, "hex with a conservative MSRV policy", which is maintained by the rust-bitcoin community. We recently have released version 1.1, which is finally feature-complete, after years of haggling over API questions. This has a couple philosophical changes from the old `hex` module: * There is no `FromHex` trait; the assumption is that if something is naturally hex-encoded then it should use `FromStr` to parse from hex, and there is little value in a trait describing "an object which can be parsed from hex" beyond this. For things like `Script` which have a hex-encoding but aren't "naturally" hex-encoded, they should have inherent methods * Relatedly, rather than requiring extension traits to decode hex to arrays or vectors, we provide standalone methods `decode_to_vec` and `decode_to_array` * The `ToHex` trait, which previously was oriented around producing hex-encoded `String`s, has been replaced with `DisplayHex`, a trait which produces a (typically) no-alloc wrapper around an object that can be hex-formatted. It is a trait rather than standalone function(s) so it can be cleanly implemented for both `[u8]` and `[u8]`-like things, but we don't expect users to implement this; they should use `Display` or inherent methods instead In addition, there are a pile of mechanical changes; `to_hex` becomes `as_hex` in most cases, `Vec::from_hex` becomes `decode_to_vec` or `hex!`, etc. So this PR has a large diff but it's mostly mechanical, and the changes serve both to clean up the code and to eliminate a bunch of allocations. A later PR will replace our encoding traits with the new `bitcoin-consensus-encoding` trait, which will further eliminate allocations when deserializing objects from hex. ACKs for top commit: apoelstra: ACK 44a6974; successfully ran local tests delta1: ACK 44a6974; tested locally Tree-SHA512: b4ed7ccd0c66b0b59baf2ab11c80af502d3590373992c73270f49ae112ca1ab3296138f08375dbe41cc8e8dac65216562eb13195bb77ee2aa7947ad778b06930
2 parents 4a7f62a + 44a6974 commit 2e39df4

27 files changed

Lines changed: 224 additions & 617 deletions

Cargo-recent.lock

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ dependencies = [
204204
"bincode",
205205
"bitcoin",
206206
"getrandom 0.2.16",
207-
"hex-conservative 1.0.0",
207+
"hex-conservative 1.1.0",
208208
"rand",
209209
"rand_chacha",
210210
"secp256k1-zkp",
@@ -293,9 +293,12 @@ dependencies = [
293293

294294
[[package]]
295295
name = "hex-conservative"
296-
version = "1.0.0"
296+
version = "1.1.0"
297297
source = "registry+https://github.com/rust-lang/crates.io-index"
298-
checksum = "9ee770c000993d17c185713463d5ebfbd1af9afae4c17cc295640104383bfbf0"
298+
checksum = "a7289f6b628ce69fb1a371d0fdcf8ff38cd93ec00e3010eb055d1e044998c8d1"
299+
dependencies = [
300+
"arrayvec",
301+
]
299302

300303
[[package]]
301304
name = "hex_lit"

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ serde_json = { version = "1.0", optional = true }
3737
actual-serde = { package = "serde", version = "1.0.103", features = [
3838
"derive",
3939
], optional = true }
40-
hex-conservative = "1.0.0"
40+
hex = { package = "hex-conservative", version = "1.1.0" }
4141

4242

4343
[target.wasm32-unknown-unknown.dev-dependencies]

elementsd-tests/src/pset.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ extern crate rand;
77
use crate::{setup, Call};
88

99
use bitcoin::{self, Address, Amount};
10-
use elements::hex::ToHex;
1110
use elements::encode::serialize;
1211
use elements::hashes::Hash;
12+
use elements::hex::DisplayHex as _;
1313
use elements::pset::PartiallySignedTransaction;
1414
use elements::{AssetId, ContractHash};
1515
use elementsd::bitcoincore_rpc::jsonrpc::serde_json::json;
@@ -116,7 +116,7 @@ fn tx_pegin() {
116116
bitcoind.client.generate_to_address(101, &btc_addr).unwrap();
117117
let proof = bitcoind.client.get_tx_out_proof(&[txid], None).unwrap();
118118
elementsd.generate(2);
119-
let inputs = json!([ {"txid":txid, "vout": vout,"pegin_bitcoin_tx": tx_bytes.to_hex(), "pegin_txout_proof": proof.to_hex(), "pegin_claim_script": claim_script } ]);
119+
let inputs = json!([ {"txid":txid, "vout": vout,"pegin_bitcoin_tx": tx_bytes.to_lower_hex_string(), "pegin_txout_proof": proof.to_lower_hex_string(), "pegin_claim_script": claim_script } ]);
120120
let outputs = json!([
121121
{address_lbtc: "0.9", "blinder_index": 0},
122122
{"fee": "0.1" }
@@ -158,7 +158,7 @@ fn psbt_rtt(elementsd: &ElementsD, base64: &str) {
158158
b_bytes[i] = b_bytes[i].wrapping_add(1);
159159
let base64 = BASE64_STANDARD.encode(&b_bytes);
160160
if let Some(decoded) = elementsd.decode_psbt(&base64) {
161-
assert_ne!(a, decoded, "{} with changed byte {}", b_bytes.to_hex(), i);
161+
assert_ne!(a, decoded, "{} with changed byte {}", b_bytes.as_hex(), i);
162162
}
163163
b_bytes[i] = b_bytes[i].wrapping_sub(1);
164164
}

elementsd-tests/src/taproot.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{Call, setup};
77

88
use bitcoin::key::{XOnlyPublicKey, Keypair};
99
use bitcoin::Amount;
10-
use elements::hex::FromHex;
10+
use elements::hex;
1111
use elements::confidential::{AssetBlindingFactor, ValueBlindingFactor};
1212
use elements::encode::{deserialize, serialize_hex};
1313
use elements::hashes::Hash;
@@ -101,7 +101,7 @@ fn funded_tap_txout(
101101
elementsd.generate(1);
102102
let tx_hex = elementsd.get_transaction(&txid_hex);
103103

104-
let tx = deserialize::<Transaction>(&Vec::<u8>::from_hex(&tx_hex).unwrap()).unwrap();
104+
let tx = deserialize::<Transaction>(&hex::decode_to_vec(&tx_hex).unwrap()).unwrap();
105105

106106
let mut outpoint: Option<OutPoint> = None;
107107
for (i, out) in tx.output.iter().enumerate() {

examples/pset_blind_coinjoin.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use elements::{pset, secp256k1_zkp};
2828

2929
use elements::encode::{deserialize, serialize_hex};
3030
use elements::{confidential, AssetId, TxOut};
31-
use elements::hex::FromHex;
31+
use elements::hex;
3232
use rand::SeedableRng;
3333

3434
// Assume txouts are simple pay to wpkh
@@ -41,7 +41,7 @@ struct Secrets {
4141
}
4242

4343
fn deser_pset(psbt_hex: &str) -> Pset {
44-
deserialize::<Pset>(&Vec::<u8>::from_hex(psbt_hex).unwrap()).unwrap()
44+
deserialize::<Pset>(&hex::decode_to_vec(psbt_hex).unwrap()).unwrap()
4545
}
4646

4747
fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) {
@@ -50,18 +50,18 @@ fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) {
5050

5151
let txout = TxOut {
5252
asset: deserialize::<confidential::Asset>(
53-
&Vec::<u8>::from_hex(v["assetcommitment"].as_str().unwrap()).unwrap(),
53+
&hex::decode_to_vec(v["assetcommitment"].as_str().unwrap()).unwrap(),
5454
)
5555
.unwrap(),
5656
value: deserialize::<confidential::Value>(
57-
&Vec::<u8>::from_hex(v["amountcommitment"].as_str().unwrap()).unwrap(),
57+
&hex::decode_to_vec(v["amountcommitment"].as_str().unwrap()).unwrap(),
5858
)
5959
.unwrap(),
6060
nonce: deserialize::<confidential::Nonce>(
61-
&Vec::<u8>::from_hex(v["commitmentnonce"].as_str().unwrap()).unwrap(),
61+
&hex::decode_to_vec(v["commitmentnonce"].as_str().unwrap()).unwrap(),
6262
)
6363
.unwrap(),
64-
script_pubkey: Script::from_hex(v["scriptPubKey"].as_str().unwrap()).unwrap(),
64+
script_pubkey: Script::from_hex_no_prefix(v["scriptPubKey"].as_str().unwrap()).unwrap(),
6565
witness: TxOutWitness::default(),
6666
};
6767

examples/raw_blind.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use elements::{pset, secp256k1_zkp, SurjectionInput};
1515

1616
use elements::encode::{deserialize, serialize_hex};
1717
use elements::{confidential, AssetId, TxOut};
18-
use elements::hex::FromHex;
18+
use elements::hex;
1919
use rand::SeedableRng;
2020

2121
/// Pset example workflow:
@@ -36,7 +36,7 @@ struct Secrets {
3636
}
3737

3838
fn deser_pset(psbt_hex: &str) -> Pset {
39-
deserialize::<Pset>(&Vec::<u8>::from_hex(psbt_hex).unwrap()).unwrap()
39+
deserialize::<Pset>(&hex::decode_to_vec(psbt_hex).unwrap()).unwrap()
4040
}
4141

4242
fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) {
@@ -45,18 +45,18 @@ fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) {
4545

4646
let txout = TxOut {
4747
asset: deserialize::<confidential::Asset>(
48-
&Vec::<u8>::from_hex(v["assetcommitment"].as_str().unwrap()).unwrap(),
48+
&hex::decode_to_vec(v["assetcommitment"].as_str().unwrap()).unwrap(),
4949
)
5050
.unwrap(),
5151
value: deserialize::<confidential::Value>(
52-
&Vec::<u8>::from_hex(v["amountcommitment"].as_str().unwrap()).unwrap(),
52+
&hex::decode_to_vec(v["amountcommitment"].as_str().unwrap()).unwrap(),
5353
)
5454
.unwrap(),
5555
nonce: deserialize::<confidential::Nonce>(
56-
&Vec::<u8>::from_hex(v["commitmentnonce"].as_str().unwrap()).unwrap(),
56+
&hex::decode_to_vec(v["commitmentnonce"].as_str().unwrap()).unwrap(),
5757
)
5858
.unwrap(),
59-
script_pubkey: Script::from_hex(v["scriptPubKey"].as_str().unwrap()).unwrap(),
59+
script_pubkey: Script::from_hex_no_prefix(v["scriptPubKey"].as_str().unwrap()).unwrap(),
6060
witness: TxOutWitness::default(),
6161
};
6262

@@ -280,13 +280,13 @@ fn main() {
280280
tx.verify_tx_amt_proofs(&secp, &[btc_txout, asset_txout])
281281
.unwrap();
282282

283-
let inp0_sig = Vec::<u8>::from_hex("3044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801").unwrap();
283+
let inp0_sig = hex::hex!("3044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801").to_vec();
284284
let inp0_pk = PublicKey::from_str(
285285
"0334c307ad8142e7c8a6bf1ad3552b12fbb860885ea7f2d76c1f49f93a7c4bbbe7",
286286
)
287287
.unwrap();
288288

289-
let inp1_sig = Vec::<u8>::from_hex("3044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa01").unwrap();
289+
let inp1_sig = hex::hex!("3044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa01").to_vec();
290290
let inp1_pk = PublicKey::from_str(
291291
"03df8f51c053ba0dfb443cce9793b6dc3339ffb0ce97af4792dade3aae1eb890f6",
292292
)

examples/tx.rs

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

src/blind.rs

Lines changed: 21 additions & 49 deletions
Large diffs are not rendered by default.

src/block.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,6 @@ impl Block {
395395
#[cfg(test)]
396396
mod tests {
397397
use crate::Block;
398-
use crate::hex::FromHex;
399398

400399
use super::*;
401400

@@ -796,7 +795,7 @@ mod tests {
796795
fn test_failed_block() {
797796
let block_str = include_str!("../tests/data/failedblock.hex");
798797

799-
let bytes = Vec::<u8>::from_hex(block_str).unwrap();
798+
let bytes = hex::decode_to_vec(block_str).unwrap();
800799
let _block = encode::deserialize::<Block>(&bytes).unwrap();
801800
}
802801
}

0 commit comments

Comments
 (0)