diff --git a/Cargo-recent.lock b/Cargo-recent.lock index a478ed20..3deca569 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -204,7 +204,7 @@ dependencies = [ "bincode", "bitcoin", "getrandom 0.2.16", - "hex-conservative 1.0.0", + "hex-conservative 1.1.0", "rand", "rand_chacha", "secp256k1-zkp", @@ -293,9 +293,12 @@ dependencies = [ [[package]] name = "hex-conservative" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee770c000993d17c185713463d5ebfbd1af9afae4c17cc295640104383bfbf0" +checksum = "a7289f6b628ce69fb1a371d0fdcf8ff38cd93ec00e3010eb055d1e044998c8d1" +dependencies = [ + "arrayvec", +] [[package]] name = "hex_lit" diff --git a/Cargo.toml b/Cargo.toml index 56871adb..9108dd36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ serde_json = { version = "1.0", optional = true } actual-serde = { package = "serde", version = "1.0.103", features = [ "derive", ], optional = true } -hex-conservative = "1.0.0" +hex = { package = "hex-conservative", version = "1.1.0" } [target.wasm32-unknown-unknown.dev-dependencies] diff --git a/elementsd-tests/src/pset.rs b/elementsd-tests/src/pset.rs index fcafcd17..7ce1d95b 100644 --- a/elementsd-tests/src/pset.rs +++ b/elementsd-tests/src/pset.rs @@ -7,9 +7,9 @@ extern crate rand; use crate::{setup, Call}; use bitcoin::{self, Address, Amount}; -use elements::hex::ToHex; use elements::encode::serialize; use elements::hashes::Hash; +use elements::hex::DisplayHex as _; use elements::pset::PartiallySignedTransaction; use elements::{AssetId, ContractHash}; use elementsd::bitcoincore_rpc::jsonrpc::serde_json::json; @@ -116,7 +116,7 @@ fn tx_pegin() { bitcoind.client.generate_to_address(101, &btc_addr).unwrap(); let proof = bitcoind.client.get_tx_out_proof(&[txid], None).unwrap(); elementsd.generate(2); - 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 } ]); + 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 } ]); let outputs = json!([ {address_lbtc: "0.9", "blinder_index": 0}, {"fee": "0.1" } @@ -158,7 +158,7 @@ fn psbt_rtt(elementsd: &ElementsD, base64: &str) { b_bytes[i] = b_bytes[i].wrapping_add(1); let base64 = BASE64_STANDARD.encode(&b_bytes); if let Some(decoded) = elementsd.decode_psbt(&base64) { - assert_ne!(a, decoded, "{} with changed byte {}", b_bytes.to_hex(), i); + assert_ne!(a, decoded, "{} with changed byte {}", b_bytes.as_hex(), i); } b_bytes[i] = b_bytes[i].wrapping_sub(1); } diff --git a/elementsd-tests/src/taproot.rs b/elementsd-tests/src/taproot.rs index 2c37a9d3..8dcc6b13 100644 --- a/elementsd-tests/src/taproot.rs +++ b/elementsd-tests/src/taproot.rs @@ -7,7 +7,7 @@ use crate::{Call, setup}; use bitcoin::key::{XOnlyPublicKey, Keypair}; use bitcoin::Amount; -use elements::hex::FromHex; +use elements::hex; use elements::confidential::{AssetBlindingFactor, ValueBlindingFactor}; use elements::encode::{deserialize, serialize_hex}; use elements::hashes::Hash; @@ -101,7 +101,7 @@ fn funded_tap_txout( elementsd.generate(1); let tx_hex = elementsd.get_transaction(&txid_hex); - let tx = deserialize::(&Vec::::from_hex(&tx_hex).unwrap()).unwrap(); + let tx = deserialize::(&hex::decode_to_vec(&tx_hex).unwrap()).unwrap(); let mut outpoint: Option = None; for (i, out) in tx.output.iter().enumerate() { diff --git a/examples/pset_blind_coinjoin.rs b/examples/pset_blind_coinjoin.rs index 333710f9..0f9931e6 100644 --- a/examples/pset_blind_coinjoin.rs +++ b/examples/pset_blind_coinjoin.rs @@ -28,7 +28,7 @@ use elements::{pset, secp256k1_zkp}; use elements::encode::{deserialize, serialize_hex}; use elements::{confidential, AssetId, TxOut}; -use elements::hex::FromHex; +use elements::hex; use rand::SeedableRng; // Assume txouts are simple pay to wpkh @@ -41,7 +41,7 @@ struct Secrets { } fn deser_pset(psbt_hex: &str) -> Pset { - deserialize::(&Vec::::from_hex(psbt_hex).unwrap()).unwrap() + deserialize::(&hex::decode_to_vec(psbt_hex).unwrap()).unwrap() } fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) { @@ -50,18 +50,18 @@ fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) { let txout = TxOut { asset: deserialize::( - &Vec::::from_hex(v["assetcommitment"].as_str().unwrap()).unwrap(), + &hex::decode_to_vec(v["assetcommitment"].as_str().unwrap()).unwrap(), ) .unwrap(), value: deserialize::( - &Vec::::from_hex(v["amountcommitment"].as_str().unwrap()).unwrap(), + &hex::decode_to_vec(v["amountcommitment"].as_str().unwrap()).unwrap(), ) .unwrap(), nonce: deserialize::( - &Vec::::from_hex(v["commitmentnonce"].as_str().unwrap()).unwrap(), + &hex::decode_to_vec(v["commitmentnonce"].as_str().unwrap()).unwrap(), ) .unwrap(), - script_pubkey: Script::from_hex(v["scriptPubKey"].as_str().unwrap()).unwrap(), + script_pubkey: Script::from_hex_no_prefix(v["scriptPubKey"].as_str().unwrap()).unwrap(), witness: TxOutWitness::default(), }; diff --git a/examples/raw_blind.rs b/examples/raw_blind.rs index 0091ceec..c45be283 100644 --- a/examples/raw_blind.rs +++ b/examples/raw_blind.rs @@ -15,7 +15,7 @@ use elements::{pset, secp256k1_zkp, SurjectionInput}; use elements::encode::{deserialize, serialize_hex}; use elements::{confidential, AssetId, TxOut}; -use elements::hex::FromHex; +use elements::hex; use rand::SeedableRng; /// Pset example workflow: @@ -36,7 +36,7 @@ struct Secrets { } fn deser_pset(psbt_hex: &str) -> Pset { - deserialize::(&Vec::::from_hex(psbt_hex).unwrap()).unwrap() + deserialize::(&hex::decode_to_vec(psbt_hex).unwrap()).unwrap() } fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) { @@ -45,18 +45,18 @@ fn parse_txout(txout_info: &str) -> (TxOut, Secrets, pset::Input) { let txout = TxOut { asset: deserialize::( - &Vec::::from_hex(v["assetcommitment"].as_str().unwrap()).unwrap(), + &hex::decode_to_vec(v["assetcommitment"].as_str().unwrap()).unwrap(), ) .unwrap(), value: deserialize::( - &Vec::::from_hex(v["amountcommitment"].as_str().unwrap()).unwrap(), + &hex::decode_to_vec(v["amountcommitment"].as_str().unwrap()).unwrap(), ) .unwrap(), nonce: deserialize::( - &Vec::::from_hex(v["commitmentnonce"].as_str().unwrap()).unwrap(), + &hex::decode_to_vec(v["commitmentnonce"].as_str().unwrap()).unwrap(), ) .unwrap(), - script_pubkey: Script::from_hex(v["scriptPubKey"].as_str().unwrap()).unwrap(), + script_pubkey: Script::from_hex_no_prefix(v["scriptPubKey"].as_str().unwrap()).unwrap(), witness: TxOutWitness::default(), }; @@ -280,13 +280,13 @@ fn main() { tx.verify_tx_amt_proofs(&secp, &[btc_txout, asset_txout]) .unwrap(); - let inp0_sig = Vec::::from_hex("3044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801").unwrap(); + let inp0_sig = hex::hex!("3044022040d1802d6e10da4c27f05eff807550e614b3d2fa20c663dbf1ebf162d3952689022001f477c953b7c543bce877e3297fccb00ef5dba21d427e79c8bfb8522713309801").to_vec(); let inp0_pk = PublicKey::from_str( "0334c307ad8142e7c8a6bf1ad3552b12fbb860885ea7f2d76c1f49f93a7c4bbbe7", ) .unwrap(); - let inp1_sig = Vec::::from_hex("3044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa01").unwrap(); + let inp1_sig = hex::hex!("3044022017c696503f5e1539fe5cb8dd05f793bd3b6e39f193028a7299a80c94c817a02d022007889009088f46cd9d9f4d137815704170410f53d503b68c1e020292a85b93fa01").to_vec(); let inp1_pk = PublicKey::from_str( "03df8f51c053ba0dfb443cce9793b6dc3339ffb0ce97af4792dade3aae1eb890f6", ) diff --git a/examples/tx.rs b/examples/tx.rs index 3144c3e7..6e889809 100644 --- a/examples/tx.rs +++ b/examples/tx.rs @@ -9,12 +9,12 @@ use elements::{Transaction, TxOutWitness}; use elements::{AssetId, confidential, TxOut}; use elements::encode::deserialize; -use elements::hex::FromHex; +use elements::hex; fn main() { let secp = secp256k1_zkp::Secp256k1::new(); - let tx: Transaction = deserialize(&Vec::::from_hex("0200000001015f2d99582ea16cc9451e8f9e19bdfedf43379ad0ad1fafb8ff66d22359017f020000000000fdffffff030a49492a5168e8cd96aa97f60f5b294cec1ca476ba2f8c1b4c87171f274422e99d08b3b32e88a1df9b226722afe3ad85304ac33f011199fd5cc84fa3c952fd4327a90325221684f36be833d1641c5ede4e72ee065ff8e5151604e123116de12e4e44d4160014d567c426a83a1e920a93d3b5cdc0362f80c5a96c0b4c3cf42cf177683e412511dbe585bff4021abab3e3d0a3b7de0e6c9109b0366609bec8fa07871b09ee66577ade9d47bf71189f94dcd31b313c014fb9baae678554035708296db5b49bc05e8e011b0be421f75438b839c6be86f3f9904c64d4515dbd160014a9cef783b24f4df35aaf6331427713acaa4a5d9d01230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000000f60000650000000000000043010001c57cafd385e2d848774a87f19409fd61500c10841b5bde34c89b928d81b9a76ffc5c999184465faf5c91377b1edb2d6aaa0168805bed16bff7a065bdbdd60935fd4e1060330000000000000001efe38f01b2cd1dba9db6a3478dae64e5a4210307895791c9bd31d4d4dddda68a10e9a660a93151c6a41bfc9711e07c7a338a135f0dbfe4b3254c43e6a4ae7c0caf0a61ed7263d68c6df68f62c980ba8bcdb7d20d3ebaa924423c6df9658ed73c11e672a9b20adb560fb8de9acdcee91324d0f86242163f17e11352cc336ece4854444fccdad0aab7f8bdc7d50bd248e606ffe612cd040c4837a5b659e34d221cdda13598f12903b3930f4acbba8a7596f4d91635e94aa8857f6c6ccb8b19595fe25a81c0ab9b324333f03309ef797418bc971bc40bf7a1eec55e08785b7dcfdb108a3210eb9002fc77c3a69e368a3ad4b490cdb77b1f82af9e93a665f52b8b20be24c59e7b49535d2708f5f17fb985370d6f636c9178ae382b82f8b77ba287a22dcd057bc465a7d49944e847a480c20cd4ce9c9149a568b221a32c9ec7068da8fa149562a347dcacca61f2dc75eb477c5bed669cdf28b907f827d7f6ba7f22100937a5595556fafd43664a54aecf3d502bbf57458bc74b77ddc7880fad23f4f384fdd965bbb2d3c339864a494b3e8a6cf00e5bb80134e9c815dfbd1bed4dd4c886f76ff50992bd493e58269536548d53876a952c002f58fff90582b8eb1629e885e39b529fdd73b188b2d492674aa56bc8bb4f2d983f86d7e484955e09c2cd42bf2f5c1091a2f675700fc689552e580cf074826e12970c8e1023b9e50c9c4236a904e77b7c9733cb47be4467bfbfec59c2b82be8d5d00383bb4e8ba11691f0fc4853c953979c2fd213abf3fdf523b5258002ea89a0de0db9799d78860580b2fd81e7ceecc0555476fd300f632d12c877f104cc8aac7a1f4c71cba1da9e4d22aafa5bbc4666d5942960399916037b106ff5d527c322eed885429a81fd2ee81edf8b7caf8c2ddc40536f6f800b2d6275dd5df471d7d3aab5285bff6250129661a43ac32ba10d442847365ba7e955d646bf0ae2df07d264a49731493bf14a90199a7f72d37b241b78db1bf8af6d1bbb04064b6bf86ce7c7b543fddaf18d890c57b3fef59d2cc098b174d229d1361b7dfe5b669166b4b3f91e170983fb60c05094bbcc4ea682da6979ab72de6a281f82ab3bdd1f0e9431b70267c101979c7972c329be5694e030f784211a236c49bb38ca77f4389b591a1e2a5e49aaa556ea68b17f45591e4bd38d467356db029ba496b334f22945926ea959f3a07f657f8bcf086c36caaac97cc651a41dc2b53ce9b82a6cf0c126c1fba7f2ad35cdae353994de1456e9539ecf10b5c4eec9ad1ed5e05152dbcfa448c016d3af78794b68322a2b1ff2d1d81b4d0208eb7065c7791cd0f4046505db5a99c0448a3b8fb27bf9ba085d5a4b1b5206e876f6242bd1da01803321a4bcf71676a949996d2b46ccce6f1f1308fbc775051c5e841f243da64b4a91a27a7192d7579a21dabded2798c3b1e99bbd2aca6b7d1f4a3028e0c018aca143bdcd842bbaa8e4ef9d70f12bd7af3f15a6fc0ce958c134fa749b2dcb25a518535239f9dbebc1034f1fd7e74c3808cf53094da2370e518660b73503a787cd0fc87f02ede9a90d0364e07fccaa9238be9ef472b7abf2378676d75cee2d85e640885e28eb5ff0c730944835122065898df69fc37444da4825a4f2524053ba834c277dce029b9a145c7382d94d64df190a4fb1cecc057413643a56f6958f87511a5bb0dccb66cf7a52b6815a6251d9b2def2a532289ab9d5dc50be8d9d399ab858e0495c2c6d487551805ea8a70b70044816ea7f8e51390ab7a23c4a58ceab9a508fff0a66b4d1ada652689a77670572e5c0e0af3b3d9ebd14f507dc1e2e61c22e1ddbcf16ecb760e41343e851240df95e99eb33c8fe84d7509f6abd8a3a42e98dbbc59299d618706ae42c8edba2e1dd08714c446fe12720dc394e80b868c5f1bd8caecea8547410977247ac554d3b6054f6c866f08f692f873a0cc41c801486cc81ef3eaed06cceeaf9706d6b8da55beaeb7ae69151de494864e30e74cc92c8aabdf80e7c589a1e0e1862333810bb3195817ebe8006b7ccc60670ba8ff76f6b2ae767ff0bee689e5c417d1f8cd09a690e8e841a3cfb1f071f6282e3adce2770d1bca0fc02d2cf7c0cabe11b154c1186985a1bbc7a96c6ed5149a0ea6986498fd588bbbffccc453dca3d391d29946cab5832cfd70304a774e509099ba244dc7c044acfad786dbff6f5060ec87b8e5d722d1773a37d6cd363226084848756bf36c81edb4ac676e2abe9f013d12d697cdababfbd1cbbcc3ca7a5efd49d571579c69c0f16498e129acc6aae9c7b95b583683ca10e3490e031a34b0f01db351a151a8d57b78617c6d2501a1e36d6c35cf9f361c5d0becaa991855b4bcb58d2bdd3270042a686072ce551f3cc2dd62fc799b4f71146cc6ccad33cdf4e6ca11992a5e2f824581c7af09da4d4a83b486173025c0e43b4baa38391f76736c99aca3b370d5a80689f1a21790b012096b97a81df2ae2dd2f944630a6654051a4d02927ef414400e8f0de0088387fa2791046a2bf4447256eff6b5da0ceaba87c20f498dfdfb773aa22901bf2d7a5b622ebe2f7a7a8a6ec5a0eb80361c3cfe91e4939d57d32b0c2f678cfd828c0507e75ed4e1afb09a61be08366832d7c2bdd4b1f882e72bfc62fb33a5daec270fc6e30ae8922f81a3afbc5c5e1899ea1485b2f7379452b803cd47c2eb355261e323f07aa5917df219100ebd0e83b4e48530f459961f5b2dfb0f4bcd6fdbfdec88cb7327ffcf4ba88646c332ddb553e55b61ae2ab9ea7dde27a8ac1ce4bb179933c5b1abd1859a9b687d8fbdf34851abf04ea102952b9024b70b1d9ffd83801dc3b733a3f8b33bd7aa3fdb1a8ddc743f3022086ceae8f0f43398f8bf069ff46b24d32deaaaef3d4cb93f150053da8b4aa50d4c4b9415004eb34b98459e9664e8370dfd9c6aa447284a3d350b09f610fa4ac4662f792cbb5478f11637da553a3a52638d7f362281acf3a8901f7ce2dd6cbce21a40a94577608d1cb068ec62717f6927a79a8c768043f16af90e97ad3a466b6115a76137456736da941d51e13e53be95522e01cfb06ee8a102518ff1bf4af8856322463fd5e920c2a1ea2a7fd403a792c0c94121b0c2a1535440ddfc96a5b2ca44ea073a192e9a427ceb4665faf26b1764c6321d592b3157d8153a2cedb5175eaea0cfead8b137f9cda7335c4d642e71bfe5cae223684b1cc83dfcc2ece5505f701be1a3cceda62e78c853b01aa6232c9bc4f7926bbc75b30fa921a3c663bfcf7236b007bcd1edb7d6f8e804e6fbab804fbcd864daaff334698af6a8cc806fc83534e0e95bd5e30e56cee45cde30e0cef551625ba7ce2f4c679d939969e43856d092cf4bad04ec84569d3a46238f8238e88ec3eec0bace677e85d0f0c3ead4bbf8f52ff217362f18fa5e6898d5f3b62e833fb45b9f8b079dd4ac5f17d6f8856ee4787c6639643c4e5772c04bcf66fe3dbbd286afd51d6cdbcac9d786b3806ec618ca1ad4763e2e18955e43c778d22b7fb9acd76ac39864ac2c2728057e46a30485371f5be8e67b400432e71d833ff8304d77de0869d80fbe4d40abf02f3dc3ca4d2135c8b0fecae2da40a8c2149611231c059859b3e5304338a70f5e3303723b5b76c0386f5fe566cf95c78cb2b14d4ba675f3ab7d2db9431c753808b3b123509245d585fab9e0e7f9f1a302739745698953be4868107b8432c96cc082a2e93044a4ed65b4775b06f90208f8589506a702615878a6188b890adb69da7b2495cb55f65b256c8b2babf85f16d94e824cd3760eac63688e341e9a3f5f7ebfbe56d9dce37b90e2fea0bec87e5dde7b8d3a048368eab5ae2cdd7df69341f5213c780ea79598e96f407bd35ad8ae653bca954cc565dc5f9a5e28a821b5cc3ce981457b11eecf8c6ca7e65515a1c8bce3ac2e7303af1ad0e9b1a00983a03fbb0cfe52d85f5beb8bebd969f7ce2c5e57160873beba3a06cda0d99a1b3a887b443d82a6a14a33a69ee64059c65e41b01f6825cdbf73089f3977f02b6008879265720693afd1aeecfb6c050f9f38b75681982b0ae91164ff83cde04410274b2450cb6fcceef45365b2473aeabc075cf4108d94a584aed4fb48afe9c90add923883e27c6c202ca4bf323e8756127d628e09d13df0449006e7d14a73125673ed8a8661a19749e5a8a01d768f500f6fbf1af08a73b7ca99117aca1d521d46e16ba12d953cfc839b17702c6f4a333e6dba3cfe450ed330e48974e751d88fa76d73036b8aeb434375c2f1b65f1a1505ba194eb4f2238d2f4ffa39e9035143de33bbc710f473d6a37e92c7d341e010f2bb545d31b50debbffda7c327be59b9469e240e2b37ca93db3545644d619c2f3173f8f5d646b545c0bf86008933308e8bfc4e1c410d901f2b1e79c74594258113212a737b286a9ac3108ed059661680f11a9d0c8994fa1188ae27339d14595733009eff14607bbb77f407f7b08bcc9973104807a34f52c4ce675c8894b3e43be483713da3440393f6079670dccc7bf4f54d81638bc411c49ec794611bff52742aafc059ee5702e91cc748da13969a1476c904d3fc261ccb022a7409f8f1ae8fbd7c2a8506f3bb2ad84ff55c93998ba367531f1c3b411ac58549a31bf205c102c67351956eab23285cba63601fbfae5498bcdc10cc173937b395e437fcb79b16482b13d824ef597144a73b8f64cf853d9b49cc93c93ff45bf63cca325ad928ceaffd59e5e8762202cdd9f95def9e4ba2d92dbc4d13d25cbc1c7aa482b4ff08e2c92e66acc9ba1475f8ec56c1dfb80af495eedcc03ea0336f18cc76ea057f815e5d2a3ca88fbc293d014862c4b505fc5e7d72876d434029b9c003d97401f604eda90dbcd76350d80529496f55ad8003fbb85f7752df6ceaf9d9ffc3f60fc0bde381fca70306b17837a81e2429c85027a1b377682c0b554a8a78252636384f5559a77573b0070c3baa520d716263b385a0defd90c2384b7ebc564a030c33cd6997b472b43942e063e44817f28f5ca7d5a1ff48d80ab6703600a7dd11395a3f64d8683d47b7c9bb83723134f850b45e3038f9395faab53d6d6302cf9c1a693c86d978addd808807ae9f0dd87ea4e98129a0bd0f0813509764c213eac369692900b35063f0dcbf7bf5961d017bdde3a1ada42c24b71a8ec1f4e49257a35d575327a24ff6049444d4e125257aa7f4c20588d978eadafec231b242b158daa825e6aa5d67066c1f16c004c9e315162aa8c9bbcb254ca8e180c8a177d505b9962b2991f85cf235680df8ea3d531fa393497041736a032c68eee70bf92145b429a0ba825aab62a7e9f023b7c34c7aa4da2251415cafa0badbb046f661ad11718013378697e12eed08f02c21de96c5d0a2fee464b69e02c382f5967a3ce115f18f09e99c9216da22518f510555f44852c4d43cfd4bd4746bb955dec5629cf89c08816ea2d43585b95e5f7beba50200f7cff83d9415476daa7e99853b5fe9440db3aa610ec1f8420a212c5bd55a1f2a5cc674ea0dde9240a9010821b4e6edb312b1f480743bcccffbb8d4716317ac74a2217d6ea49de513838bbddd890a35aea5c5b47ec286389055202da360387bfb2327eb38a2ec5521680fbf7c54b20b0c4d21e2f23046939fe683d63bc60c9451d5985cb3d74ca56ec7d848037298f5acf7f3059ea5f73c5213408b458184d334bca66ddc792c674c626e6e3e2e366b2284b21cd8c134e0783e7494b5278dcc29af3b17d5609c04e1d6bf3f21670befce3fab0f7b2d9b7e6c46656bf423b500df83f2bfd0cc7502db1a3d8320235064708115f45b9ae7810ecaf73304e153662620a247d3d6d2d4251441c4dcdd14fb9b33f2f52f1b4a05fa1cd8e77c3c79178ae0ad961a9737c01a0ec073e4743010001662279b3e4efb9e9b04d9859d348dbdecaf42dcbe0664d7d035851e52630e9f537632b1b090f530aa6a9d3e001feb931eeea6006d339890fbbf481f842a96d05fd4e106033000000000000000198b771005818add879ce29234db70c78e5a9d046b424d5e2cab6e9499bd13df7432a9ee058a2454d33bc1ddef43b73de3a83eff603d0ba0686b127c6eb7f2c02c5d46b6d58a4fe22cbd3fa865bf378465d0133b2fafc47c9aaf56cde01dd065b2457911e889d4bf1f63e1575799ebeed4efa00edb19898b1b3d7e1eac163cfa25550e5ea917f0912d54aa9dd9980aa8757219e94e93325d126fd6f31fc3bb8784ff910cbaf274e46e62d42f1e25b8d78bea8498ebfd3cd52bbc41f971a50bb235d83d014e420a92969a24292aa2692021ebb7717691b1bd0bc81eb80c9ede4174e64352238ccce5efe4ff231db947cdd03b03786042cc7ca7cab2253850abf322cb98f039890a5ab690c0803e0692d2482e03a2cc56ef08f4e1cadf082764775ad8aa85bd380ee8ebedd4115b3a4513f3baa630ce21476ab129668994c7ae936f0b439be17e5a13326081d19ae36211992752e08549632cfeedd4b7effd2e07405baa70ac0cdd6accbc1c8f4b9f5b3d27e2ee3cced0254927d649a61ebec2d67ce51746911512e9c9547365ffe406d3604d67f6d8cad7dea01eebfbb32a986ea7b8b4d78d8df0a368c5da4039f53787369b1be5ed937e8608cd115a7d54c6e3819c34014e0a3b69e192e7f195cb570add2b1c583017834d20f5f2b83038859a2888344eb6ac38a2f9f1e7aa7468454351c9df871c802060525844e72cadcce258469dff954aca0403efa569212e348440b35a94f75fbf237d9508f406f6b88dcb76c46108371c969518f46c32590ce4a527500564e2504401a8b74c5edda5c2037b5e43ba1682916c5e4bedfd559b475e6b9afacd2bf4bc2861497c3154b684dd5669b80c1548114feff221b4ba6fa9630f15a348942a5ff0fc1b6b7bbaf10de7e9268b3f3059895bad350eab5e6678eb379c78b7cca0a19206fe2fb51b9543eafe174af2007badb1a86ac43ee32386150ebc1ab27123dedafa2a3b7e6e6ce4b6c4686529a157fed25c4ae5f7e44e0f63bad17c8d7c88b507280c03e952b7af36962381699150a15dae23aec75d78708bf9aab8f9197d6d3ad97d179d0d7890e16fae101fd57d49d17e090c01ac5b72d53111df514917c735926fe66665b7ac08ad1249f99e1d0fd1bd2c11f32a5edf273dac9a9d904abab6551745f71cdd2bcf5b114c31bec42b4f7078e5da4076e140f6370133b593366786bf10be1dbe9dc411bca1b7ec80587bf7735ecd3e3dbaca3855a9df3b01782ef6c009a916b597ac1b968040c0fb2054c7685ff34851a2f0153ea1f9f0aea6781234b7848148e03fb0f067d77e272ac86a59cbd54a501fa763be2c3bc8f083ad2accbb3d8b2cfb933823510b5b86b7ba22724511eebd7c497dd6b79243c5985054fd01b1328f7dcee2d6e7090bda4763e7d0aca6fa7a283a84be84ab15aa95beb1b4b5d6760f39e42ed72d69f7ab0c6740e92a14ef3490cc5d610bcdf0300a8192a2bba672c3971782ff9847e7a6d479896d87e9d5e95fc1158cf6e30d44697be519ea5d312855e3ee7205cbfc1e496cd8909a46e8e167b3d8bbb61a824340ed8cb434ebca7789ed0430d85fdb7548840e42a63e5d201bb77bb66f9c515fc7ed6d812916962adfd42f621ee50cdfed8b9593d747e094e618c94f8198707c598f1c1ad019aeb7fee68c72e66656f43b56f443014986c0d3c7446500999316ae004082843accea6fb833c893046094dd2b995d84e4cd74789956a5289d6ad4ff2a766d0e7a64d91cc7f7dc6f225fbc27ca0f2d30e6d2ba6105e5e04aa6c261ccc0a0dad14311863c6bb863858707779f6a708c5feb9c55b612452ba50c10472b18b5e0abf69f019f4b90246b2d36795b598a809a4599412623d810c94baca6c369a82dffae8c711fc2d105e92a8d7b4c244f3eecdeca19698e79f83462d6870d0b91fa926331dea367a418be40b1d7d530b1f239b77b893bc5a4525013252cf199a3c66166eeab9e7876cb47a0d6f4cc9df5c83bdc5230a345b44a4c7362e02a091fda5d7ff731d73bd7bbcf3092494eb7e873f976a2015f3631dd0faf76c0f54159dfcb6796fd5144c3e31c998ad5b6028b9182445e9e25faa8a8b5c332a19947d5cb14c2a1dfb76313d711a2eea0ca56c4b4c9edb8cfd089f03672a499e6419fca6914052f7d0176bb2e607c2fc6a3de7e58c3f63ac54f2122af3a9135d5e58b28918b9c481f9f8b94a76c5b2cb790df5e726a6b4c24dd56809d3ba683941fbe3f4334e62d37990aa4b64efa848404cb090cf98d254f0cc8ef48090a46997c64fe4b129ac84663bfc2b0a25a02bc5898a199643af41cbad18631c5db596048cb1bb89f0ea9243ec8f72ee67a6a95eb751ba7f59ded999f2875ca40082a72b62f9bdec52142562d0a48c50730a940db9613596ebbd359237fea5ad701fb2b68bd64f0fbdc2485a8102444fd321777a6e22f093e15dc23eb158035054681053c2035326135e407681a633370138fc265a7cda97825423b08f7955cff40bf4590b38e482bd388741c17a3d79a40662fb41fd760e15f4b58d540fb66b3ad698365c339d8fc6babfb7d3b039af01a840859f9ac7ede34cca3d9fa2efe8eeb7c804b02225d039aa1db5a18dfbb96445742e08e643d897e3db984bce40167997547657432c88c81005d1eba0a5c2b27bbf2fe3f92dfdd0d59a49a1432d2352e912480b8a76b7618576b6db40a57af5d5bf3f2df7bf01e30f8b823a4b714c39082afc4f2f1ec198586ae3db5d5557fb054ab069680736da45187f264ef8d9a45d4b8d0eb9a54f5f074a9c5b6fd8d82550f290e599e3a73c0eac52dd94dc918ae4b985f6863a5783d764662ce64a0d3eafe619e1ffdaa3faf4a6985dfe6a58f7a132ddf896d9a757349b0a51d10432730111c391d926b96fa605714c7dbb1719d868fb7ef6995d63d4d5619653e865dcff21bc8713e6093daab77f2acf5491a66244d9d46335da8a16f63e2d296e83f540f5e4f574f1a5a1500a20a8190b0bbf60f0b401a4a5c333edd38728866bf26ac44ebaf7f41356c8fd60f1bd60112a0d9715c11c9b271d2b7a3cede68f4a88790c47ae1b027700cc9edc1a9a63f8f63b796e9ff2773d5138bc8d1fc98a84a7624b3cd5d04d6a11d4e55e08ad2f69f1f90cbca0a1db3f53008bb85f155385de4bd312af8920b1c63489525b9e0a97bc5eb54b1ef6173af2950559e9f56b24374a61c96458184ceabc34ac24021c26ba82c3e3687a3d8a8e28ec3aa563c94ac9125ae8b0b9881e071b8c862827970028e55cf0c7821411c824a5c4da44fbdee147c86f943b718387c8232291fc844a89aab8466736296b930fe971d0346527dcc71090ae165c7a8e8edc2c72a9af00d5c3fcd52ba9253ac15132045fd311203339e782c6e54ff26e3a950f2430f74961f554593c7c435ee5a79a0a0bef3bdc347ea7faa6b3e4579adafeff126d6ded61b116d20c2fa9e5b020f71395c4d1efc8f18adae9f5326d52962b0862793fc889d984069631cae5d4295aceea308881579e1c313cd09833d67097c247def9cca36eb72a0e069dfb30ec4e14148196b08fd416de071cbac34895c13b754f354af6aeffcb6d64531e48becab49697177ebe29d550c17f22626d9d073d0c40c5151d99ecf52a51cc47d6c2c2bc2087fd94b8ab3452eb3acdd0a2e091fa3fe7baccb70e69348854504562752cb5489fd65765719108e5f6387f231e72a61f33ad1f50580519f9e6693695c767cc7f0a60a9b6927630e874f7ad8a072ad1ea326c8b65d51b0cf247d83acbc6efde4628581bda8449c5278ba69115c6d0e40531cd19783c34ff963204830cadd81e263062521ce8cd1559bcff6fcd4b331238e8620348b494fd9248ef2f364fa9f836abec7b499685ec7d03287042a8ef3d68292d27fafad43c78d3564ec4415e1549471bb4c93957be34315b81ad020ee257fe8e6f8c6b8f429257bbc91015ff376ef698d4236c7d925aabd87fb8c50c737cfd4dd37791b1c43d7d925dda0af5cef8e5828993dff41d4019e61152b20017f18723d6f8589a72ee6aa61df954b11a094dfee7f8de82b4c6e0b8378cdc20965297622ee78b665df2fc9e0a59e2416d8101aab95a72d5ec8c6bacc46b8b052454bed1b1155e323c778b76cc12c4337a0456479e99cd954ee9b7a610ef2fdd85115c8761e48a15ee0dc75a1c44a0595783ee7a3b3f0be27bd901f1118ffd7967aa98fef47180b3c7314a238223aa468b3acd5c568ea74934fdc10b06f42b18b23d7a425cb4180a5f5e76de3f54064df11ff9cee21403be789639ea2946e88ecc81bcb492adf6d7652a600ca07d614a0916c89eee9348ab1e356e153bc37434e37bc7e581bb797251198ffc955e555ee20ce6118f175166ab25e25cbc847b825f969a66085f745eb64ad7ab1e193a7dadf466c29eff0ded9a9a82323f1d0ab88134ada28d3691e98e90ceeaec3369d466e24526e4eee3255e0266318c2851476b98af959eeacafd88994d597c52afd23d22578876cadbe26026e10753aef97ed889dd436d0e9369bafc8cd50dd0b6090cc3944b81063bbada167cebcab6866fb3b87791b6dff1de3b2aab67397df70c60ebefa9389e741fd5337113a1da0d7ccf733348eb91cf40d0c323baa3f692f9b45881efb66edaf4ea7ac6d88b6a93fb7237f6a9bb43902ccdb2ea3e6a342abfaa5e36d9b685bb1a97f0a2b94a69c674935fad7b38d7702bdff95d3aca3895f3b05c70cf1754cacc5980610f09b6e2cb3e89311638fd4b271805efc7486d2c4f0cf0910598427c66627c74ae12f29b63a7ad778e0aaa38f7b1cc23189603d01891ba26c14e4e96c0f7c86e63c73d8d1098661540b4daf2424c89be4991f07ed284a8765d92c6b52c080bdf62bca1428a018352baa32571d8d36da5653a91415dfe8d0c4aa46ed6766f4c162a05ddbccdf14ca9f84e2d487199467f338e81f3f5058bcd22e96a04119d036de1ceb872ca05954e53c86b85626a44856e5685fe35d8217af87349d24650059e00ec7b80d7c0496950a1c827f443db6933a756723cd529c25d7a93e3be32666bf2d20f533d6b3e1378296cafa3b468a3926e7754781923b12d9701bad179da601a623e25f76731a98e93712415496ea84f88dffd243f7ec9a480cc22358bb6705d46be5807e3aa49019e16f86d0c35af6c6e6f7019cc38f5dee215298ae1319bcf248aed114fdb0a5b342b8d250fdbc3bd5ba21e3232a7655bf424eaed8c810b6b1912fa31e37399a56aa33a9a6a76974175ac96b67c43c1ecfeb5de2b0c7b8d4f29993def838ace907acee23a1a7fb52d53078a4d544c858ba18412f152f9596b31a15107e428c96175b5fd49dafda407a0c86bfc9ff6a44217a635bbe6c672c85156f21ec664465ca9e6b9e2e4636aaf6c7d02a9cc28907f5b84d08b1a0a216c8a8494f165a637f5d4edcd0e272390d8704840cd62846db58c4f4c118f19ae3087d9198a05f8b2b256cbe176bc9604df06bda9b7e49d7ded17a059f32b28e1ed47421f32d425004261ce060a2e6af1b7f583f9d7b6e887103df1c359f9d043fdcf91220c57c438fe37b6e606492850ae87dd6f0fc4339777202464dd8ba10e119775ec36daffcca9aebe2208249ffb7068009612a15fd4ee01fb564b567c7c31a5179f88bd1e71d4bd0771b51651ed98ea4bead8deb759c86b2d705d16f4335457b0c9d3b0e9cff91f8df33f265600bd0cc8e8128918456726dfd3cbd8b8c45b21506dab2c49975e10440a0673bee73c2d757f48ea9e4c8de2c4a6eeb55d3127c78b95c2f13b4b0f66c9ddfaf6d28ca7070a6b713d28e8ecb64d175b2a4e8151323f0f9e1769b4ca1228f7d555ed851aacfd6bb782629e6f38aae70000").unwrap()).unwrap(); + let tx: Transaction = deserialize(&hex::hex!("0200000001015f2d99582ea16cc9451e8f9e19bdfedf43379ad0ad1fafb8ff66d22359017f020000000000fdffffff030a49492a5168e8cd96aa97f60f5b294cec1ca476ba2f8c1b4c87171f274422e99d08b3b32e88a1df9b226722afe3ad85304ac33f011199fd5cc84fa3c952fd4327a90325221684f36be833d1641c5ede4e72ee065ff8e5151604e123116de12e4e44d4160014d567c426a83a1e920a93d3b5cdc0362f80c5a96c0b4c3cf42cf177683e412511dbe585bff4021abab3e3d0a3b7de0e6c9109b0366609bec8fa07871b09ee66577ade9d47bf71189f94dcd31b313c014fb9baae678554035708296db5b49bc05e8e011b0be421f75438b839c6be86f3f9904c64d4515dbd160014a9cef783b24f4df35aaf6331427713acaa4a5d9d01230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000000f60000650000000000000043010001c57cafd385e2d848774a87f19409fd61500c10841b5bde34c89b928d81b9a76ffc5c999184465faf5c91377b1edb2d6aaa0168805bed16bff7a065bdbdd60935fd4e1060330000000000000001efe38f01b2cd1dba9db6a3478dae64e5a4210307895791c9bd31d4d4dddda68a10e9a660a93151c6a41bfc9711e07c7a338a135f0dbfe4b3254c43e6a4ae7c0caf0a61ed7263d68c6df68f62c980ba8bcdb7d20d3ebaa924423c6df9658ed73c11e672a9b20adb560fb8de9acdcee91324d0f86242163f17e11352cc336ece4854444fccdad0aab7f8bdc7d50bd248e606ffe612cd040c4837a5b659e34d221cdda13598f12903b3930f4acbba8a7596f4d91635e94aa8857f6c6ccb8b19595fe25a81c0ab9b324333f03309ef797418bc971bc40bf7a1eec55e08785b7dcfdb108a3210eb9002fc77c3a69e368a3ad4b490cdb77b1f82af9e93a665f52b8b20be24c59e7b49535d2708f5f17fb985370d6f636c9178ae382b82f8b77ba287a22dcd057bc465a7d49944e847a480c20cd4ce9c9149a568b221a32c9ec7068da8fa149562a347dcacca61f2dc75eb477c5bed669cdf28b907f827d7f6ba7f22100937a5595556fafd43664a54aecf3d502bbf57458bc74b77ddc7880fad23f4f384fdd965bbb2d3c339864a494b3e8a6cf00e5bb80134e9c815dfbd1bed4dd4c886f76ff50992bd493e58269536548d53876a952c002f58fff90582b8eb1629e885e39b529fdd73b188b2d492674aa56bc8bb4f2d983f86d7e484955e09c2cd42bf2f5c1091a2f675700fc689552e580cf074826e12970c8e1023b9e50c9c4236a904e77b7c9733cb47be4467bfbfec59c2b82be8d5d00383bb4e8ba11691f0fc4853c953979c2fd213abf3fdf523b5258002ea89a0de0db9799d78860580b2fd81e7ceecc0555476fd300f632d12c877f104cc8aac7a1f4c71cba1da9e4d22aafa5bbc4666d5942960399916037b106ff5d527c322eed885429a81fd2ee81edf8b7caf8c2ddc40536f6f800b2d6275dd5df471d7d3aab5285bff6250129661a43ac32ba10d442847365ba7e955d646bf0ae2df07d264a49731493bf14a90199a7f72d37b241b78db1bf8af6d1bbb04064b6bf86ce7c7b543fddaf18d890c57b3fef59d2cc098b174d229d1361b7dfe5b669166b4b3f91e170983fb60c05094bbcc4ea682da6979ab72de6a281f82ab3bdd1f0e9431b70267c101979c7972c329be5694e030f784211a236c49bb38ca77f4389b591a1e2a5e49aaa556ea68b17f45591e4bd38d467356db029ba496b334f22945926ea959f3a07f657f8bcf086c36caaac97cc651a41dc2b53ce9b82a6cf0c126c1fba7f2ad35cdae353994de1456e9539ecf10b5c4eec9ad1ed5e05152dbcfa448c016d3af78794b68322a2b1ff2d1d81b4d0208eb7065c7791cd0f4046505db5a99c0448a3b8fb27bf9ba085d5a4b1b5206e876f6242bd1da01803321a4bcf71676a949996d2b46ccce6f1f1308fbc775051c5e841f243da64b4a91a27a7192d7579a21dabded2798c3b1e99bbd2aca6b7d1f4a3028e0c018aca143bdcd842bbaa8e4ef9d70f12bd7af3f15a6fc0ce958c134fa749b2dcb25a518535239f9dbebc1034f1fd7e74c3808cf53094da2370e518660b73503a787cd0fc87f02ede9a90d0364e07fccaa9238be9ef472b7abf2378676d75cee2d85e640885e28eb5ff0c730944835122065898df69fc37444da4825a4f2524053ba834c277dce029b9a145c7382d94d64df190a4fb1cecc057413643a56f6958f87511a5bb0dccb66cf7a52b6815a6251d9b2def2a532289ab9d5dc50be8d9d399ab858e0495c2c6d487551805ea8a70b70044816ea7f8e51390ab7a23c4a58ceab9a508fff0a66b4d1ada652689a77670572e5c0e0af3b3d9ebd14f507dc1e2e61c22e1ddbcf16ecb760e41343e851240df95e99eb33c8fe84d7509f6abd8a3a42e98dbbc59299d618706ae42c8edba2e1dd08714c446fe12720dc394e80b868c5f1bd8caecea8547410977247ac554d3b6054f6c866f08f692f873a0cc41c801486cc81ef3eaed06cceeaf9706d6b8da55beaeb7ae69151de494864e30e74cc92c8aabdf80e7c589a1e0e1862333810bb3195817ebe8006b7ccc60670ba8ff76f6b2ae767ff0bee689e5c417d1f8cd09a690e8e841a3cfb1f071f6282e3adce2770d1bca0fc02d2cf7c0cabe11b154c1186985a1bbc7a96c6ed5149a0ea6986498fd588bbbffccc453dca3d391d29946cab5832cfd70304a774e509099ba244dc7c044acfad786dbff6f5060ec87b8e5d722d1773a37d6cd363226084848756bf36c81edb4ac676e2abe9f013d12d697cdababfbd1cbbcc3ca7a5efd49d571579c69c0f16498e129acc6aae9c7b95b583683ca10e3490e031a34b0f01db351a151a8d57b78617c6d2501a1e36d6c35cf9f361c5d0becaa991855b4bcb58d2bdd3270042a686072ce551f3cc2dd62fc799b4f71146cc6ccad33cdf4e6ca11992a5e2f824581c7af09da4d4a83b486173025c0e43b4baa38391f76736c99aca3b370d5a80689f1a21790b012096b97a81df2ae2dd2f944630a6654051a4d02927ef414400e8f0de0088387fa2791046a2bf4447256eff6b5da0ceaba87c20f498dfdfb773aa22901bf2d7a5b622ebe2f7a7a8a6ec5a0eb80361c3cfe91e4939d57d32b0c2f678cfd828c0507e75ed4e1afb09a61be08366832d7c2bdd4b1f882e72bfc62fb33a5daec270fc6e30ae8922f81a3afbc5c5e1899ea1485b2f7379452b803cd47c2eb355261e323f07aa5917df219100ebd0e83b4e48530f459961f5b2dfb0f4bcd6fdbfdec88cb7327ffcf4ba88646c332ddb553e55b61ae2ab9ea7dde27a8ac1ce4bb179933c5b1abd1859a9b687d8fbdf34851abf04ea102952b9024b70b1d9ffd83801dc3b733a3f8b33bd7aa3fdb1a8ddc743f3022086ceae8f0f43398f8bf069ff46b24d32deaaaef3d4cb93f150053da8b4aa50d4c4b9415004eb34b98459e9664e8370dfd9c6aa447284a3d350b09f610fa4ac4662f792cbb5478f11637da553a3a52638d7f362281acf3a8901f7ce2dd6cbce21a40a94577608d1cb068ec62717f6927a79a8c768043f16af90e97ad3a466b6115a76137456736da941d51e13e53be95522e01cfb06ee8a102518ff1bf4af8856322463fd5e920c2a1ea2a7fd403a792c0c94121b0c2a1535440ddfc96a5b2ca44ea073a192e9a427ceb4665faf26b1764c6321d592b3157d8153a2cedb5175eaea0cfead8b137f9cda7335c4d642e71bfe5cae223684b1cc83dfcc2ece5505f701be1a3cceda62e78c853b01aa6232c9bc4f7926bbc75b30fa921a3c663bfcf7236b007bcd1edb7d6f8e804e6fbab804fbcd864daaff334698af6a8cc806fc83534e0e95bd5e30e56cee45cde30e0cef551625ba7ce2f4c679d939969e43856d092cf4bad04ec84569d3a46238f8238e88ec3eec0bace677e85d0f0c3ead4bbf8f52ff217362f18fa5e6898d5f3b62e833fb45b9f8b079dd4ac5f17d6f8856ee4787c6639643c4e5772c04bcf66fe3dbbd286afd51d6cdbcac9d786b3806ec618ca1ad4763e2e18955e43c778d22b7fb9acd76ac39864ac2c2728057e46a30485371f5be8e67b400432e71d833ff8304d77de0869d80fbe4d40abf02f3dc3ca4d2135c8b0fecae2da40a8c2149611231c059859b3e5304338a70f5e3303723b5b76c0386f5fe566cf95c78cb2b14d4ba675f3ab7d2db9431c753808b3b123509245d585fab9e0e7f9f1a302739745698953be4868107b8432c96cc082a2e93044a4ed65b4775b06f90208f8589506a702615878a6188b890adb69da7b2495cb55f65b256c8b2babf85f16d94e824cd3760eac63688e341e9a3f5f7ebfbe56d9dce37b90e2fea0bec87e5dde7b8d3a048368eab5ae2cdd7df69341f5213c780ea79598e96f407bd35ad8ae653bca954cc565dc5f9a5e28a821b5cc3ce981457b11eecf8c6ca7e65515a1c8bce3ac2e7303af1ad0e9b1a00983a03fbb0cfe52d85f5beb8bebd969f7ce2c5e57160873beba3a06cda0d99a1b3a887b443d82a6a14a33a69ee64059c65e41b01f6825cdbf73089f3977f02b6008879265720693afd1aeecfb6c050f9f38b75681982b0ae91164ff83cde04410274b2450cb6fcceef45365b2473aeabc075cf4108d94a584aed4fb48afe9c90add923883e27c6c202ca4bf323e8756127d628e09d13df0449006e7d14a73125673ed8a8661a19749e5a8a01d768f500f6fbf1af08a73b7ca99117aca1d521d46e16ba12d953cfc839b17702c6f4a333e6dba3cfe450ed330e48974e751d88fa76d73036b8aeb434375c2f1b65f1a1505ba194eb4f2238d2f4ffa39e9035143de33bbc710f473d6a37e92c7d341e010f2bb545d31b50debbffda7c327be59b9469e240e2b37ca93db3545644d619c2f3173f8f5d646b545c0bf86008933308e8bfc4e1c410d901f2b1e79c74594258113212a737b286a9ac3108ed059661680f11a9d0c8994fa1188ae27339d14595733009eff14607bbb77f407f7b08bcc9973104807a34f52c4ce675c8894b3e43be483713da3440393f6079670dccc7bf4f54d81638bc411c49ec794611bff52742aafc059ee5702e91cc748da13969a1476c904d3fc261ccb022a7409f8f1ae8fbd7c2a8506f3bb2ad84ff55c93998ba367531f1c3b411ac58549a31bf205c102c67351956eab23285cba63601fbfae5498bcdc10cc173937b395e437fcb79b16482b13d824ef597144a73b8f64cf853d9b49cc93c93ff45bf63cca325ad928ceaffd59e5e8762202cdd9f95def9e4ba2d92dbc4d13d25cbc1c7aa482b4ff08e2c92e66acc9ba1475f8ec56c1dfb80af495eedcc03ea0336f18cc76ea057f815e5d2a3ca88fbc293d014862c4b505fc5e7d72876d434029b9c003d97401f604eda90dbcd76350d80529496f55ad8003fbb85f7752df6ceaf9d9ffc3f60fc0bde381fca70306b17837a81e2429c85027a1b377682c0b554a8a78252636384f5559a77573b0070c3baa520d716263b385a0defd90c2384b7ebc564a030c33cd6997b472b43942e063e44817f28f5ca7d5a1ff48d80ab6703600a7dd11395a3f64d8683d47b7c9bb83723134f850b45e3038f9395faab53d6d6302cf9c1a693c86d978addd808807ae9f0dd87ea4e98129a0bd0f0813509764c213eac369692900b35063f0dcbf7bf5961d017bdde3a1ada42c24b71a8ec1f4e49257a35d575327a24ff6049444d4e125257aa7f4c20588d978eadafec231b242b158daa825e6aa5d67066c1f16c004c9e315162aa8c9bbcb254ca8e180c8a177d505b9962b2991f85cf235680df8ea3d531fa393497041736a032c68eee70bf92145b429a0ba825aab62a7e9f023b7c34c7aa4da2251415cafa0badbb046f661ad11718013378697e12eed08f02c21de96c5d0a2fee464b69e02c382f5967a3ce115f18f09e99c9216da22518f510555f44852c4d43cfd4bd4746bb955dec5629cf89c08816ea2d43585b95e5f7beba50200f7cff83d9415476daa7e99853b5fe9440db3aa610ec1f8420a212c5bd55a1f2a5cc674ea0dde9240a9010821b4e6edb312b1f480743bcccffbb8d4716317ac74a2217d6ea49de513838bbddd890a35aea5c5b47ec286389055202da360387bfb2327eb38a2ec5521680fbf7c54b20b0c4d21e2f23046939fe683d63bc60c9451d5985cb3d74ca56ec7d848037298f5acf7f3059ea5f73c5213408b458184d334bca66ddc792c674c626e6e3e2e366b2284b21cd8c134e0783e7494b5278dcc29af3b17d5609c04e1d6bf3f21670befce3fab0f7b2d9b7e6c46656bf423b500df83f2bfd0cc7502db1a3d8320235064708115f45b9ae7810ecaf73304e153662620a247d3d6d2d4251441c4dcdd14fb9b33f2f52f1b4a05fa1cd8e77c3c79178ae0ad961a9737c01a0ec073e4743010001662279b3e4efb9e9b04d9859d348dbdecaf42dcbe0664d7d035851e52630e9f537632b1b090f530aa6a9d3e001feb931eeea6006d339890fbbf481f842a96d05fd4e106033000000000000000198b771005818add879ce29234db70c78e5a9d046b424d5e2cab6e9499bd13df7432a9ee058a2454d33bc1ddef43b73de3a83eff603d0ba0686b127c6eb7f2c02c5d46b6d58a4fe22cbd3fa865bf378465d0133b2fafc47c9aaf56cde01dd065b2457911e889d4bf1f63e1575799ebeed4efa00edb19898b1b3d7e1eac163cfa25550e5ea917f0912d54aa9dd9980aa8757219e94e93325d126fd6f31fc3bb8784ff910cbaf274e46e62d42f1e25b8d78bea8498ebfd3cd52bbc41f971a50bb235d83d014e420a92969a24292aa2692021ebb7717691b1bd0bc81eb80c9ede4174e64352238ccce5efe4ff231db947cdd03b03786042cc7ca7cab2253850abf322cb98f039890a5ab690c0803e0692d2482e03a2cc56ef08f4e1cadf082764775ad8aa85bd380ee8ebedd4115b3a4513f3baa630ce21476ab129668994c7ae936f0b439be17e5a13326081d19ae36211992752e08549632cfeedd4b7effd2e07405baa70ac0cdd6accbc1c8f4b9f5b3d27e2ee3cced0254927d649a61ebec2d67ce51746911512e9c9547365ffe406d3604d67f6d8cad7dea01eebfbb32a986ea7b8b4d78d8df0a368c5da4039f53787369b1be5ed937e8608cd115a7d54c6e3819c34014e0a3b69e192e7f195cb570add2b1c583017834d20f5f2b83038859a2888344eb6ac38a2f9f1e7aa7468454351c9df871c802060525844e72cadcce258469dff954aca0403efa569212e348440b35a94f75fbf237d9508f406f6b88dcb76c46108371c969518f46c32590ce4a527500564e2504401a8b74c5edda5c2037b5e43ba1682916c5e4bedfd559b475e6b9afacd2bf4bc2861497c3154b684dd5669b80c1548114feff221b4ba6fa9630f15a348942a5ff0fc1b6b7bbaf10de7e9268b3f3059895bad350eab5e6678eb379c78b7cca0a19206fe2fb51b9543eafe174af2007badb1a86ac43ee32386150ebc1ab27123dedafa2a3b7e6e6ce4b6c4686529a157fed25c4ae5f7e44e0f63bad17c8d7c88b507280c03e952b7af36962381699150a15dae23aec75d78708bf9aab8f9197d6d3ad97d179d0d7890e16fae101fd57d49d17e090c01ac5b72d53111df514917c735926fe66665b7ac08ad1249f99e1d0fd1bd2c11f32a5edf273dac9a9d904abab6551745f71cdd2bcf5b114c31bec42b4f7078e5da4076e140f6370133b593366786bf10be1dbe9dc411bca1b7ec80587bf7735ecd3e3dbaca3855a9df3b01782ef6c009a916b597ac1b968040c0fb2054c7685ff34851a2f0153ea1f9f0aea6781234b7848148e03fb0f067d77e272ac86a59cbd54a501fa763be2c3bc8f083ad2accbb3d8b2cfb933823510b5b86b7ba22724511eebd7c497dd6b79243c5985054fd01b1328f7dcee2d6e7090bda4763e7d0aca6fa7a283a84be84ab15aa95beb1b4b5d6760f39e42ed72d69f7ab0c6740e92a14ef3490cc5d610bcdf0300a8192a2bba672c3971782ff9847e7a6d479896d87e9d5e95fc1158cf6e30d44697be519ea5d312855e3ee7205cbfc1e496cd8909a46e8e167b3d8bbb61a824340ed8cb434ebca7789ed0430d85fdb7548840e42a63e5d201bb77bb66f9c515fc7ed6d812916962adfd42f621ee50cdfed8b9593d747e094e618c94f8198707c598f1c1ad019aeb7fee68c72e66656f43b56f443014986c0d3c7446500999316ae004082843accea6fb833c893046094dd2b995d84e4cd74789956a5289d6ad4ff2a766d0e7a64d91cc7f7dc6f225fbc27ca0f2d30e6d2ba6105e5e04aa6c261ccc0a0dad14311863c6bb863858707779f6a708c5feb9c55b612452ba50c10472b18b5e0abf69f019f4b90246b2d36795b598a809a4599412623d810c94baca6c369a82dffae8c711fc2d105e92a8d7b4c244f3eecdeca19698e79f83462d6870d0b91fa926331dea367a418be40b1d7d530b1f239b77b893bc5a4525013252cf199a3c66166eeab9e7876cb47a0d6f4cc9df5c83bdc5230a345b44a4c7362e02a091fda5d7ff731d73bd7bbcf3092494eb7e873f976a2015f3631dd0faf76c0f54159dfcb6796fd5144c3e31c998ad5b6028b9182445e9e25faa8a8b5c332a19947d5cb14c2a1dfb76313d711a2eea0ca56c4b4c9edb8cfd089f03672a499e6419fca6914052f7d0176bb2e607c2fc6a3de7e58c3f63ac54f2122af3a9135d5e58b28918b9c481f9f8b94a76c5b2cb790df5e726a6b4c24dd56809d3ba683941fbe3f4334e62d37990aa4b64efa848404cb090cf98d254f0cc8ef48090a46997c64fe4b129ac84663bfc2b0a25a02bc5898a199643af41cbad18631c5db596048cb1bb89f0ea9243ec8f72ee67a6a95eb751ba7f59ded999f2875ca40082a72b62f9bdec52142562d0a48c50730a940db9613596ebbd359237fea5ad701fb2b68bd64f0fbdc2485a8102444fd321777a6e22f093e15dc23eb158035054681053c2035326135e407681a633370138fc265a7cda97825423b08f7955cff40bf4590b38e482bd388741c17a3d79a40662fb41fd760e15f4b58d540fb66b3ad698365c339d8fc6babfb7d3b039af01a840859f9ac7ede34cca3d9fa2efe8eeb7c804b02225d039aa1db5a18dfbb96445742e08e643d897e3db984bce40167997547657432c88c81005d1eba0a5c2b27bbf2fe3f92dfdd0d59a49a1432d2352e912480b8a76b7618576b6db40a57af5d5bf3f2df7bf01e30f8b823a4b714c39082afc4f2f1ec198586ae3db5d5557fb054ab069680736da45187f264ef8d9a45d4b8d0eb9a54f5f074a9c5b6fd8d82550f290e599e3a73c0eac52dd94dc918ae4b985f6863a5783d764662ce64a0d3eafe619e1ffdaa3faf4a6985dfe6a58f7a132ddf896d9a757349b0a51d10432730111c391d926b96fa605714c7dbb1719d868fb7ef6995d63d4d5619653e865dcff21bc8713e6093daab77f2acf5491a66244d9d46335da8a16f63e2d296e83f540f5e4f574f1a5a1500a20a8190b0bbf60f0b401a4a5c333edd38728866bf26ac44ebaf7f41356c8fd60f1bd60112a0d9715c11c9b271d2b7a3cede68f4a88790c47ae1b027700cc9edc1a9a63f8f63b796e9ff2773d5138bc8d1fc98a84a7624b3cd5d04d6a11d4e55e08ad2f69f1f90cbca0a1db3f53008bb85f155385de4bd312af8920b1c63489525b9e0a97bc5eb54b1ef6173af2950559e9f56b24374a61c96458184ceabc34ac24021c26ba82c3e3687a3d8a8e28ec3aa563c94ac9125ae8b0b9881e071b8c862827970028e55cf0c7821411c824a5c4da44fbdee147c86f943b718387c8232291fc844a89aab8466736296b930fe971d0346527dcc71090ae165c7a8e8edc2c72a9af00d5c3fcd52ba9253ac15132045fd311203339e782c6e54ff26e3a950f2430f74961f554593c7c435ee5a79a0a0bef3bdc347ea7faa6b3e4579adafeff126d6ded61b116d20c2fa9e5b020f71395c4d1efc8f18adae9f5326d52962b0862793fc889d984069631cae5d4295aceea308881579e1c313cd09833d67097c247def9cca36eb72a0e069dfb30ec4e14148196b08fd416de071cbac34895c13b754f354af6aeffcb6d64531e48becab49697177ebe29d550c17f22626d9d073d0c40c5151d99ecf52a51cc47d6c2c2bc2087fd94b8ab3452eb3acdd0a2e091fa3fe7baccb70e69348854504562752cb5489fd65765719108e5f6387f231e72a61f33ad1f50580519f9e6693695c767cc7f0a60a9b6927630e874f7ad8a072ad1ea326c8b65d51b0cf247d83acbc6efde4628581bda8449c5278ba69115c6d0e40531cd19783c34ff963204830cadd81e263062521ce8cd1559bcff6fcd4b331238e8620348b494fd9248ef2f364fa9f836abec7b499685ec7d03287042a8ef3d68292d27fafad43c78d3564ec4415e1549471bb4c93957be34315b81ad020ee257fe8e6f8c6b8f429257bbc91015ff376ef698d4236c7d925aabd87fb8c50c737cfd4dd37791b1c43d7d925dda0af5cef8e5828993dff41d4019e61152b20017f18723d6f8589a72ee6aa61df954b11a094dfee7f8de82b4c6e0b8378cdc20965297622ee78b665df2fc9e0a59e2416d8101aab95a72d5ec8c6bacc46b8b052454bed1b1155e323c778b76cc12c4337a0456479e99cd954ee9b7a610ef2fdd85115c8761e48a15ee0dc75a1c44a0595783ee7a3b3f0be27bd901f1118ffd7967aa98fef47180b3c7314a238223aa468b3acd5c568ea74934fdc10b06f42b18b23d7a425cb4180a5f5e76de3f54064df11ff9cee21403be789639ea2946e88ecc81bcb492adf6d7652a600ca07d614a0916c89eee9348ab1e356e153bc37434e37bc7e581bb797251198ffc955e555ee20ce6118f175166ab25e25cbc847b825f969a66085f745eb64ad7ab1e193a7dadf466c29eff0ded9a9a82323f1d0ab88134ada28d3691e98e90ceeaec3369d466e24526e4eee3255e0266318c2851476b98af959eeacafd88994d597c52afd23d22578876cadbe26026e10753aef97ed889dd436d0e9369bafc8cd50dd0b6090cc3944b81063bbada167cebcab6866fb3b87791b6dff1de3b2aab67397df70c60ebefa9389e741fd5337113a1da0d7ccf733348eb91cf40d0c323baa3f692f9b45881efb66edaf4ea7ac6d88b6a93fb7237f6a9bb43902ccdb2ea3e6a342abfaa5e36d9b685bb1a97f0a2b94a69c674935fad7b38d7702bdff95d3aca3895f3b05c70cf1754cacc5980610f09b6e2cb3e89311638fd4b271805efc7486d2c4f0cf0910598427c66627c74ae12f29b63a7ad778e0aaa38f7b1cc23189603d01891ba26c14e4e96c0f7c86e63c73d8d1098661540b4daf2424c89be4991f07ed284a8765d92c6b52c080bdf62bca1428a018352baa32571d8d36da5653a91415dfe8d0c4aa46ed6766f4c162a05ddbccdf14ca9f84e2d487199467f338e81f3f5058bcd22e96a04119d036de1ceb872ca05954e53c86b85626a44856e5685fe35d8217af87349d24650059e00ec7b80d7c0496950a1c827f443db6933a756723cd529c25d7a93e3be32666bf2d20f533d6b3e1378296cafa3b468a3926e7754781923b12d9701bad179da601a623e25f76731a98e93712415496ea84f88dffd243f7ec9a480cc22358bb6705d46be5807e3aa49019e16f86d0c35af6c6e6f7019cc38f5dee215298ae1319bcf248aed114fdb0a5b342b8d250fdbc3bd5ba21e3232a7655bf424eaed8c810b6b1912fa31e37399a56aa33a9a6a76974175ac96b67c43c1ecfeb5de2b0c7b8d4f29993def838ace907acee23a1a7fb52d53078a4d544c858ba18412f152f9596b31a15107e428c96175b5fd49dafda407a0c86bfc9ff6a44217a635bbe6c672c85156f21ec664465ca9e6b9e2e4636aaf6c7d02a9cc28907f5b84d08b1a0a216c8a8494f165a637f5d4edcd0e272390d8704840cd62846db58c4f4c118f19ae3087d9198a05f8b2b256cbe176bc9604df06bda9b7e49d7ded17a059f32b28e1ed47421f32d425004261ce060a2e6af1b7f583f9d7b6e887103df1c359f9d043fdcf91220c57c438fe37b6e606492850ae87dd6f0fc4339777202464dd8ba10e119775ec36daffcca9aebe2208249ffb7068009612a15fd4ee01fb564b567c7c31a5179f88bd1e71d4bd0771b51651ed98ea4bead8deb759c86b2d705d16f4335457b0c9d3b0e9cff91f8df33f265600bd0cc8e8128918456726dfd3cbd8b8c45b21506dab2c49975e10440a0673bee73c2d757f48ea9e4c8de2c4a6eeb55d3127c78b95c2f13b4b0f66c9ddfaf6d28ca7070a6b713d28e8ecb64d175b2a4e8151323f0f9e1769b4ca1228f7d555ed851aacfd6bb782629e6f38aae70000")).unwrap(); let asset_id = AssetId::from_str("b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23").expect("Valid asset id"); let btc_asset = confidential::Asset::Explicit(asset_id); let btc_value = confidential::Value::Explicit(21_000_000 * 100_000_000); diff --git a/src/blind.rs b/src/blind.rs index 484ea546..bd611259 100644 --- a/src/blind.rs +++ b/src/blind.rs @@ -945,18 +945,18 @@ impl Transaction { /// /// ``` /// # use std::str::FromStr; - /// # use elements::hex::FromHex; + /// # use elements::hex; /// # use elements::encode::deserialize; /// # use elements::secp256k1_zkp; /// # use elements::{confidential, script, Transaction, TxOut, TxOutWitness}; /// # fn body() -> Result<(), Box> { /// let secp = secp256k1_zkp::Secp256k1::new(); - /// let tx: Transaction = deserialize(&Vec::::from_hex( + /// let tx: Transaction = deserialize(&hex::hex!( /// "0200000001014166d8bc73e9f6bf833f6372b021d6e412ae773cdd722467db163ff06d1e1fcb0100000000fdffffff030bbc8258e21ddcfa93f8b13e26675ce0696bab13e48b6e570087d27b8c2e58229108a6dd1a702dc30f897e040004def8dd2e67b7c6567a77b7c4d88e71d837531d76021d91021fab6f42fbae69c1ef0fe51ed088f08f69f9e658c5f702ab8a512334cb160014bea76c13404321e84760d712218e455b559f2ea20b637f6c0c63b8403cb889ee0502f2b4d8f391b8230798e938ea0aff882758f5fc09674f64e8313722b6fda15d4e3be5845a2c8fd7a243312413f026f6dc9541bb6e031465dee3abbf0059ebabf7933cd5bc8725a8e284f9f2868df84dcd78af6e15741600149928d95e500cf680ab923370529b5110b4c6b35501230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000000f900006f000000000002473044022018a96048b7b3d732fe44421655a26c076a84adc9b0d210856734ef52093b0ba8022045f3645b9d9f40a47963f56c5fe599a23079bd14fceaa2432750a235c623485e01210232edc2082acf05281c9ddb1d8e024de805ae65f6547848ea34441c09173bee3000430100012bfbd82937b25fc506c0b016d904d63eb15301c8fabc6e796549f0383cc08c7effd3d398b04e4feb1279f90f7c32d9a87907155514d69f9612b059f6fdf2a62ffd4e10603300000000000000013f2817003c824b0c690dbde0739e2e1263411a92287701d3bcb9917b2562397755e3945a5f0e917e4eb71b9245d225abcb97a43c7c8bae23fe9b389991db5e693937b2dc225072e5177673ba18545a9dcafd1f550501543ca45d11eaabd2769e49bc5a26fbe64eedaf38d56ef5f6d5cbac587c97c9846a6472a0525104dbabf24d34fb3db29244ef5dce6c9b71a12d9bd48bb796f6b4f89c1130e767ea70842402a1d1c1e4fa2ab18db1f407587e2b5ecbfc34c05b5fe5d10ab43fc9fda482ae7b08eb0115e9758b9d14de8f8d567133779a6153411e32456241f149e0731dbc263a5831317bb394a0efbed52cbf121abafce5dcde0949b619dffea3a942e0ce237a4725a865f4d3a7dd18f6c3baceefd2504fe03d898687ed44237e6105a237621a71f68a22d43ade7c59e14ebc5ea93e236f29b7d8cdaf933c8dc2df72dfd4b74c4469ce34a263373c7154ee89a66387bda99794ecfda0ac03298f1be66f60a67202053fcc98eea44839f8f6e5e0aa3657b72bd54a236362222ab91b5bc0abc7bf1b19138dbead02f904e0417b45699fa3699f7c8af319db491b7c0990a119ae0fbb0591e5c1185c50aa6b8a6ee85cbb841bc4fb99164e0b4d0e18fd8f61d41e05af83c4e94091256f27fe2838d8b44c657f0035c11c3c7636f62e0e3b2188faed87daa23b01f690a0712a06f06f464be8b5ae955f3f880f750d01d23c3f6ee7472b1a8508b0b7a200675dd347c14d520e77f7d61dc28e87f63129aeeb15c32fce6fc109ea7582bedef9594685b8290ead0fec8f7a0477babf661c61d7e651b19b46a59b06d92472ff1e30033534acfdc6a23bdd287e0582d3ca45be95436120ebae081c0c81da96d60db6870d02e386e5cf0ceeb0d5d746ab7178f9297c47be7d9fae7b73eda435319ed7865fd3357120645cc46bbb8ab4ff58fbffc3252888ac7e1bf6f61ef113c1823e38494c2344897f31f65374b13b677656b37386d95a66089b2d1c557b6f70d0354fb71a903c530ead4a0199d71052f589be243ccbc890537b9412f2d70a4d9585c8af6af9844f403acc40ff8633bd2232c032fff6538aa45218ecac24eb62a48f852b91dab12efea26f2b96f368fd850da25ba319d09289df0ee8052ebc0e39bb006966cc51757a3bc3da2a7483ccc7b82f4b13fdc5222a72f60bb750ffb469fa1821cff233ce8078676a9c8dc4cbdd89337275af2e51fe5351d7ed81ef62dcd944022da3ae3cc501e777d567217b21e13d8f1cc2cfac2d8494343e3b6ae80cff461ea20a3604bd41b42d2ead953bdbd75170c7129139724a6669ae77ac234370625a9533168bc1cad48839ef2abe517d2955d75b5d573e6b6e52e5342d9b6d9e2ed5413bd2cb8190fbbfa22a090da3eb462a886e2c2fbc076fc47c8778d3d10b15b7afdc2fd8886b4f85a565c2f517005b125df57a444a4d2528b7d3ac67a56454fdb2fc764f29d6e9fa8ec0bfb78f562ed9331d24f541c03a51628a932457e0287189ea36a35be4d01577e7a2a766f2081366840780abfd2aff20a9d4cc826fd751fbb0e7b353d518a3cd90bd61e694a7645a7859e21532d8f9759d32804c3341e41164f8815a38411484f4b394db6a8150591faa9d37cc76e812fc2b6cfb1e605d91552a31fe88b9d18cbbc7d2e558db74987564209ce126241c38a80da1df34db585a9d7a1330080cb16fdaf9ec1c37f309a8a0e2e7748ede59e7910b8b6b5caee51532ee6c5bd851db455c150b8d90445a36fbac9858798d73abf605dd0f515c23a0f975d50d09e6d7f541f0250c23c414219c87b15929ada1974a71709809db49ad8cab72958c31b1ddd0064d264641327a433d748713c57bc0063ec45b852a9beb2cc2be7465bd48b3d113ecf3d4981f2e3ddc7494714d21b860eb336ab91e894af0a5ff727f2b8d85c12f7ed321c90038e8f26f544c4918562b7c65e7cc1cecd5c6961ea2d1f806268d1dca92337f127a03c2626fcac5b8caf0a7abc3a6cc4d362f040572b56c5ad09e0dfd92235dbb2c1a8fbccdee13b2cf55681ec8f053575214c9200bee18428b25440b220079ca8708d23c84927103a8afac4bee58b95cce012ea23b175bd2a12636afc07e649675568ef945d352402f222fa62dcbad7f9f0dae132c089aea82d4c8b905655943e8b61f55475b3c3755d5967b01236e2c4b833ff6945031b50f0a68f0ec7130055761f8e9c2ebb2c9462d0b8aa9e99c7ebed1d3213abc471bbd49f44e78e057c750590f3ac02d3baa776d9f9ef39bc1a166dd7cb1cc3e63d94d7bb51544b9b02ad1278f7691973030612534ff513d2cf7988b3235b4449976b90fa5932639bafb7d0d33b58a167617ab4a46189e251bd488cc36a4b40968aa34c20a80f3ee5380152b7dd62de83c1e2a07307861b3713506115c1021880c19f89f45e40a16cebfc1980ebbab7bb9288eb33d4696c39bedada35a41f9e6832a0f5e12f2968303533c8186cc09da7c3ce4e96410f7a9bc5941706fd513a908ace16cd3605c5d0f4b872e931d79361134371285b6d223e1601ad129daa776ab58cb4dc7eaddd45cbf722d4cc4229d75a52e18c7470ed1a7a84671bd8bca4b9bdb0d7b0a34779d1a538fad3b6e2d7cc2972ab1bb98613b8ecc27f9fc25fd797aca4e5d0de4aa6df7f6607ad268baea41f3c1f9afc9dc5da929b29e4ac203a7476fe2c185ac25b835b6f2037c3f540852bfd2d643c179e0951cebc35743f6315a56d2965de934695ef5dbae70924f8548a858518340d7add64f45d2c7b69bfdbb8fb640a2284619fa857d2f5f8bbf615822e45b924622d32e78caedead8ab69fdfe142c97d7fb61af8cd32767d1006c6331d316e0e66b112a765388ff027eecd1181913ef9c701f2a46d0bf35abcaa3fe0cd26863e3d65ded79b262d1e914c538ae7d05ab30390465ba25a73a6ab53ce4296a3f5cbfd3901cca44bdd6818fa8d427ab2ceddc315f0adcd3fcae63074ea9e42f15fa02f1e3ec6276adc953beaadbce84ca6ef04966c882e3e7802436e4042fa5be4c3773d685bed66eec0c5a6cc463770c00740fef403badedadd28984e22027b38a0c66b7a409080adea574cb95ca236d701751056f7ea1e1b3082f0a26acbc630526053be88bd88267e23c2787daef884d709a5ac2c118c8c8b4b1eb6cd9d829ec42d9f249f754cf93b6c4cfdcf99cec0f9d742af36300274df095a35efa8ba95d412d2e61db8776660882519d4500f615e6a3e88640e93e921dc1fc4b74b5776cfdd47eb8b00d422fb0ee5c889c419bd352cef4573dab05fe44abd39bb7014e4ad0af6e5c9ed8236edb16d05057a6794ee76e923b6d1bef5e17e7078f6696af0f23064b1a592e89ff7073f040e9ea236450fa8d8fad6d04606b1a1a407ea14868b0c81c76c0f5fe9047e9c60dd150f9164533a7e4cbcc87f5c58e9e9ce317ce694cdd816b45fc497ec5c66736050ba925fa7ec598274f23a4ff022e7970dc520e4baefb30a26a5464fd5c75906e88a2c245cfcf00807c3b5e0deeb463886d606bfe7f30b73a512c5488f7c586dbcecd03ecc6cfc3caef921930aa01d2ca21ae3acfe5af26003acd436c344f80a4a9d9371a51b5b19b984d12b2a134f2ed89a6c5cf9905b2626d926bee7fd39988282411a0ea0ec1b61c22eceee21cd264c1fede96d9460cddc0624c9e22ccf42ff18bb13f8686bd6ef528aeda6181647a1c6c6ebd90fe05a69cbf169a971ae616d9d74840f1a7a3cc48c7a27b07a14e58bace67aa61dc594f0dc909283fc39c77a5dfadd50a358fc2c05118cb6197f3aba31d75fe2681219bff02e70f6d968f99d59a6c80a2af8bc09c21a2874ecfa47850844221fe066a1e6b40c0c5c4b59f8a8c22b78419c77be2306a9e085a76dbf9552ac9a575b872df0f9834f7aa8d89d585ec34ddb7c1d76c6d132356679263c8458a288c95f36631ca460ef925fdd9801154f886beae75dfb5e794ee58813cd1748e932e279ad65a3e2e894d190e221f07207d6ab5d2c7e328661746bc12e72d6075eb2a4e1f91a3b27d3309f9825d2467aef6f5236c38b071e5a6d17e3a7a88033a3ddb756e7aceb2c7d4fcca92a077a110684337fd8222f9c38e806554d30d9c3fcb647faa000f72adcc8e1d6c811634757a74b4d52f9e47826319f3954756d0623149a9f62f838feb135b1d26fe00e299a96dd94106fd39c9aa14360792870f33b8cde870e98353b27c1bbff569b79ef1d5f0161a4b585f4002b42c970b3e84912bf707c8d49fe56adfca407f8a039314a5c0720060061ace5a8144224bf52d5458e1fff84306c2c88b86061e18116a8b46cfb2adb6b33f704ae6d83aa2aac13bcd61b64c93cb6d2d5c3acc990626f891f9b7befa0f25c1a2665290309add936ff62d4fd182d68adeafb49f75fea798d8572444253886bc936589bda972b5e5625db267de1b30a8501ef215ab8a320574ce27a33fe603a67656ed8744f048b022cd61c132ece087fa0d94c2d4dfbb92a46ea5403341df3896ac49932955c6b3d700bc475c9d173c6173c8d883bd9499aede17e7840294334f1b0585b66f00e121ca298933703951801584c5db57854ef87802d254fc75d31319b8560f5ebee2ea80ffefa63e2a4c4e3d53b007ca18f83539f3078b2736f4fb4f8fff41823912227b04bab8aeeb7d95eb0db3dda58a98077f25e1db6dd454cfcd41068dcfb54f1d1e0b478013e58ca7efe874e98205d7c59ceeeb28cdd55cab4fa3a01ebaa957effe330364f75c0d6728b769dad34e58e9f217d1e8e96d79d896c193b425236ef2303eed072d114c06c198fd6a12a28f4d436dd126d1ab98c7e1621e0f59cc7276dbe7cf267ce2c6c0ed164deb57039fc5be8ae4e72efe26115e0fd59ae6fed9743eebbea873fca30c9d7eda201e73fe22e509b11c19580d368bca3f4cc59b949c8d03fa63e7b2b79f39983235d7ea3fc6fc92fab4c66a7680ec57f998fd818db6fa88ac2913f4a48a4cfbf68f1f565f799a6a95a22c8f6a4d6ba2a5307e51c99d22bcdb399520306446a6804f7cccff394986341187c4a72813392984e57ce3cab06c540722e25be50ba138ca0a54686c8960e2f6118380b3b9255d14071b1e2131d6cda16eb463bc4642cc11391a7c8a75a6da8c5f1424f7752ca3dbd37f2d9a2a3855f3b3aa7104c7a5be0c334df618dd478c43b9bb0fe7d774e93cbc8323816e1f0e1290e52079009150761207d99b1ec995ec7897a0385513abb96ec5f9d2c757662cd946d8e340646944b5fc6cf92f606ed2bd6872fe89c1cdabfa7f755b27dadce1337a18ecad4b78c0291f34e1cf0577eab17c70b05eea58bfb7bb3cdb46d46507db8fe8cbe3dca07d92d1ea2c5a6e354cabba8d532a47f6d9ba6ca48add4df8bf8ebbf3ccf8b0417f4b90756faf134ee210511d40314f218f9902897390fb0f405eabfc4a7ed4467e4fd14edd3ce4ee0337a5f0c21590816126768d5a85d67c8a7ef6b07c8d40dd13978cecbbfff0507d6030167e01bfbcb3557610ebad49f2f98cd9e003d3fe0a4dbc64d4202d4260ece552b7f7dad2be1dc61e3e7fbd5ae5be1f9bc0599807727c1e30eaa6d80ce79bc6d5a28c5c3efb8c1e99ffadde8ba7f42c2f27e3fbadec5b13e8673256b2aea4ea1a7b92d909ac4fd06fc3f03098cff0667224949eb1fc242ee42da5a9a06d93c5c4896e3c54e8815602d2a42c4bcad7a597e9261d24a404ba0f4645eb68f0521b7eb73d7b26ce2f802ba54674d011c07c485c1f7b6e31197c40a39c53e94cbd0b3de605c76ec9d7272a53ea5547b2131da2b51b2b0c099bc93214f02c2469c396dbc6fda284126d7d069fc3d51750037e545cf2ffe35b308d1c515870bf0fb062c2c666367061430100011850912d035bb6962d10e126e5a9666eb4128d7fefc4a0633ba0f388c5f28302a7a2e02653aebda6a6bad0cbdd972b57201a14a7f879c480fe5e1c36db90f749fd4e1060330000000000000001bdbe9301cb099b5fb8baac78310a3529d6677700658a6a87eb00a5f66dceb0862dc11cdcf845e07ba63ea84308200d309ffc3211996c507208560b7f65fa70f0a176dd0cb179ca911797c66d6fb56d27728a4fcc9998919a89c52d8bded3f732a5360861a6639c839f39503ea1457ae5d4ff7e1811ac2d33047823c5c118768343620abe7fd8cf459e5fca0f490ed91d9c09b37303662c201fff61247e8fefed8ffb29f999cddf601670469de151617021352c0dfe54512bc44c3b8e1a4ece73d2eaa727b28093d4741bd01dba0d9c7a4cb69e8a63bf6e887fcf6a57812ae40fd829dcfb6bab3a2a4ac678418e15179613f2436f53ae806ecb8f44115847b16cf935efadee467aa6de4a0cccaf8e4b1835b8dd1f9d04f0bbd4b3164dbc58a3a10db4537c94bafeb0289c6a192b28d5ba48df580a44a0d044ba82140295bfae70214127b73c7efac419bccaa75716867bc0bc75171e54dc3c439635d832cd052c4e9fa7370b1794b3da8a1a740b50cbcc605dc840f4d996f1283018a6356c437e79218a191ec68a48b193d3560b690d44741b354b13320ea16286405dc6476e8e8231d667978ef9c36e84f09e74387b4d557e39a40f51a62f70b5be58415c256f262486fd144489de4b8605a0d53945ed08daf543f3fac38888dcd4650903b95ebfcb4e0f57ca89b3f0132400e4012e00854c41b2788bd7c0d5d40845f48571d954e12013f6cf7ece536f32ff9a3c94ed10f1a2fd50b3f38a0f1272489d583deec9da33d9ac46914efea240aa004a8f17e1e168136b4ada57309b91e10c716eae0a5789c64747c0e09a696b67e8c7bba12c2b8d80248da93acfc7c1455a33b40f8761fd37812e74e572a9a21b0e2d7bc37ccad146d847a53d7a650122d96d00b179e353db2864e5ec929173550e0edf2c02b2ccb595b326582758d700009f4c433cf86837d1070686a6eeee6f4ab1e6ffc44bda783d7e2ff81f289991cdf982b61a73660020e544e5897c3021a446c8a4966ca625bbd6bfdc505e85d1f5acc663607cc2ba18945b74662be550b215878b35d9932f11cbe509456461ffa2b3bad33405f51c5b17b5081bbb4874c2656e0efecb2647d22028e53f263401e779e92ea3f70c860b0405e8109e10e27c2f4986e66965f4ddb895b943ba4dd0315372ac0460f78ec408cd562c21537d7f0f5e12c95e3d86066db77390b02e9073e241aa97af7588bbd6fa967a6776a3e226c0e56936fccae5ecd8aa20af1cc9b74a4579d8bd4fba988438fe455da8261f9aa96bf222e5af2fe297ce1901f0845334e856fa928119e23cc64f5ac541c699befad140a3e2cf53f591112d1ae57391eecf6fb729654fa98ba946ba8a532c3cb8b0dad5f08e3158f128cb065379b2ffc78d8394e5d2f1c7f4fa7b8a5031a7053f0144835e7ef53f4d60c8953bfde31e75fa3ab6bab86bc37617585db21f16318902138c1a7c25db16c212bef0de8aed1575e1c8e1064755b4b493adaec2dd320f8f8b9a240352f7a8a409ff3ac3beaf08114ba7294502f8f0f529e039ac7cda8a9d8e45b9aeb4e7a83d2de5a4edcb363a15020a5d285cf6acc3f43dfa724fd6c8ce76c33d485db88cdf379faaa7a0eb65f52c99daf2fb0edd8eed2e38e2990b044bb4ab7cda75d23b04fb72e842b54d88ed8a7ed236f61ce58e7a7fc34aa94e9100157cda06dcf81722058369df2b912442ea0768383b7c673f239a7f56dd4ec8739cd14698000747b979f22852e72352b0287fe7c0bddb68bd494341a0cbbd0df4fec1d613f7160f8fae32b9009c4d7146a8004a158763efea270c6724d022bd3d5954789e2ebcb50663b98a619182d800263485faee5e621d99f6819068f6d032aba95f7294aa6bb297f93fbd0e1def781351fe5ed7330ffb203d48aef9c6e6af244cca568dd164226131343f37977f11a770bea7f40e8b0593f5efd23ca0ff18594512004a9a34582de5ecfe06519f6223b5576ba1492d817e6da30791abfd2f4e85d235fc16f43ffa1879afd6f3c3aa252a232d567502dbdd70005997da48f8a0c64911af8ba5e8c123a3e81247de4a536ef41330d345c2681e1a508e4accee45140a194a1eedbe6559e67a9daa34580f00166db39d3f6e92d0b996754bb1d8cd3d68d692b872a0e9b086c14c1d143e03ffe5279a6687e5fe139534e59d43e2204ad9794a38a3d9cc9e63245c89123977e66dde7e33800f62a9ab3aa725b09670cbd58890056d62b459473ecdcca375d4784f278042fecd626c635414ed1ed1a1e2cec075d1a495004debb13df0c61e0bfc2f10ac84d94c404400559c6b4209fcc4fd0f4e041fc5101fa8265478fb794e7c008af8172d267e495d314d65b9dc1dc3ede3be27e4c80840ee7b75c31355bb4c940049bb0e02234370a2cd009753983409d87604ff5bd2d179061f9629be6663ffad62e3aed59de373892140475cf491a6482da6d9a1cc1031b4fce7737accce613a01fccaf36f0ac6fe1323828f3cf2a3e8c64cd0f95916c3db7176200e8f6384e6527f8020a761c0e46d388c4c1424118a69afc6bc5884d9ca3a19b5a65f95d3cc476b1f8e1c7bd41969b0f42d6b121816c1f3ebcff888c0c93d582d6f9b1bb5acc1cbdef4db323585ee059b4a68b37dd6ec85fa3a7bdc0ff7cd5e903cc76bc6a30b7965132e551bd5ac1c11ef069da69064086baa14435a9492444619dc3df5466bfb2cda341ff630d767ab55ec2bec5f92fa0e23cd8b4a5386c85cf540fdc4a15e9a27f7ea48c29d92a58c738eb2133005ab4b787d849acca740d58d258e5fe32dac3f2499773ffe3b362cb384632a8f24b9380c1ec1566108052ac157691ccdfe8ee497c57fcb8db7799ff2688288f07dcd7af020e3b21ce8ce9a730fa23f88fe2ade8291a439fd3b5769ff98284e042a1d795b1920b10cf755d3073a7a8e7f9b78b62baea353b77fc4be39caf38c709ad8c548432a7ed102e114f44b0ff22c7c04d4299f9d47bd81172385ddb1e5c9019809968a7638bde0b766d63514f85b22b1a795fb97b9c367b9693299c7447630e333265faf35ea516247d1d1ef7f9ded1219f9cba746100cbf6470becbe5e73fb817e7979bd1d502e9b7ab62bd70a70115cf3f9eee4e7ba131040a4baf9139e7bc6968b0053075f75afc787e2a083caff88d5b627d81d5e8584bb30334211866dceb96a2f03db6734e5a8cd28d4000119a55e32ac45dc38080c5fa05200e0054bea35713648f17634b6954b7be38e38fb29c3f5251f33c3f6531855f393fad9568b3f3ee02fdcf02f2172de1f8007a479d235091c4c39b76941bcf563b46e32248f9adbbb247bc62d552c5444ffdbd0cebf3e5a08212400cd7155236c21a410bb1dc9aca0f82b438c5e1d2c1632c577801ca18d30371e39efd3135092d008e290dba376f799a85dbfa317e9490bf2ee52444567ef8f74c5350e69331c03d51ddc8151822656cf7bbc054dcf9a5166a2bc72b01c5778c4c8f3076343ec1a6f7f3380d3e19bde7c248b23789bc724af6fe17c2173b0c204ff8b6342e5c9bd8f652ff0c80077fce0ce258b0879c74986f5d51e59eae4b946de1e2b785f039ef9bde314753011e35dd9ab9278fd95e4b10f04b4a157a16a6de9ba5a1793a4be0f2e2fd3cf2fd9366b2b7cd358f7a9a9397899833839c8bc968c5c37660488cf391637702de780b5ac526ab11fc895a5c783931dd0d486cc7672f417ceb30914b8f6fc51d270c932c81c7fda22b2b88ff14f7c9285f6341053fc529aefc97755fc5962a5e094b10291b98c991b0bee8c28b639f642bbcbd7c27d9217c19e11a94ecd58bc79c220feb9f1799f952e8a31b9607bb9fc4ababb8515aed1112050e0a75cb5c7811a63b90eafe411e92f2864fdbc4f23ac3c335d300440f9b6c0e7402a825fd5f4eb32ccb76ae4ef43441282356cac29b0147f780252427c9d21abdf7306c9f2836f599cef0a2c2eb4596df9498d661bcf8bcc88d5a7f0779489f9423ad045b735e421ba0f861744beecb7c1efcb5989386e9c2e4e07ef033ce75d5e3ae6b78775cbb3d5ad8fa5b29ee2137f6b59f865c71af63ac98c2f0cecaec428c773a747ba188f8f3dc30ede05077b422a920a313b885c31d247328c691f66a7440bb27581baea7d9365f8da23bf71a7cbbca02c74391928daf1f6b2b0f74acd3b89ad53e3dc87aa2716a25c89c4a6f1a363cbd97745910e399cfa766ddc5b25fe4f40412690316acab688493a1c882ccabf7ba2b1496f77ba6a34133b3a6d9f5c6526309f1d2e14c261959dae012420bf9fa0aa2b3e3862308f6c6f65e7f0660eed3b5fbf3278eb5b2893b1c8dbef827e7bee0fa92fad9393f037c4b90babf62a159e2637f22a46a18bee1baf9c4c3344186083b167de5936437a5fb379ae305e8a502fc22f849398daa9547c8f6c2554d231daba90a5f729069c24bdb2b749cd1a16489f7c0940a59ba7f324dcb2c42e47652179208bfff6d64a1ac5e557a34321a4c3bda6eae6f461e1a6ecc9cee9fbf36e2b6c504ae2e0a3bd03235fb6032725280d64fa1a33f58a7196b56c0a65dc7bbf0a429889d0ee2467796515f857800c78fe21bd17f65807342a7f4a0a7926d064f073d1a7dc76295b9e35195b7880fd83db7e2335709179cca4f285b0b14693fd0b6cef9958cc6906adacdf1ad1b572eaf9e6ef42b574d75a1f58927d49113726572b40bd792b6ca621daa7c5f56645b1f8ed5b0a7ac26f71c4c665b89b975b3c38ed6949271df097c8018e772b2a3f8bba41424bd9c1b06e111cfdedbac883dbdc5345e5a6aec531c722c94b0c6b072288b706afe77a6e179fd38c7f6a0051246f0b161d0a5c696374755b01822181bd843ee8d4f476ef5bf3efbf9cae0f3162ee5de88c0aeafcb3b5fb34a7edaad5292428a612eeea80a54c0dc3ac1ac7b00f103aa39015a038d4537271bdc277e4a8f8648797b6a67cebb7485625406f9963d17b51d1f4706674e58da1b5e4c415eb403791c72a62a2e6a5a4cf50d26fe78d7e9620c50f718dbd0d075efccbeb8b731f8b1ecc988f2b38dce9cda9a644441391728a47ccd8975dac442c39f59726802474ec44a45afb5e545512e8f069e139da079c6e0bafce31f30bef474bb2deeeb6a035ab37757b02d6f4de3ff85a0cd5109290259c1be2a8288a33dcad5518d9d0413a393f659095beef0572193af15d909acbff828b56adba008a3fdb653ee5fcb5653884ef69d8f8f6588b2b46a3dd361dd4983d205d22f9351f4ebc049f867832b35181a70f390158a2960fc9bc2551e23925f2c9a262b7b9e9da6c97f35e5ba21986f5cface9e8d829751921a9e6fdfbe084197a97a778c795c0a9e293c7a07033ac2a34e0f27ca53b4cc7833fc7682c0da1f5784e812e4223933dc2b4b20f77c4d01c40c4f7db5a556ad3de59605e45c02928f5b8a7720eb83f750c9789b062826bfc895ee526f0c813d3a3bdc3a6a03c27c9f3eeaec747bfa72c19da03af860ea21986df7c0509575c2b7f47f036758d9777e6843f620084bafac9c6a2f7910f703c8dff42c9f160a15d852cc4bf2f33b1b53c392959e804d34a3b56c1bf47a4813c7d67d36e66859b1eeb8f105c79aadab1cd2ea927cb9cc48a70da61241b5e3d3a5802c3ba003e7d318628f6a6a37725b6fc721899b30c9dd2b3d6f18d70df0f363ddac2fd3cc79fdde2ac26ccf16462534ba1a8d1baea51b789bc00226febe51678af19898e4f4456f072e5d79345323f8231b085b94419dd812bfae12c4defd363fa4baf09c4ceac1d543365ab52f230925f56840efff264b3b8e961c8aa8e62a8f3df6f204331a1dc08375c6521ebede7a0eaa92d378830d11a989681bd6e07b7a870195f4c2fb579a800000" - /// ).unwrap()).unwrap(); - /// let conf_asset : confidential::Asset = deserialize(&Vec::::from_hex("0b37d4818b8ce1df5d3d0b88d140c6848029d6d85fb0f6ee270865caf53d0b82d4").unwrap()).unwrap(); - /// let conf_value : confidential::Value = deserialize(&Vec::::from_hex("094e2cceeb8005ac14b611821c37fca757b47426afb0bb4eabe41c275d3997c046").unwrap()).unwrap(); - /// let spk : script::Script = deserialize(&Vec::::from_hex("16001475f578ed4f7a0103182a6e92942c66350dd949dc").unwrap()).unwrap(); + /// )).unwrap(); + /// let conf_asset : confidential::Asset = deserialize(&hex::hex!("0b37d4818b8ce1df5d3d0b88d140c6848029d6d85fb0f6ee270865caf53d0b82d4")).unwrap(); + /// let conf_value : confidential::Value = deserialize(&hex::hex!("094e2cceeb8005ac14b611821c37fca757b47426afb0bb4eabe41c275d3997c046")).unwrap(); + /// let spk : script::Script = deserialize(&hex::hex!("16001475f578ed4f7a0103182a6e92942c66350dd949dc")).unwrap(); /// /// let txout = TxOut { /// asset: conf_asset, @@ -1378,7 +1378,6 @@ mod tests { use crate::confidential; use crate::encode; use crate::encode::deserialize; - use crate::hex::FromHex; use crate::Script; use bitcoin::{PrivateKey, PublicKey}; use rand::thread_rng; @@ -1388,14 +1387,14 @@ mod tests { #[test] fn test_blind_tx() { // tested with elements 0.20 rebase branch - let tx_hex = "020000000001741498f6da8f47eb438d0fb9de099b7e29c0e011b9ab64c3e0eb097a09a6a9220100000000fdffffff0301230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b201000775f04dedb2d102a11e47fd7a0edfb424a43b2d3cf29d700d4b168c92e115709ff7d15070e201dd16001483641e58db3de6067f010d71c9782874572af9fb01230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000f42400206a1039b0fe0d110d2108f2cc49d637f95b6ac18045af5b302b3c14bf8457994160014ad65ebbed8416659141cc788c1b917d6ff3e059901230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000000f9000000000000"; - let mut tx: Transaction = deserialize(&Vec::::from_hex(tx_hex).unwrap()[..]).unwrap(); + const TX_HEX: &str = "020000000001741498f6da8f47eb438d0fb9de099b7e29c0e011b9ab64c3e0eb097a09a6a9220100000000fdffffff0301230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b201000775f04dedb2d102a11e47fd7a0edfb424a43b2d3cf29d700d4b168c92e115709ff7d15070e201dd16001483641e58db3de6067f010d71c9782874572af9fb01230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000f42400206a1039b0fe0d110d2108f2cc49d637f95b6ac18045af5b302b3c14bf8457994160014ad65ebbed8416659141cc788c1b917d6ff3e059901230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20100000000000000f9000000000000"; + let mut tx: Transaction = deserialize(&hex::hex!(TX_HEX)).unwrap(); let spent_utxo_secrets = TxOutSecrets { asset: AssetId::from_str( "b2e15d0d7a0c94e4e2ce0fe6e8691b9e451377f6e46e8045a86f7c4b5d4f0f23", ) .unwrap(), - asset_bf: AssetBlindingFactor::from_hex( + asset_bf: AssetBlindingFactor::from_str( "a5b3d111cdaa5fc111e2723df4caf315864f25fb4610cc737f10d5a55cd4096f", ) .unwrap(), @@ -1405,7 +1404,7 @@ mod tests { ) .unwrap() .to_sat(), - value_bf: ValueBlindingFactor::from_hex( + value_bf: ValueBlindingFactor::from_str( "e36a4de359469f547571d117bc5509fb74fba73c84b0cdd6f4edfa7ff7fa457d", ) .unwrap(), @@ -1434,27 +1433,18 @@ mod tests { let spent_utxo = TxOut { asset: Asset::from_commitment( - &Vec::::from_hex( - "0baf634b18e1880c96dcf9947b0e0fd2d38d66d723339174df3fd980148c2f0bb3", - ) - .unwrap(), + &hex::hex!("0baf634b18e1880c96dcf9947b0e0fd2d38d66d723339174df3fd980148c2f0bb3"), ) .unwrap(), value: Value::from_commitment( - &Vec::::from_hex( - "093baba9076190867fbc5e43132cb2f82245caf603b493d7c0da8b7eda7912fa2c", - ) - .unwrap(), + &hex::hex!("093baba9076190867fbc5e43132cb2f82245caf603b493d7c0da8b7eda7912fa2c"), ) .unwrap(), nonce: Nonce::from_commitment( - &Vec::::from_hex( - "02a96a456f4936dcf0afbc325ac3798c4464e7b66dd460d564f3f91882d6089a3b", - ) - .unwrap(), + &hex::hex!("02a96a456f4936dcf0afbc325ac3798c4464e7b66dd460d564f3f91882d6089a3b"), ) .unwrap(), - script_pubkey: Script::from_hex("0014d2bcde17e7744f6377466ca1bd35d212954674c8") + script_pubkey: Script::from_hex_no_prefix("0014d2bcde17e7744f6377466ca1bd35d212954674c8") .unwrap(), witness: TxOutWitness::default(), }; @@ -1571,7 +1561,7 @@ mod tests { let secp = secp256k1_zkp::Secp256k1::new(); let tx_str = include_str!("../tests/data/issue_tx.hex"); - let bytes = Vec::::from_hex(tx_str).unwrap(); + let bytes = hex::decode_to_vec(tx_str).unwrap(); let tx = encode::deserialize::(&bytes).unwrap(); let mut utxos = [ @@ -1582,50 +1572,32 @@ mod tests { ]; { utxos[0].asset = Asset::from_commitment( - &Vec::::from_hex( - "0ae7a52e8e4b07e00548bab151a83e5c9ab2f9a910e10dcee930a1a152a939f99e", - ) - .unwrap(), + &hex::hex!("0ae7a52e8e4b07e00548bab151a83e5c9ab2f9a910e10dcee930a1a152a939f99e"), ) .unwrap(); utxos[0].value = Value::Explicit(1); utxos[1].asset = Asset::from_commitment( - &Vec::::from_hex( - "0bc226167e9ee0bb5a86c8f1478ee7d7becb7bfd4d97c26a041e628c5486a8c67a", - ) - .unwrap(), + &hex::hex!("0bc226167e9ee0bb5a86c8f1478ee7d7becb7bfd4d97c26a041e628c5486a8c67a"), ) .unwrap(); utxos[1].value = Value::Explicit(1); utxos[2].asset = Asset::from_commitment( - &Vec::::from_hex( - "0b495dbfc356993c5ac157c3d04fadf6f198a7e35a873df482ad9e4e95daa8aa7e", - ) - .unwrap(), + &hex::hex!("0b495dbfc356993c5ac157c3d04fadf6f198a7e35a873df482ad9e4e95daa8aa7e"), ) .unwrap(); utxos[2].value = Value::from_commitment( - &Vec::::from_hex( - "08e0ac2ab5f3c173d5e0652a2ec209a9a370a4e510178e73c2f22f9e132341abf4", - ) - .unwrap(), + &hex::hex!("08e0ac2ab5f3c173d5e0652a2ec209a9a370a4e510178e73c2f22f9e132341abf4"), ) .unwrap(); utxos[3].asset = Asset::from_commitment( - &Vec::::from_hex( - "0aa0956d60687982d5e73d52f8c5902478754e5f0e2e5ceff5ae53fa9681c12ae1", - ) - .unwrap(), + &hex::hex!("0aa0956d60687982d5e73d52f8c5902478754e5f0e2e5ceff5ae53fa9681c12ae1"), ) .unwrap(); utxos[3].value = Value::from_commitment( - &Vec::::from_hex( - "094b35f1e86b097ccf0b3a826570c089c724ed9cf22620937500b14acdd169e7bf", - ) - .unwrap(), + &hex::hex!("094b35f1e86b097ccf0b3a826570c089c724ed9cf22620937500b14acdd169e7bf"), ) .unwrap(); } diff --git a/src/block.rs b/src/block.rs index f16f790f..0b72b69e 100644 --- a/src/block.rs +++ b/src/block.rs @@ -395,7 +395,6 @@ impl Block { #[cfg(test)] mod tests { use crate::Block; - use crate::hex::FromHex; use super::*; @@ -796,7 +795,7 @@ mod tests { fn test_failed_block() { let block_str = include_str!("../tests/data/failedblock.hex"); - let bytes = Vec::::from_hex(block_str).unwrap(); + let bytes = hex::decode_to_vec(block_str).unwrap(); let _block = encode::deserialize::(&bytes).unwrap(); } } diff --git a/src/confidential.rs b/src/confidential.rs index a6c0779a..91d692ad 100644 --- a/src/confidential.rs +++ b/src/confidential.rs @@ -18,7 +18,6 @@ //! use crate::hashes::{sha256d, Hash}; -use crate::hex; use secp256k1_zkp::{self, CommitmentSecrets, Generator, PedersenCommitment, PublicKey, Secp256k1, SecretKey, Signing, Tweak, ZERO_TWEAK, compute_adaptive_blinding_factor, @@ -724,7 +723,7 @@ impl<'de> Deserialize<'de> for Nonce { #[derive(Debug, Clone, PartialEq, Eq)] pub enum TweakHexDecodeError { /// Invalid hexadecimal string. - InvalidHex(hex_conservative::DecodeFixedLengthBytesError), + InvalidHex(hex::DecodeFixedLengthBytesError), /// Invalid tweak after decoding hexadecimal string. InvalidTweak(secp256k1_zkp::Error), } @@ -743,8 +742,8 @@ impl fmt::Display for TweakHexDecodeError { } #[doc(hidden)] -impl From for TweakHexDecodeError { - fn from(err: hex_conservative::DecodeFixedLengthBytesError) -> Self { +impl From for TweakHexDecodeError { + fn from(err: hex::DecodeFixedLengthBytesError) -> Self { TweakHexDecodeError::InvalidHex(err) } } @@ -775,7 +774,7 @@ impl std::error::Error for TweakHexDecodeError { } /// Blinding factor used for asset commitments. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct AssetBlindingFactor(pub(crate) Tweak); impl AssetBlindingFactor { @@ -784,6 +783,12 @@ impl AssetBlindingFactor { AssetBlindingFactor(Tweak::new(rng)) } + /// Parse a blinding factor from a 64-character hex string. + #[deprecated(since = "0.27.0", note = "use s.parse() instead")] + pub fn from_hex(s: &str) -> Result { + s.parse() + } + /// Create from bytes. pub fn from_slice(bytes: &[u8]) -> Result { Ok(AssetBlindingFactor(Tweak::from_slice(bytes)?)) @@ -800,27 +805,14 @@ impl AssetBlindingFactor { } } -impl hex::FromHex for AssetBlindingFactor { - type Err = TweakHexDecodeError; - - fn from_hex(s: &str) -> Result { - let mut slice: [u8; 32] = hex_conservative::decode_to_array(s)?; - slice.reverse(); - - let inner = Tweak::from_inner(slice)?; - Ok(AssetBlindingFactor(inner)) - } -} - -impl fmt::Display for AssetBlindingFactor { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - hex::format_hex_reverse(self.0.as_ref(), f) - } +impl core::borrow::Borrow<[u8]> for AssetBlindingFactor { + fn borrow(&self) -> &[u8] { &self.0[..] } } -impl fmt::LowerHex for AssetBlindingFactor { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - hex::format_hex_reverse(self.0.as_ref(), f) +hex::impl_fmt_traits! { + #[display_backward(true)] + impl fmt_traits for AssetBlindingFactor { + const LENGTH: usize = 32; } } @@ -828,7 +820,11 @@ impl str::FromStr for AssetBlindingFactor { type Err = encode::Error; fn from_str(s: &str) -> Result { - Ok(hex::FromHex::from_hex(s)?) + let mut slice: [u8; 32] = hex::decode_to_array(s)?; + slice.reverse(); + + let inner = Tweak::from_inner(slice)?; + Ok(AssetBlindingFactor(inner)) } } @@ -846,8 +842,6 @@ impl Serialize for AssetBlindingFactor { #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for AssetBlindingFactor { fn deserialize>(d: D) -> Result { - use crate::hex::FromHex; - if d.is_human_readable() { struct HexVisitor; @@ -863,7 +857,7 @@ impl<'de> Deserialize<'de> for AssetBlindingFactor { E: ::serde::de::Error, { if let Ok(hex) = ::std::str::from_utf8(v) { - AssetBlindingFactor::from_hex(hex).map_err(E::custom) + hex.parse().map_err(E::custom) } else { Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) } @@ -873,7 +867,7 @@ impl<'de> Deserialize<'de> for AssetBlindingFactor { where E: ::serde::de::Error, { - AssetBlindingFactor::from_hex(v).map_err(E::custom) + v.parse().map_err(E::custom) } } @@ -910,7 +904,7 @@ impl<'de> Deserialize<'de> for AssetBlindingFactor { } /// Blinding factor used for value commitments. -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct ValueBlindingFactor(pub(crate) Tweak); impl ValueBlindingFactor { @@ -919,6 +913,12 @@ impl ValueBlindingFactor { ValueBlindingFactor(Tweak::new(rng)) } + /// Parse a blinding factor from a 64-character hex string. + #[deprecated(since = "0.27.0", note = "use s.parse() instead")] + pub fn from_hex(s: &str) -> Result { + s.parse() + } + /// Create the value blinding factor of the last output of a transaction. pub fn last( secp: &Secp256k1, @@ -1001,27 +1001,14 @@ impl Neg for ValueBlindingFactor { } } -impl hex::FromHex for ValueBlindingFactor { - type Err = TweakHexDecodeError; - - fn from_hex(s: &str) -> Result { - let mut slice: [u8; 32] = hex_conservative::decode_to_array(s)?; - slice.reverse(); - - let inner = Tweak::from_inner(slice)?; - Ok(ValueBlindingFactor(inner)) - } -} - -impl fmt::Display for ValueBlindingFactor { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - hex::format_hex_reverse(self.0.as_ref(), f) - } +impl core::borrow::Borrow<[u8]> for ValueBlindingFactor { + fn borrow(&self) -> &[u8] { &self.0[..] } } -impl fmt::LowerHex for ValueBlindingFactor { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - hex::format_hex_reverse(self.0.as_ref(), f) +hex::impl_fmt_traits! { + #[display_backward(true)] + impl fmt_traits for ValueBlindingFactor { + const LENGTH: usize = 32; } } @@ -1029,7 +1016,11 @@ impl str::FromStr for ValueBlindingFactor { type Err = encode::Error; fn from_str(s: &str) -> Result { - Ok(hex::FromHex::from_hex(s)?) + let mut slice: [u8; 32] = hex::decode_to_array(s)?; + slice.reverse(); + + let inner = Tweak::from_inner(slice)?; + Ok(ValueBlindingFactor(inner)) } } @@ -1047,8 +1038,6 @@ impl Serialize for ValueBlindingFactor { #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for ValueBlindingFactor { fn deserialize>(d: D) -> Result { - use crate::hex::FromHex; - if d.is_human_readable() { struct HexVisitor; @@ -1064,7 +1053,7 @@ impl<'de> Deserialize<'de> for ValueBlindingFactor { E: ::serde::de::Error, { if let Ok(hex) = ::std::str::from_utf8(v) { - ValueBlindingFactor::from_hex(hex).map_err(E::custom) + hex.parse().map_err(E::custom) } else { Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) } @@ -1074,7 +1063,7 @@ impl<'de> Deserialize<'de> for ValueBlindingFactor { where E: ::serde::de::Error, { - ValueBlindingFactor::from_hex(v).map_err(E::custom) + v.parse().map_err(E::custom) } } diff --git a/src/dynafed.rs b/src/dynafed.rs index c10bf8af..9316eca6 100644 --- a/src/dynafed.rs +++ b/src/dynafed.rs @@ -16,6 +16,7 @@ use std::{fmt, io}; +use hex::DisplayHex as _; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] @@ -26,22 +27,13 @@ use crate::hashes::{Hash, sha256, sha256d}; use crate::Script; /// ad-hoc struct to fmt in hex +#[cfg(feature = "serde")] struct HexBytes<'a>(&'a [u8]); -impl fmt::Display for HexBytes<'_> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - crate::hex::format_hex(self.0, f) - } -} -impl fmt::Debug for HexBytes<'_> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self, f) - } -} #[cfg(feature = "serde")] impl Serialize for HexBytes<'_> { fn serialize(&self, s: S) -> Result { if s.is_human_readable() { - s.collect_str(self) + s.collect_str(&self.0.as_hex()) } else { s.serialize_bytes(self.0) } @@ -54,10 +46,11 @@ impl fmt::Display for HexBytesArray<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[")?; for (i, e) in self.0.iter().enumerate() { - if i != 0 { - write!(f, ", ")?; + if i == 0 { + write!(f, "{}", e.as_hex())?; + } else { + write!(f, ", {}", e.as_hex())?; } - crate::hex::format_hex(&e[..], f)?; } write!(f, "]") } @@ -165,10 +158,10 @@ impl FullParams { /// Format for [`fmt::Debug`]. fn fmt_debug(&self, f: &mut fmt::Formatter, name: &'static str) -> fmt::Result { let mut s = f.debug_struct(name); - s.field("signblockscript", &HexBytes(&self.signblockscript[..])); + s.field("signblockscript", &self.signblockscript[..].as_hex()); s.field("signblock_witness_limit", &self.signblock_witness_limit); - s.field("fedpeg_program", &HexBytes(self.fedpeg_program.as_ref())); - s.field("fedpegscript", &HexBytes(&self.fedpegscript[..])); + s.field("fedpeg_program", &self.fedpeg_program.as_bytes().as_hex()); + s.field("fedpegscript", &self.fedpegscript[..].as_hex()); s.field("extension_space", &HexBytesArray(&self.extension_space)); s.finish() } @@ -242,7 +235,7 @@ impl fmt::Debug for Params { Params::Null => write!(f, "Null"), Params::Compact { signblockscript, signblock_witness_limit, elided_root } => { let mut s = f.debug_struct("Compact"); - s.field("signblockscript", &HexBytes(&signblockscript[..])); + s.field("signblockscript", &signblockscript[..].as_hex()); s.field("signblock_witness_limit", signblock_witness_limit); s.field("elided_root", elided_root); s.finish() @@ -466,9 +459,7 @@ impl<'de> Deserialize<'de> for Params { } fn visit_str(self, v: &str) -> Result { - use crate::hex::FromHex; - - Ok(HexBytes(FromHex::from_hex(v).map_err(E::custom)?)) + Ok(HexBytes(hex::decode_to_vec(v).map_err(E::custom)?)) } fn visit_bytes(self, v: &[u8]) -> Result { @@ -650,7 +641,6 @@ mod tests { use std::fmt::{self, Write}; use crate::hashes::sha256; - use crate::hex::ToHex; use crate::{BlockHash, TxMerkleNode}; use super::*; @@ -696,7 +686,7 @@ mod tests { elided_root: sha256::Midstate::from_byte_array([0; 32]), }; assert_eq!( - compact_entry.calculate_root().to_hex(), + format!("{:x}", compact_entry.calculate_root()), "f98f149fd11da6fbe26d0ee53cadd28372fa9eed2cb7080f41da7ca311531777" ); @@ -708,7 +698,7 @@ mod tests { ext, )); assert_eq!( - full_entry.calculate_root().to_hex(), + format!("{:x}", full_entry.calculate_root()), "8eb1b83cce69a3d8b0bfb7fbe77ae8f1d24b57a9cae047b8c0aba084ad878249" ); @@ -725,7 +715,7 @@ mod tests { height: Default::default(), }; assert_eq!( - header.calculate_dynafed_params_root().unwrap().to_hex(), + format!("{:x}", header.calculate_dynafed_params_root().unwrap()), "113160f76dc17fe367a2def79aefe06feeea9c795310c9e88aeedc23e145982e" ); } diff --git a/src/encode.rs b/src/encode.rs index b1556335..d140eef2 100644 --- a/src/encode.rs +++ b/src/encode.rs @@ -19,7 +19,7 @@ use std::io::Cursor; use std::{any, error, fmt, io, mem}; use bitcoin::ScriptBuf; -use hex_conservative::{DecodeFixedLengthBytesError, DecodeVariableLengthBytesError}; +use hex::{DecodeFixedLengthBytesError, DecodeVariableLengthBytesError}; use secp256k1_zkp::{self, RangeProof, SurjectionProof, Tweak}; use crate::hashes::{sha256, Hash}; @@ -174,7 +174,7 @@ pub fn serialize(data: &T) -> Vec { /// Encode an object into a hex-encoded string pub fn serialize_hex(data: &T) -> String { - crate::hex::ToHex::to_hex(&serialize(data)[..]) + hex::DisplayHex::to_lower_hex_string(&serialize(data)[..]) } /// Deserialize an object from a vector, will error if said deserialization diff --git a/src/hex.rs b/src/hex.rs deleted file mode 100644 index 6384c7e3..00000000 --- a/src/hex.rs +++ /dev/null @@ -1,323 +0,0 @@ -// Rust Elements Library -// Written in 2023 by -// Andrew Poelstra -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. -// If not, see . -// - -//! Hex Encoding and Decoding - -// The rust-bitcoin hex stury is such a mess right now that the most -// straightforward thing is to just reimplement everything here. -// -// This is a copy/paste of the bitcoin_hashes hex module, with the -// std/alloc feature gates, and the benchmarks, removed. -// - -use std::{fmt, io, str}; - -use hex_conservative::{decode_to_vec, DecodeVariableLengthBytesError}; - -/// Trait for objects that can be serialized as hex strings. -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 { - /// Error returned by [`FromHex::from_hex`], may differ depending - /// on whether `Self` is fixed size of variable length. - type Err; - - /// Produces an object from a hex string. - fn from_hex(s: &str) -> Result; -} - -impl ToHex for T { - /// Outputs the hash in hexadecimal form. - fn to_hex(&self) -> String { - format!("{:x}", self) - } -} - -/// 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(()) -} - -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` use [`ToHex`] -/// but if you have an encodable object, by using this you avoid the -/// serialization to `Vec` by going directly to `String`. -/// -/// Note that to achieve better performance 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. -pub struct HexWriter(String); - -impl HexWriter { - /// Creates a new [`HexWriter`] with the `capacity` of the inner `String` - /// that will contain final hex value. - pub fn new(capacity: usize) -> Self { - HexWriter(String::with_capacity(capacity)) - } - - /// Returns the resulting hex string. - pub fn result(self) -> String { - self.0 - } -} - -impl io::Write for HexWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - use core::fmt::Write; - for ch in buf { - write!(self.0, "{:02x}", ch).expect("writing to string"); - } - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl FromHex for Vec { - type Err = DecodeVariableLengthBytesError; - - fn from_hex(s: &str) -> Result { - decode_to_vec(s) - } -} - -macro_rules! impl_fromhex_array { - ($len:expr) => { - impl FromHex for [u8; $len] { - type Err = hex_conservative::DecodeFixedLengthBytesError; - - fn from_hex(s: &str) -> Result { - hex_conservative::decode_to_array(s) - } - } - } -} - -impl_fromhex_array!(2); -impl_fromhex_array!(4); -impl_fromhex_array!(6); -impl_fromhex_array!(8); -impl_fromhex_array!(10); -impl_fromhex_array!(12); -impl_fromhex_array!(14); -impl_fromhex_array!(16); -impl_fromhex_array!(20); -impl_fromhex_array!(24); -impl_fromhex_array!(28); -impl_fromhex_array!(32); -impl_fromhex_array!(33); -impl_fromhex_array!(64); -impl_fromhex_array!(65); -impl_fromhex_array!(128); -impl_fromhex_array!(256); -impl_fromhex_array!(384); -impl_fromhex_array!(512); - -#[cfg(test)] -mod tests { - use hex_conservative::DecodeFixedLengthBytesError; - - use super::*; - - use core::fmt; - use std::io::Write; - - #[test] - fn hex_roundtrip() { - let expected = "0123456789abcdef"; - let expected_up = "0123456789ABCDEF"; - - let parse: Vec = 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(); - assert_eq!(ser, expected); - - let parse: Vec = 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(); - 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(); - assert_eq!(ser, expected); - } - - #[test] - fn hex_truncate() { - struct HexBytes(Vec); - 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); - 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] - fn hex_error() { - let oddlen = "0123456789abcdef0"; - let badchar1 = "Z123456789abcdef"; - let badchar2 = "012Y456789abcdeb"; - let badchar3 = "«23456789abcdef"; - - let result = Vec::::from_hex(oddlen); - assert!( - matches!(&result, Err(DecodeVariableLengthBytesError::OddLengthString(err)) - if err.length() == 17), - "Got: {:?}", result - ); - let result = <[u8; 4]>::from_hex(oddlen); - assert!( - matches!(&result, Err(DecodeFixedLengthBytesError::InvalidLength(err)) - if err.invalid_length() == 17), - "Got: {:?}", result - ); - let result = <[u8; 8]>::from_hex(oddlen); - assert!( - matches!(&result, Err(DecodeFixedLengthBytesError::InvalidLength(err)) - if err.invalid_length() == 17), - "Got: {:?}", result - ); - let result = Vec::::from_hex(badchar1); - assert!( - matches!(&result, Err(DecodeVariableLengthBytesError::InvalidChar(_))), - "Got: {:?}", result - ); - let result = Vec::::from_hex(badchar2); - assert!( - matches!(&result, Err(DecodeVariableLengthBytesError::InvalidChar(_))), - "Got: {:?}", result - ); - let result = Vec::::from_hex(badchar3); - assert!( - matches!(&result, Err(DecodeVariableLengthBytesError::InvalidChar(_))), - "Got: {:?}", result - ); - } - - - #[test] - 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()); - } -} diff --git a/src/internal_macros.rs b/src/internal_macros.rs index 7fb072b6..1972a6c8 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -437,9 +437,5 @@ macro_rules! hex_deserialize( #[cfg(test)] macro_rules! hex_script( - ($e:expr) => ({ - let v: Vec = crate::hex::FromHex::from_hex($e) - .expect("hex decoding"); - crate::Script::from(v) - }) + ($e:expr) => (crate::Script::from_hex_no_prefix($e).expect("hex decoding")) ); diff --git a/src/issuance.rs b/src/issuance.rs index d6387617..fd59a542 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -188,9 +188,8 @@ impl Decodable for AssetId { #[cfg(feature = "serde")] impl ::serde::Serialize for AssetId { fn serialize(&self, s: S) -> Result { - use crate::hex::ToHex; if s.is_human_readable() { - s.serialize_str(&self.to_hex()) + s.collect_str(self) } else { s.serialize_bytes(&self.0[..]) } diff --git a/src/lib.rs b/src/lib.rs index f90057ef..5002c4ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,8 @@ /// Re-export of bitcoin crate pub extern crate bitcoin; +/// Re-export of hex crate +pub extern crate hex; /// Re-export of secp256k1-zkp crate pub extern crate secp256k1_zkp; /// Re-export of serde crate @@ -57,7 +59,6 @@ mod error; mod ext; mod fast_merkle_root; pub mod hash_types; -pub mod hex; pub mod issuance; pub mod locktime; pub mod opcodes; diff --git a/src/pset/elip100.rs b/src/pset/elip100.rs index 7b22fe7c..56c1db00 100644 --- a/src/pset/elip100.rs +++ b/src/pset/elip100.rs @@ -221,12 +221,11 @@ mod test { use crate::encode::serialize; use crate::{OutPoint, Txid}; - use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::Hash; + use hex::DisplayHex as _; use crate::{ encode::{serialize_hex, Encodable}, - hex::ToHex, pset::{elip100::PSET_HWW_PREFIX, map::Map, PartiallySignedTransaction}, AssetId, }; @@ -280,7 +279,10 @@ mod test { crate::ContractHash::from_json_contract(VALID_CONTRACT).unwrap(), contract_hash ); - assert_eq!(asset_metadata.serialize().to_hex(),"b47b22656e74697479223a7b22646f6d61696e223a227465746865722e746f227d2c226973737565725f7075626b6579223a22303333376363656563306265656130323332656265313463626130313937613966626434356663663265633934363734396465393230653731343334633262393034222c226e616d65223a2254657468657220555344222c22707265636973696f6e223a382c227469636b6572223a2255534474222c2276657273696f6e223a307d688628ce04bab832e264ba83944033a6ae59d8e6350402c0baf50e2759d2969500000000"); + assert_eq!( + asset_metadata.serialize().to_lower_hex_string(), + "b47b22656e74697479223a7b22646f6d61696e223a227465746865722e746f227d2c226973737565725f7075626b6579223a22303333376363656563306265656130323332656265313463626130313937613966626434356663663265633934363734396465393230653731343334633262393034222c226e616d65223a2254657468657220555344222c22707265636973696f6e223a382c227469636b6572223a2255534474222c2276657273696f6e223a307d688628ce04bab832e264ba83944033a6ae59d8e6350402c0baf50e2759d2969500000000", + ); assert_eq!( AssetMetadata::deserialize(&asset_metadata.serialize()).unwrap(), @@ -297,11 +299,11 @@ mod test { key.consensus_encode(&mut vec).unwrap(); assert_eq!( - vec.to_hex(), - format!("08{}00{}", PSET_HWW_PREFIX.to_hex(), asset_id.into_tag()) + vec.to_lower_hex_string(), + format!("08{}00{}", PSET_HWW_PREFIX.to_lower_hex_string(), asset_id.into_tag()) ); - assert!(vec.to_hex().starts_with(&ELIP0100_IDENTIFIER[2..])); // cut prefix "fc: which is PSET_GLOBAL_PROPRIETARY serialized one level up + assert!(vec.to_lower_hex_string().starts_with(&ELIP0100_IDENTIFIER[2..])); // cut prefix "fc: which is PSET_GLOBAL_PROPRIETARY serialized one level up } #[test] @@ -340,7 +342,7 @@ mod test { pset.add_asset_metadata(asset_id, &asset_meta); - let expected_key = Vec::::from_hex(ELIP0100_ASSET_METADATA_RECORD_KEY).unwrap(); + let expected_key = hex::hex!(ELIP0100_ASSET_METADATA_RECORD_KEY); let values: Vec> = pset .global @@ -351,9 +353,9 @@ mod test { .map(|p| p.value) .collect(); assert_eq!(values.len(), 1); - assert_eq!(values[0].to_hex(), ELIP0100_ASSET_METADATA_RECORD_VALUE); + assert_eq!(values[0].to_lower_hex_string(), ELIP0100_ASSET_METADATA_RECORD_VALUE); - let txid_hex_non_convention = txid.as_byte_array().to_vec().to_hex(); + let txid_hex_non_convention = txid.as_byte_array().to_lower_hex_string(); assert_eq!( ELIP0100_ASSET_METADATA_RECORD_VALUE, ELIP0100_ASSET_METADATA_RECORD_VALUE_WRONG @@ -369,7 +371,7 @@ mod test { pset.add_token_metadata(token_id, &token_meta); - let expected_key = Vec::::from_hex(ELIP0100_TOKEN_METADATA_RECORD_KEY).unwrap(); + let expected_key = hex::hex!(ELIP0100_TOKEN_METADATA_RECORD_KEY); let values: Vec> = pset .global @@ -380,7 +382,7 @@ mod test { .map(|p| p.value) .collect(); assert_eq!(values.len(), 1); - assert_eq!(values[0].to_hex(), ELIP0100_TOKEN_METADATA_RECORD_VALUE); + assert_eq!(values[0].to_lower_hex_string(), ELIP0100_TOKEN_METADATA_RECORD_VALUE); } #[cfg(feature = "json-contract")] @@ -398,6 +400,6 @@ mod test { let expected = AssetId::from_str(ELIP0100_ASSET_TAG).unwrap(); - assert_eq!(asset_id.to_hex(), expected.to_hex()); + assert_eq!(asset_id.to_string(), expected.to_string()); } } diff --git a/src/pset/elip102.rs b/src/pset/elip102.rs index c1b0df1e..89331603 100644 --- a/src/pset/elip102.rs +++ b/src/pset/elip102.rs @@ -69,7 +69,7 @@ mod test { use super::*; use crate::AssetId; use crate::encode::{serialize_hex, Encodable}; - use crate::hex::{FromHex, ToHex}; + use hex::DisplayHex as _; // b'\xfc\rpset_liquidex' const ELIP0102_IDENTIFIER: &str = "fc0d707365745f6c69717569646578"; @@ -81,18 +81,18 @@ mod test { key.consensus_encode(&mut vec).unwrap(); assert_eq!( - vec.to_hex(), - format!("0d{}00", PSET_LIQUIDEX_PREFIX.to_hex()) + vec.to_lower_hex_string(), + format!("0d{}00", PSET_LIQUIDEX_PREFIX.to_lower_hex_string()), ); - assert!(vec.to_hex().starts_with(&ELIP0102_IDENTIFIER[2..])); // cut proprietary prefix "fc" + assert!(vec.to_lower_hex_string().starts_with(&ELIP0102_IDENTIFIER[2..])); // cut proprietary prefix "fc" } #[test] fn set_get_abf() { // An ABF that's different if serialized in reverse or not - let abf_hex = "3311111111111111111111111111111111111111111111111111111111111111"; - let abf_bytes = Vec::::from_hex(abf_hex).unwrap(); + const ABF_HEX: &str = "3311111111111111111111111111111111111111111111111111111111111111"; + let abf_bytes = hex::hex!(ABF_HEX); let abf = AssetBlindingFactor::from_slice(&abf_bytes).unwrap(); let mut input = Input::default(); @@ -101,7 +101,7 @@ mod test { assert_eq!(input.get_abf().unwrap().unwrap(), abf); let input_hex = serialize_hex(&input); assert!(input_hex.contains(ELIP0102_IDENTIFIER)); - assert!(input_hex.contains(abf_hex)); + assert!(input_hex.contains(ABF_HEX)); let mut output = Output::default(); assert!(output.get_abf().is_none()); @@ -109,7 +109,7 @@ mod test { assert_eq!(output.get_abf().unwrap().unwrap(), abf); let output_hex = serialize_hex(&output); assert!(output_hex.contains(ELIP0102_IDENTIFIER)); - assert!(output_hex.contains(abf_hex)); + assert!(output_hex.contains(ABF_HEX)); } #[test] diff --git a/src/pset/macros.rs b/src/pset/macros.rs index 25a04bc3..a6e637ed 100644 --- a/src/pset/macros.rs +++ b/src/pset/macros.rs @@ -16,7 +16,7 @@ macro_rules! hex_pset { ($s:expr) => { $crate::encode::deserialize( - & as $crate::hashes::hex::FromHex>::from_hex($s).unwrap(), + hex_conservative::decode_to_vec($s).unwrap(), ) }; } diff --git a/src/pset/mod.rs b/src/pset/mod.rs index 230369b5..be62d61c 100644 --- a/src/pset/mod.rs +++ b/src/pset/mod.rs @@ -785,24 +785,24 @@ impl Decodable for PartiallySignedTransaction { #[cfg(test)] mod tests { use super::*; - use crate::hex::{FromHex, ToHex}; + use hex::DisplayHex as _; #[track_caller] fn tx_pset_rtt(tx_hex: &str) { let tx: Transaction = - encode::deserialize(&Vec::::from_hex(tx_hex).unwrap()[..]).unwrap(); + encode::deserialize(&hex::decode_to_vec(tx_hex).unwrap()).unwrap(); let pset = PartiallySignedTransaction::from_tx(tx); let rtt_tx_hex = encode::serialize_hex(&pset.extract_tx().unwrap()); assert_eq!(tx_hex, rtt_tx_hex); let pset_rtt_hex = encode::serialize_hex(&pset); let pset2: PartiallySignedTransaction = - encode::deserialize(&Vec::::from_hex(&pset_rtt_hex).unwrap()[..]).unwrap(); + encode::deserialize(&hex::decode_to_vec(&pset_rtt_hex).unwrap()).unwrap(); assert_eq!(pset, pset2); } fn pset_rtt(pset_hex: &str) { let pset: PartiallySignedTransaction = - encode::deserialize(&Vec::::from_hex(pset_hex).unwrap()[..]).unwrap(); + encode::deserialize(&hex::decode_to_vec(pset_hex).unwrap()[..]).unwrap(); assert_eq!(encode::serialize_hex(&pset), pset_hex); } @@ -832,14 +832,15 @@ mod tests { use serde_json; use std::str::FromStr; + const PSET_HEX: &str = "70736574ff01020402000000010401010105010201fb04020000000001017a0bb9325c276764451bbc2eb82a4c8c4bb6f4007ba803e5a5ba72d0cd7c09848e1a091622d935953bf06e0b7393239c68c6f810a00fe19d11c6ae343cffd3037077da02535fe4ad0fcd675cd0f62bf73b60a554dc1569b80f1f76a2bbfc9f00d439bf4b160014d2cbec8783bd01c9f178348b08500a830a89a7f9010e20805131ba6b37165c026eed9325ac56059ba872fd569e3ed462734098688b4770010f0400000000000103088c83b50d0000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20104220020e5793ad956ee91ebf3543b37d110701118ed4078ffa0d477eacb8885e486ad8507fc047073657406210212bf0ea45b733dfde8ecb5e896306c4165c666c99fc5d1ab887f71393a975cea07fc047073657408040000000000010308f40100000000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b201040000"; + // Initially secp context and rng global state let secp = secp256k1_zkp::Secp256k1::new(); #[allow(deprecated)] let mut rng = rand::rngs::StdRng::seed_from_u64(0); - let pset_hex = "70736574ff01020402000000010401010105010201fb04020000000001017a0bb9325c276764451bbc2eb82a4c8c4bb6f4007ba803e5a5ba72d0cd7c09848e1a091622d935953bf06e0b7393239c68c6f810a00fe19d11c6ae343cffd3037077da02535fe4ad0fcd675cd0f62bf73b60a554dc1569b80f1f76a2bbfc9f00d439bf4b160014d2cbec8783bd01c9f178348b08500a830a89a7f9010e20805131ba6b37165c026eed9325ac56059ba872fd569e3ed462734098688b4770010f0400000000000103088c83b50d0000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b20104220020e5793ad956ee91ebf3543b37d110701118ed4078ffa0d477eacb8885e486ad8507fc047073657406210212bf0ea45b733dfde8ecb5e896306c4165c666c99fc5d1ab887f71393a975cea07fc047073657408040000000000010308f40100000000000007fc04707365740220230f4f5d4b7c6fa845806ee4f67713459e1b69e8e60fcee2e4940c7a0d5de1b201040000"; let mut pset: PartiallySignedTransaction = - encode::deserialize(&Vec::::from_hex(pset_hex).unwrap()[..]).unwrap(); + encode::deserialize(&hex::hex!(PSET_HEX)).unwrap(); let btc_txout_secrets_str = r#" { @@ -874,64 +875,55 @@ mod tests { fn basic_pset() { // Invalid psets // Check Global mandatory field - let pset_str = "70736574ff010401000105010001fb040200000000"; let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], + &hex::hex!("70736574ff010401000105010001fb040200000000"), ); pset.expect_err("Missing tx version"); // Check input mandatory field - let pset_str = "70736574ff010204020000000104010001fb040200000000"; let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], + &hex::hex!("70736574ff010204020000000104010001fb040200000000"), ); pset.expect_err("Missing inp count"); - let pset_str = "70736574ff010204020000000105010001fb040200000000"; let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], + &hex::hex!("70736574ff010204020000000105010001fb040200000000"), ); pset.expect_err("Missing out count"); - let pset_str = "70736574ff01020402000000010401000105010000"; let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], + &hex::hex!("70736574ff01020402000000010401000105010000"), ); pset.expect_err("Missing pset version"); // Check inp/out count mismatch - let pset_str = "70736574ff01020402000000010401000105010001fb04020000000001017a0ad92644e9bf6cb8d0856a8ca713c8a212d3a62142e85454b7865217890e52ec3108a469a9811ec1c1df7a98dbc3a7f71860293e98c6fad8a7ef6828344e9172547302217d344513f0a5ed1a60ebeba01460c505ad63d95b3542fb303aca8f9382777d160014bd5c31aaea2ddc585f317ee589bc6800bc95e7e6010e208965573f41392a88d8bb106cf13a7bdc69f1ab914cd5e8de11235467b514e5a9010f040100000000"; - let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], - ); + let pset = encode::deserialize::(&hex::hex!( + "70736574ff01020402000000010401000105010001fb04020000000001017a0ad92644e9bf6cb8d0856a8ca713c8a212d3a62142e85454b7865217890e52ec3108a469a9811ec1c1df7a98dbc3a7f71860293e98c6fad8a7ef6828344e9172547302217d344513f0a5ed1a60ebeba01460c505ad63d95b3542fb303aca8f9382777d160014bd5c31aaea2ddc585f317ee589bc6800bc95e7e6010e208965573f41392a88d8bb106cf13a7bdc69f1ab914cd5e8de11235467b514e5a9010f040100000000" + )); pset.expect_err("Input count mismatch"); // input mandatory field - let pset_str = "70736574ff01020402000000010401010105010001fb04020000000001017a0ad92644e9bf6cb8d0856a8ca713c8a212d3a62142e85454b7865217890e52ec3108a469a9811ec1c1df7a98dbc3a7f71860293e98c6fad8a7ef6828344e9172547302217d344513f0a5ed1a60ebeba01460c505ad63d95b3542fb303aca8f9382777d160014bd5c31aaea2ddc585f317ee589bc6800bc95e7e601010f040100000000"; - let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], - ); + let pset = encode::deserialize::(&hex::hex!( + "70736574ff01020402000000010401010105010001fb04020000000001017a0ad92644e9bf6cb8d0856a8ca713c8a212d3a62142e85454b7865217890e52ec3108a469a9811ec1c1df7a98dbc3a7f71860293e98c6fad8a7ef6828344e9172547302217d344513f0a5ed1a60ebeba01460c505ad63d95b3542fb303aca8f9382777d160014bd5c31aaea2ddc585f317ee589bc6800bc95e7e601010f040100000000" + )); pset.expect_err("Input mandatory field prevtxid"); // output mandatory amount field - let pset_str = "70736574ff01020402000000010401000105010101fb04020000000007fc04707365740220010101010101010101010101010101010101010101010101010101010101010101040000"; - let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], - ); + let pset = encode::deserialize::(&hex::hex!( + "70736574ff01020402000000010401000105010101fb04020000000007fc04707365740220010101010101010101010101010101010101010101010101010101010101010101040000" + )); pset.expect_err("Output non-mandatory field"); - let pset_str = "70736574ff01020402000000010401000105010101fb040200000000010308170000000000000007fc0470736574022009090909090909090909090909090909090909090909090909090909090909090100"; - let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], - ); + let pset = encode::deserialize::(&hex::hex!( + "70736574ff01020402000000010401000105010101fb040200000000010308170000000000000007fc0470736574022009090909090909090909090909090909090909090909090909090909090909090100" + )); pset.expect_err("Output mandatory field script pubkey"); // Valid Psets // Check both possible conf/explicit values are allowed for pset - let pset_str = "70736574ff01020402000000010401000105010101fb040200000000010308170000000000000007fc0470736574012109090909090909090909090909090909090909090909090909090909090909090907fc04707365740220090909090909090909090909090909090909090909090909090909090909090901040000"; - let pset = encode::deserialize::( - &Vec::::from_hex(pset_str).unwrap()[..], - ); + let pset = encode::deserialize::(&hex::hex!( + "70736574ff01020402000000010401000105010101fb040200000000010308170000000000000007fc0470736574012109090909090909090909090909090909090909090909090909090909090909090907fc04707365740220090909090909090909090909090909090909090909090909090909090909090901040000" + )); pset.expect("Both conf/explicit value are allowed be present in map"); // Commented code for quick test vector generation @@ -965,23 +957,23 @@ mod tests { fn pset_from_elements() { let pset_str = include_str!("../../tests/data/pset_swap_tutorial.hex"); - let bytes = Vec::::from_hex(pset_str).unwrap(); + let bytes = hex::decode_to_vec(pset_str).unwrap(); let pset = encode::deserialize::(&bytes).unwrap(); - assert_eq!(pset_str.len(), encode::serialize(&pset).to_hex().len()); - let back_hex = encode::serialize(&pset).to_hex(); + assert_eq!(pset_str.len(), encode::serialize(&pset).to_lower_hex_string().len()); + let back_hex = encode::serialize(&pset).to_lower_hex_string(); //assert_eq!(pset_str, &back_hex); //TODO this fails, field ordering? - let bytes = Vec::::from_hex(&back_hex).unwrap(); + let bytes = hex::decode_to_vec(&back_hex).unwrap(); let pset = encode::deserialize::(&bytes).unwrap(); - assert_eq!(&back_hex, &encode::serialize(&pset).to_hex()); + assert_eq!(&back_hex, &encode::serialize(&pset).to_lower_hex_string()); } #[test] fn pset_remove_in_out() { let pset_str = include_str!("../../tests/data/pset_swap_tutorial.hex"); - let bytes = Vec::::from_hex(pset_str).unwrap(); + let bytes = hex::decode_to_vec(pset_str).unwrap(); let mut pset = encode::deserialize::(&bytes).unwrap(); let n_inputs = pset.n_inputs(); @@ -1002,7 +994,7 @@ mod tests { let policy = crate::AssetId::from_str("5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225").unwrap(); let pk = bitcoin::key::PublicKey::from_str("020202020202020202020202020202020202020202020202020202020202020202").unwrap(); - let script = crate::Script::from_hex("0014d2bcde17e7744f6377466ca1bd35d212954674c8").unwrap(); + let script = crate::Script::from_hex_no_prefix("0014d2bcde17e7744f6377466ca1bd35d212954674c8").unwrap(); let sats_in = 10000; let sats_fee = 1000; let btc_txout_secrets = TxOutSecrets { diff --git a/src/pset/raw.rs b/src/pset/raw.rs index 66a4b9a2..39db0606 100644 --- a/src/pset/raw.rs +++ b/src/pset/raw.rs @@ -21,7 +21,7 @@ use std::{fmt, io}; use super::Error; use crate::encode::{self, deserialize, serialize, Decodable, Encodable, VarInt, MAX_VEC_SIZE}; -use crate::hex; +use hex::DisplayHex as _; /// A PSET key in its raw byte form. #[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)] #[cfg_attr( @@ -111,8 +111,7 @@ impl ProprietaryKey { 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: {}", self.type_value, self.key.as_hex()) } } diff --git a/src/pset/serialize.rs b/src/pset/serialize.rs index 31f86d32..227e21f5 100644 --- a/src/pset/serialize.rs +++ b/src/pset/serialize.rs @@ -25,7 +25,6 @@ use crate::encode::{ self, deserialize, deserialize_partial, serialize, Decodable, Encodable, VarInt, }; use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; -use crate::hex::ToHex; use crate::{AssetId, BlockHash, Script, Transaction, TxOut, Txid}; use bitcoin; use bitcoin::bip32::{ChildNumber, Fingerprint, KeySource}; @@ -54,7 +53,8 @@ pub trait Deserialize: Sized { /// Encode an object into a hex-encoded string pub fn serialize_hex(data: &T) -> String { - Serialize::serialize(data)[..].to_hex() + use hex::DisplayHex as _; + Serialize::serialize(data)[..].to_lower_hex_string() } impl_pset_de_serialize!(Transaction); diff --git a/src/script.rs b/src/script.rs index a1424ed3..0b0a4507 100644 --- a/src/script.rs +++ b/src/script.rs @@ -27,13 +27,12 @@ use std::default::Default; use std::{fmt, io, ops, str}; -use hex_conservative::DecodeVariableLengthBytesError; use secp256k1_zkp::{Verification, Secp256k1}; #[cfg(feature = "serde")] use serde; use crate::encode::{self, Decodable, Encodable}; use crate::hashes::Hash; -use crate::{hex, opcodes, ScriptHash, WScriptHash, PubkeyHash, WPubkeyHash}; +use crate::{opcodes, ScriptHash, WScriptHash, PubkeyHash, WPubkeyHash}; use bitcoin::PublicKey; @@ -78,22 +77,6 @@ impl fmt::UpperHex for Script { } } -impl hex::FromHex for Script { - type Err = DecodeVariableLengthBytesError; - - fn from_hex(s: &str) -> Result { - hex_conservative::decode_to_vec(s).map(|v| Script(Box::<[u8]>::from(v))) - } -} - -impl str::FromStr for Script { - type Err = ::Err; - - fn from_str(s: &str) -> Result { - hex::FromHex::from_hex(s) - } -} - #[derive(PartialEq, Eq, Debug, Clone)] /// An object which can be used to construct a script piece by piece pub struct Builder(Vec, Option); @@ -234,6 +217,17 @@ impl Script { /// Creates a new empty script pub fn new() -> Script { Script(vec![].into_boxed_slice()) } + /// Parse a hex-string with no length prefix as a [`Script`]. + #[deprecated(since = "0.27.0", note = "use from_hex_no_prefix instead")] + pub fn from_hex(s: &str) -> Result { + Self::from_hex_no_prefix(s) + } + + /// Parse a hex-string with no length prefix as a [`Script`]. + pub fn from_hex_no_prefix(s: &str) -> Result { + hex::decode_to_vec(s).map(|v| Script(Box::<[u8]>::from(v))) + } + /// Generates P2PK-type of scriptPubkey pub fn new_p2pk(pubkey: &PublicKey) -> Script { Builder::new() @@ -885,7 +879,6 @@ impl<'de> serde::Deserialize<'de> for Script { D: serde::Deserializer<'de>, { use std::fmt::Formatter; - use crate::hex::FromHex; struct Visitor; impl<'de> serde::de::Visitor<'de> for Visitor { @@ -899,7 +892,7 @@ impl<'de> serde::Deserialize<'de> for Script { where E: serde::de::Error, { - let v = Vec::from_hex(v).map_err(E::custom)?; + let v = hex::decode_to_vec(v).map_err(E::custom)?; Ok(Script::from(v)) } @@ -953,7 +946,6 @@ impl Decodable for Script { #[cfg(test)] mod test { - use crate::hex::FromHex; use bitcoin::PublicKey; use std::str::FromStr; @@ -965,6 +957,10 @@ mod test { #[test] fn script() { + // Clippy likes these at the top of the method + const KEYSTR_C: &str = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"; + const KEYSTR_U: &str = "41042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"; + let mut comp = vec![]; let mut script = Builder::new(); assert_eq!(&script[..], &comp[..]); @@ -987,12 +983,10 @@ mod test { script = script.push_slice(b"NRA4VR"); comp.extend([6u8, 78, 82, 65, 52, 86, 82].iter().copied()); assert_eq!(&script[..], &comp[..]); // keys - let keystr = "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"; - let key = PublicKey::from_str(&keystr[2..]).unwrap(); - script = script.push_key(&key); comp.extend(Vec::from_hex(keystr).unwrap().iter().copied()); assert_eq!(&script[..], &comp[..]); - let keystr = "41042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"; - let key = PublicKey::from_str(&keystr[2..]).unwrap(); - script = script.push_key(&key); comp.extend(Vec::from_hex(keystr).unwrap().iter().copied()); assert_eq!(&script[..], &comp[..]); + let key = PublicKey::from_str(&KEYSTR_C[2..]).unwrap(); + script = script.push_key(&key); comp.extend(hex::hex!(KEYSTR_C).iter().copied()); assert_eq!(&script[..], &comp[..]); + let key = PublicKey::from_str(&KEYSTR_U[2..]).unwrap(); + script = script.push_key(&key); comp.extend(hex::hex!(KEYSTR_U).iter().copied()); assert_eq!(&script[..], &comp[..]); // opcodes script = script.push_opcode(opcodes::all::OP_CHECKSIG); comp.push(0xACu8); assert_eq!(&script[..], &comp[..]); @@ -1004,7 +998,7 @@ mod test { // from txid 3bb5e6434c11fb93f64574af5d116736510717f2c595eb45b52c28e31622dfff which was in my mempool when I wrote the test let script = Builder::new().push_opcode(opcodes::all::OP_DUP) .push_opcode(opcodes::all::OP_HASH160) - .push_slice(&Vec::from_hex("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap()) + .push_slice(&hex::hex!("16e1ae70ff0fa102905d4af297f6912bda6cce19")) .push_opcode(opcodes::all::OP_EQUALVERIFY) .push_opcode(opcodes::all::OP_CHECKSIG) .into_script(); @@ -1085,7 +1079,7 @@ mod test { #[test] fn script_serialize() { - let hex_script = Vec::from_hex("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52").unwrap(); + let hex_script = hex::hex!("6c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52"); let script: Result = deserialize(&hex_script); assert!(script.is_ok()); assert_eq!(serialize(&script.unwrap()), hex_script); diff --git a/src/serde_utils.rs b/src/serde_utils.rs index 2924edf8..f9ba7fcd 100644 --- a/src/serde_utils.rs +++ b/src/serde_utils.rs @@ -7,7 +7,7 @@ pub mod btreemap_byte_values { // NOTE: This module can be exactly copied to use with HashMap. use ::std::collections::BTreeMap; - use crate::hex::{FromHex, ToHex}; + use hex::DisplayHex as _; use serde; pub fn serialize(v: &BTreeMap>, s: S) @@ -21,7 +21,7 @@ pub mod btreemap_byte_values { if s.is_human_readable() { let mut map = s.serialize_map(Some(v.len()))?; for (key, value) in v { - map.serialize_entry(key, &value.to_hex())?; + map.serialize_entry(key, &value.to_lower_hex_string())?; } map.end() } else { @@ -51,7 +51,7 @@ pub mod btreemap_byte_values { { let mut ret = BTreeMap::new(); while let Some((key, value)) = a.next_entry()? { - ret.insert(key, FromHex::from_hex(value).map_err(serde::de::Error::custom)?); + ret.insert(key, hex::decode_to_vec(value).map_err(serde::de::Error::custom)?); } Ok(ret) } @@ -223,7 +223,7 @@ pub mod hex_bytes { //! Module for serialization of byte arrays as hex strings. #![allow(missing_docs)] - use crate::hex::{FromHex, ToHex}; + use hex::DisplayHex as _; use serde; pub fn serialize(bytes: &T, s: S) -> Result @@ -231,7 +231,7 @@ pub mod hex_bytes { { // Don't do anything special when not human readable. if s.is_human_readable() { - s.serialize_str(&bytes.as_ref().to_hex()) + s.collect_str(&bytes.as_ref().as_hex()) } else { serde::Serialize::serialize(bytes, s) } @@ -239,14 +239,11 @@ pub mod hex_bytes { pub fn deserialize<'de, D, B>(d: D) -> Result where D: serde::Deserializer<'de>, - B: serde::Deserialize<'de> + FromHex, - ::Err: std::fmt::Display, + B: serde::Deserialize<'de> + From>, { struct Visitor(::std::marker::PhantomData); - impl serde::de::Visitor<'_> for Visitor - where - ::Err: std::fmt::Display, + impl>> serde::de::Visitor<'_> for Visitor { type Value = B; @@ -257,8 +254,8 @@ pub mod hex_bytes { fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { - if let Ok(hex) = ::std::str::from_utf8(v) { - FromHex::from_hex(hex).map_err(E::custom) + if let Ok(hex) = ::core::str::from_utf8(v) { + hex::decode_to_vec(hex).map_err(E::custom).map(B::from) } else { Err(E::invalid_value(serde::de::Unexpected::Bytes(v), &self)) } @@ -267,7 +264,7 @@ pub mod hex_bytes { fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { - FromHex::from_hex(v).map_err(E::custom) + hex::decode_to_vec(v).map_err(E::custom).map(B::from) } } diff --git a/src/sighash.rs b/src/sighash.rs index 14461ddc..4b42b663 100644 --- a/src/sighash.rs +++ b/src/sighash.rs @@ -969,18 +969,17 @@ impl std::str::FromStr for SchnorrSighashType { mod tests{ use super::*; use crate::encode::deserialize; - use crate::hex::FromHex; use std::str::FromStr; fn test_segwit_sighash(tx: &str, script: &str, input_index: usize, value: &str, hash_type: EcdsaSighashType, expected_result: &str) { - let tx: Transaction = deserialize(&Vec::::from_hex(tx).unwrap()[..]).unwrap(); - let script = Script::from(Vec::::from_hex(script).unwrap()); + let tx: Transaction = deserialize(&hex::decode_to_vec(tx).unwrap()).unwrap(); + let script = Script::from(hex::decode_to_vec(script).unwrap()); // A hack to parse sha256d strings are sha256 so that we don't reverse them... let raw_expected = crate::hashes::sha256::Hash::from_str(expected_result).unwrap(); let expected_result = Sighash::from_slice(&raw_expected[..]).unwrap(); let mut cache = SighashCache::new(&tx); - let value : confidential::Value = deserialize(&Vec::::from_hex(value).unwrap()[..]).unwrap(); + let value : confidential::Value = deserialize(&hex::decode_to_vec(value).unwrap()).unwrap(); let actual_result = cache.segwitv0_sighash(input_index, &script, value, hash_type); assert_eq!(actual_result, expected_result); } @@ -1007,8 +1006,8 @@ mod tests{ fn test_legacy_sighash(tx: &str, script: &str, input_index: usize, hash_type: EcdsaSighashType, expected_result: &str) { - let tx: Transaction = deserialize(&Vec::::from_hex(tx).unwrap()[..]).unwrap(); - let script = Script::from(Vec::::from_hex(script).unwrap()); + let tx: Transaction = deserialize(&hex::decode_to_vec(tx).unwrap()).unwrap(); + let script = Script::from(hex::decode_to_vec(script).unwrap()); // A hack to parse sha256d strings are sha256 so that we don't reverse them... let raw_expected = crate::hashes::sha256::Hash::from_str(expected_result).unwrap(); let expected_result = Sighash::from_slice(&raw_expected[..]).unwrap(); diff --git a/src/taproot.rs b/src/taproot.rs index 7f5940e3..e401bd6a 100644 --- a/src/taproot.rs +++ b/src/taproot.rs @@ -854,7 +854,6 @@ mod tests{ use super::*; use crate::hashes::HashEngine; use crate::hashes::sha256t::Tag; - use crate::hex::FromHex; use std::str::FromStr; fn tag_engine(tag_name: &str) -> sha256::HashEngine { @@ -892,11 +891,11 @@ mod tests{ let internal_key = UntweakedPublicKey::from_str("93c7378d96518a75448821c4f7c8f4bae7ce60f804d03d1f0628dd5dd0f5de51").unwrap(); let script_weights = vec![ - (10, Script::from_hex("51").unwrap()), // semantics of script don't matter for this test - (20, Script::from_hex("52").unwrap()), - (20, Script::from_hex("53").unwrap()), - (30, Script::from_hex("54").unwrap()), - (19, Script::from_hex("55").unwrap()), + (10, Script::from_hex_no_prefix("51").unwrap()), // semantics of script don't matter for this test + (20, Script::from_hex_no_prefix("52").unwrap()), + (20, Script::from_hex_no_prefix("53").unwrap()), + (30, Script::from_hex_no_prefix("54").unwrap()), + (19, Script::from_hex_no_prefix("55").unwrap()), ]; let tree_info = TaprootSpendInfo::with_huffman_tree(&secp, internal_key, script_weights.clone()).unwrap(); @@ -915,7 +914,7 @@ mod tests{ length, tree_info .script_map - .get(&(Script::from_hex(script).unwrap(), LeafVersion::default())) + .get(&(Script::from_hex_no_prefix(script).unwrap(), LeafVersion::default())) .expect("Present Key") .iter() .next() @@ -952,11 +951,11 @@ mod tests{ // A B C / \ // D E let scripts = [ - Script::from_hex("51").unwrap(), - Script::from_hex("52").unwrap(), - Script::from_hex("53").unwrap(), - Script::from_hex("54").unwrap(), - Script::from_hex("55").unwrap(), + Script::from_hex_no_prefix("51").unwrap(), + Script::from_hex_no_prefix("52").unwrap(), + Script::from_hex_no_prefix("53").unwrap(), + Script::from_hex_no_prefix("54").unwrap(), + Script::from_hex_no_prefix("55").unwrap(), ]; let builder = builder .add_leaf(2, scripts[0].clone()).unwrap() diff --git a/src/transaction.rs b/src/transaction.rs index 03e2b2be..69b08bf3 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1304,7 +1304,6 @@ mod tests { use crate::{encode::serialize, pset::PartiallySignedTransaction}; use crate::confidential; - use crate::hex::FromHex; use secp256k1_zkp::{self, ZERO_TWEAK}; use crate::script; @@ -2404,7 +2403,7 @@ mod tests { #[test] fn superfluous_asset_issuance() { - let tx = Vec::::from_hex("1ae80068000109fee1000000000000000000000000000000000000000000000000000000000000005acf37f60000c7280028a7000000006e000000010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010115190000b9bfb80000000100000000d8d8d8d8d8d8d8d8d8d8d8d8d8d80000000000b8bfb8").unwrap(); + let tx = hex::decode_to_vec("1ae80068000109fee1000000000000000000000000000000000000000000000000000000000000005acf37f60000c7280028a7000000006e000000010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010115190000b9bfb80000000100000000d8d8d8d8d8d8d8d8d8d8d8d8d8d80000000000b8bfb8").unwrap(); assert!(matches!( Transaction::consensus_decode(&tx[..]), Err(encode::Error::ParseFailed("superfluous asset issuance")),