diff --git a/.gitignore b/.gitignore index 01626769f..2bb34f4b4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ Cargo.lock **/target + +# The Claude config directory +.claude diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..9bd9e8232 --- /dev/null +++ b/TODO.md @@ -0,0 +1,6 @@ +# Notes from upgrade to bitcoin-beta + +## TODO + +- Check that there are no usages of `bitcoin::primitives` or `bitcoin::units`. + diff --git a/client/Cargo.toml b/client/Cargo.toml index b7c13e367..fc7243304 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -21,7 +21,8 @@ rustdoc-args = ["--cfg", "docsrs"] client-sync = ["jsonrpc"] [dependencies] -bitcoin = { version = "0.32.0", default-features = false, features = ["std", "serde"] } +# Branch `corepc`. hex stuff plus RC stuff (#5704, #5657, and #5710) +bitcoin = { version = "0.33.0-beta", path = "../../rust-bitcoin/bitcoin", default-features = false, features = ["std", "serde"] } log = "0.4" serde = { version = "1.0.103", default-features = false, features = [ "derive", "alloc" ] } serde_json = { version = "1.0.117" } diff --git a/client/src/client_sync/error.rs b/client/src/client_sync/error.rs index 331a81eeb..6e3743050 100644 --- a/client/src/client_sync/error.rs +++ b/client/src/client_sync/error.rs @@ -8,8 +8,9 @@ use bitcoin::hex; #[derive(Debug)] pub enum Error { JsonRpc(jsonrpc::error::Error), - HexToArray(hex::HexToArrayError), - HexToBytes(hex::HexToBytesError), + // TODO: Consider renaming these two variants now the inner type changed. + HexToArray(hex::DecodeFixedLengthBytesError), + HexToBytes(hex::DecodeVariableLengthBytesError), Json(serde_json::error::Error), BitcoinSerialization(bitcoin::consensus::encode::FromHexError), Io(io::Error), @@ -28,12 +29,12 @@ impl From for Error { fn from(e: jsonrpc::error::Error) -> Error { Error::JsonRpc(e) } } -impl From for Error { - fn from(e: hex::HexToArrayError) -> Self { Self::HexToArray(e) } +impl From for Error { + fn from(e: hex::DecodeFixedLengthBytesError) -> Self { Self::HexToArray(e) } } -impl From for Error { - fn from(e: hex::HexToBytesError) -> Self { Self::HexToBytes(e) } +impl From for Error { + fn from(e: hex::DecodeVariableLengthBytesError) -> Self { Self::HexToBytes(e) } } impl From for Error { diff --git a/integration_test/Cargo.toml b/integration_test/Cargo.toml index 05421c435..d92007abe 100644 --- a/integration_test/Cargo.toml +++ b/integration_test/Cargo.toml @@ -61,7 +61,9 @@ v17 = ["v18_and_below"] TODO = [] # This is a dirty hack while writing the tests. [dependencies] -bitcoin = { version = "0.32.0", default-features = false, features = ["std", "serde"] } +# Branch `corepc`. hex stuff plus RC stuff (#5704, #5657, and #5710) +bitcoin = { version = "0.33.0-beta", path = "../../rust-bitcoin/bitcoin", default-features = false, features = ["std", "serde"] } +hex-unstable = { package = "hex-conservative", version = "0.3.0", default-features = false, features = ["alloc"] } env_logger = "0.9.0" node = { package = "corepc-node", version = "0.11.0", path = "../node", default-features = false } rand = "0.8.5" diff --git a/integration_test/src/lib.rs b/integration_test/src/lib.rs index 63f4da29a..0ab08f1e1 100644 --- a/integration_test/src/lib.rs +++ b/integration_test/src/lib.rs @@ -3,8 +3,7 @@ use std::path::PathBuf; use bitcoin::bip32::{Fingerprint, Xpriv, Xpub}; -use bitcoin::secp256k1::{Secp256k1, XOnlyPublicKey}; -use bitcoin::Network; +use bitcoin::{Network, XOnlyPublicKey}; use node::{Conf, P2P}; use rand::distributions::Alphanumeric; use rand::Rng; @@ -86,7 +85,7 @@ impl NodeExt for Node { } fn create_mempool_transaction(&self) -> (bitcoin::Address, bitcoin::Txid) { - const MILLION_SATS: bitcoin::Amount = bitcoin::Amount::from_sat(1000000); + const MILLION_SATS: bitcoin::Amount = bitcoin::Amount::from_sat_u32(1000000); let address = self.client.new_address().expect("failed to get new address"); @@ -105,7 +104,8 @@ impl NodeExt for Node { let best_block_hash = self.client.best_block_hash().expect("best_block_hash"); let best_block = self.client.get_block(best_block_hash).expect("best_block"); - let tx = best_block.txdata[1].clone(); + + let tx = best_block.assume_checked(None).transactions()[1].clone(); (address, tx) } @@ -162,14 +162,13 @@ pub struct TestKeys { /// Returns deterministic test keys derived from a zero seed. pub fn test_keys() -> TestKeys { - let secp = Secp256k1::new(); let seed = [0u8; 32]; - let xprv = Xpriv::new_master(Network::Regtest, &seed).unwrap(); - let xpub = Xpub::from_priv(&secp, &xprv); + let xprv = Xpriv::new_master(Network::Regtest, &seed); + let xpub = Xpub::from_xpriv(&xprv); TestKeys { xprv, xpub, fingerprint: xpub.fingerprint(), - x_only_public_key: xprv.private_key.x_only_public_key(&secp).0, + x_only_public_key: xprv.private_key.x_only_public_key().0.into(), } } diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index 1b6fcdb0d..dd456a37f 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -5,6 +5,8 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. use bitcoin::consensus::encode; +#[allow(unused_imports)] // Because of feature gated tests. +use bitcoin::ext::*; use bitcoin::hex; use integration_test::{Node, NodeExt as _, Wallet}; use node::vtype::*; // All the version specific types. @@ -39,7 +41,8 @@ fn blockchain__get_best_block_hash__modelled() { let node = Node::with_wallet(Wallet::None, &[]); let json: GetBestBlockHash = node.client.get_best_block_hash().expect("getbestblockhash"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); model.unwrap(); } @@ -79,8 +82,8 @@ fn blockchain__get_block__modelled() { .find(|entry| entry.transaction.transaction.compute_txid() == mined_txid) .expect("mined transaction should be present in verbosity=2 results"); assert!(mined_entry.fee.is_some()); - assert!(!mined_entry.transaction.transaction.input.is_empty()); - assert!(!mined_entry.transaction.transaction.output.is_empty()); + assert!(!mined_entry.transaction.transaction.inputs.is_empty()); + assert!(!mined_entry.transaction.transaction.outputs.is_empty()); let json: GetBlockVerboseThree = node.client.get_block_verbose_three(block_hash).expect("getblock verbose=3"); @@ -140,7 +143,6 @@ fn blockchain__get_block_filter__modelled() { #[test] #[cfg(not(feature = "v22_and_below"))] fn blockchain__get_block_from_peer() { - use bitcoin::hashes::Hash; let (node1, _node2, _node3) = integration_test::three_node_network(); let now = std::time::SystemTime::now() @@ -152,8 +154,8 @@ fn blockchain__get_block_from_peer() { let mut header = bitcoin::block::Header { version: bitcoin::block::Version::from_consensus(0x20000000), prev_blockhash: node1.client.best_block_hash().expect("best_block_hash failed"), - merkle_root: bitcoin::TxMerkleNode::all_zeros(), - time: now, + merkle_root: bitcoin::TxMerkleNode::from_byte_array([0_u8; 32]), + time: bitcoin::BlockTime::from_u32(now), bits: bitcoin::CompactTarget::from_consensus(0x207fffff), nonce: 0, }; @@ -173,7 +175,7 @@ fn blockchain__get_block_hash__modelled() { let node = Node::with_wallet(Wallet::None, &[]); let json: GetBlockHash = node.client.get_block_hash(0).expect("getblockhash"); - let model: Result = json.into_model(); + let model: Result = json.into_model(); model.unwrap(); } @@ -349,7 +351,8 @@ fn blockchain__get_mempool_ancestors__modelled() { let json: GetMempoolAncestors = node.client.get_mempool_ancestors(child_txid).expect("getmempoolancestors"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); let ancestors = model.unwrap(); assert!(ancestors.0.contains(&parent_txid)); @@ -379,7 +382,8 @@ fn blockchain__get_mempool_descendants__modelled() { let json: GetMempoolDescendants = node.client.get_mempool_descendants(parent_txid).expect("getmempooldescendants"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); let descendants = model.unwrap(); assert!(descendants.0.contains(&child_txid)); @@ -436,7 +440,8 @@ fn blockchain__get_raw_mempool__modelled() { // verbose = false + mempool_sequence = false let json: GetRawMempool = node.client.get_raw_mempool().expect("getrawmempool"); - let model: Result = json.clone().into_model(); + let model: Result = + json.clone().into_model(); let mempool = model.unwrap(); // Sanity check. assert_eq!(mempool.0.len(), 1); @@ -454,7 +459,8 @@ fn blockchain__get_raw_mempool__modelled() { // verbose = false + mempool_sequence = true let json: GetRawMempoolSequence = node.client.get_raw_mempool_sequence().expect("getrawmempool sequence"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); let mempool = model.unwrap(); // Sanity check. assert_eq!(mempool.txids.len(), 1); @@ -646,7 +652,8 @@ fn blockchain__verify_tx_out_proof__modelled() { let proof = node.client.get_tx_out_proof(&[txid]).expect("gettxoutproof"); let json: VerifyTxOutProof = node.client.verify_tx_out_proof(&proof).expect("verifytxoutproof"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); let txids = model.unwrap(); // sanity check @@ -713,7 +720,7 @@ fn blockchain__wait_for_new_block__modelled() { fn create_child_spending_parent(node: &Node, parent_txid: bitcoin::Txid) -> bitcoin::Txid { let inputs = vec![Input { txid: parent_txid, vout: 0, sequence: None }]; let spend_address = node.client.new_address().expect("newaddress"); - let outputs = vec![Output::new(spend_address, bitcoin::Amount::from_sat(100_000))]; + let outputs = vec![Output::new(spend_address, bitcoin::Amount::from_sat_u32(100_000))]; let raw: CreateRawTransaction = node.client.create_raw_transaction(&inputs, &outputs).expect("createrawtransaction"); diff --git a/integration_test/tests/generating.rs b/integration_test/tests/generating.rs index 9c6989879..913c59f42 100644 --- a/integration_test/tests/generating.rs +++ b/integration_test/tests/generating.rs @@ -16,7 +16,7 @@ fn generating__generate_block__modelled() { node.fund_wallet(); let mining_addr = node.client.new_address().expect("failed to get new address"); let dest_addr = node.client.new_address().expect("failed to get new address"); - let amount = bitcoin::Amount::from_sat(1_000_000); + let amount = bitcoin::Amount::from_sat_u32(1_000_000); let txid = node .client .send_to_address_rbf(&dest_addr, amount) @@ -33,7 +33,8 @@ fn generating__generate_block__modelled() { .client .generate_block(&mining_addr.to_string(), &transactions) .expect("generateblock"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); model.unwrap(); } @@ -57,7 +58,7 @@ fn generating__generate__modelled() { let json: Generate = node.client.generate(NBLOCKS).expect("generate"); - let model: Result = json.into_model(); + let model: Result = json.into_model(); model.unwrap(); } @@ -71,7 +72,8 @@ fn generating__generate_to_address__modelled() { let json: GenerateToAddress = node.client.generate_to_address(NBLOCKS, &address).expect("generatetoaddress"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); model.unwrap(); } @@ -86,7 +88,8 @@ fn generating__generate_to_descriptor__modelled() { let json: GenerateToDescriptor = node.client.generate_to_descriptor(NBLOCKS, &descriptor).expect("generatetodescriptor"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); model.unwrap(); } @@ -113,7 +116,8 @@ fn generating__invalidate_block() { node.client.invalidate_block(new_best_block).expect("invalidateblock"); let json: GetBestBlockHash = node.client.get_best_block_hash().expect("getbestblockhash"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); let best_block = model.unwrap(); assert_eq!(old_best_block, best_block.0); diff --git a/integration_test/tests/hidden.rs b/integration_test/tests/hidden.rs index c7bb6caac..f30df0f3d 100644 --- a/integration_test/tests/hidden.rs +++ b/integration_test/tests/hidden.rs @@ -7,15 +7,15 @@ #[cfg(not(feature = "v28_and_below"))] use std::collections::HashMap; -#[cfg(not(feature = "v28_and_below"))] -use bitcoin::hashes::Hash; -#[cfg(not(feature = "v28_and_below"))] -use bitcoin::hex::DisplayHex; +#[allow(unused_imports)] // Because of feature gated tests. +use bitcoin::ext::*; #[cfg(not(feature = "v28_and_below"))] use bitcoin::{ - absolute, consensus, transaction, Amount, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, + absolute, consensus, transaction, Amount, OutPoint, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, }; +#[cfg(not(feature = "v28_and_below"))] +use hex_unstable::DisplayHex; use integration_test::{Node, NodeExt as _, Wallet}; use node::mtype; use node::vtype::*; // All the version specific types. @@ -110,17 +110,14 @@ fn hidden__get_orphan_txs__modelled() { .map(|i| Transaction { version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint { - txid: Txid::from_raw_hash(Txid::from_byte_array([i; 32]).into()), - vout: 0, - }, - script_sig: ScriptBuf::new(), + inputs: vec![TxIn { + previous_output: OutPoint { txid: Txid::from_byte_array([i; 32]), vout: 0 }, + script_sig: ScriptSigBuf::new(), sequence: Sequence::MAX, witness: Witness::new(), }], - output: vec![TxOut { - value: Amount::from_sat(100_000), + outputs: vec![TxOut { + amount: Amount::from_sat_u32(100_000), script_pubkey: address.script_pubkey(), }], }) diff --git a/integration_test/tests/mining.rs b/integration_test/tests/mining.rs index bcc3bf66f..4ff917be8 100644 --- a/integration_test/tests/mining.rs +++ b/integration_test/tests/mining.rs @@ -4,7 +4,8 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. -use bitcoin::SignedAmount; +use bitcoin::ext::*; +use bitcoin::{BlockTime, SignedAmount}; use integration_test::{Node, NodeExt as _, Wallet}; use node::vtype::*; use node::{mtype, TemplateRequest, TemplateRules}; // All the version specific types. @@ -78,7 +79,7 @@ fn mining__prioritise_transaction() { node.fund_wallet(); let (_addr, txid) = node.create_mempool_transaction(); - let fee_delta = SignedAmount::from_sat(10_000); + let fee_delta = SignedAmount::from_sat(10_000).expect("valid amount"); let json = node.client.prioritise_transaction(&txid, fee_delta).expect("prioritisetransaction"); assert!(json) // According to docs always returns true. } @@ -107,54 +108,52 @@ fn mining__submit_block() { // FIXME: Submitting this block sometimes works and sometimes returns 'inconclusive'. #[allow(dead_code)] fn submit_empty_block(node: &Node, bt: &mtype::GetBlockTemplate) { - use bitcoin::hashes::Hash as _; + use bitcoin::script::ScriptHash; use bitcoin::{ - absolute, block, transaction, Amount, Block, OutPoint, ScriptBuf, ScriptHash, Sequence, - Transaction, TxIn, TxMerkleNode, TxOut, Witness, + absolute, block, transaction, Amount, Block, OutPoint, ScriptPubKeyBuf, ScriptSigBuf, + Sequence, Transaction, TxIn, TxMerkleNode, TxOut, Witness, }; - let txdata = vec![Transaction { + let transactions = vec![Transaction { version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint::default(), + inputs: vec![TxIn { + previous_output: OutPoint::COINBASE_PREVOUT, // Just a dummy value. // FIXME: (Tobin) I don't know if this script is meaningful in anyway other than enabling function reusability in the code copied from BDK? - script_sig: ScriptBuf::builder() + script_sig: ScriptSigBuf::builder() .push_int(bt.height as _) - .push_int(rand::random()) // random number so that re-mining creates unique block + .expect("push height") + .push_int(rand::random()) + .expect("push random number so that re-mining creates unique block") .into_script(), sequence: Sequence::default(), witness: Witness::new(), }], - output: vec![TxOut { - value: Amount::ZERO, - script_pubkey: ScriptBuf::new_p2sh(&ScriptHash::all_zeros()), + outputs: vec![TxOut { + amount: Amount::ZERO, + script_pubkey: ScriptPubKeyBuf::new_p2sh(ScriptHash::from_byte_array([0; 20])), }], }]; - let mut block = Block { - header: block::Header { - version: block::Version::default(), - prev_blockhash: bt.previous_block_hash, - merkle_root: TxMerkleNode::all_zeros(), - time: Ord::max( - bt.min_time, - std::time::UNIX_EPOCH.elapsed().expect("elapsed").as_secs() as u32, - ), - bits: bt.bits, - nonce: 0, - }, - txdata, + let mut header = block::Header { + version: block::Version::default(), + prev_blockhash: bt.previous_block_hash, + merkle_root: TxMerkleNode::from_byte_array([0; 32]), + time: Ord::max( + BlockTime::from_u32(bt.min_time), + BlockTime::from_u32(std::time::UNIX_EPOCH.elapsed().expect("elapsed").as_secs() as u32), + ), + bits: bt.bits, + nonce: 0, }; - block.header.merkle_root = block.compute_merkle_root().expect("must compute"); - for nonce in 0..=u32::MAX { - block.header.nonce = nonce; - if block.header.target().is_met_by(block.block_hash()) { + header.nonce = nonce; + if header.target().is_met_by(header.block_hash()) { break; } } + let block = Block::new_unchecked(header, transactions); let _: () = node.client.submit_block(&block).expect("submitblock"); } @@ -162,9 +161,8 @@ fn submit_empty_block(node: &Node, bt: &mtype::GetBlockTemplate) { // FIXME: Submitting this block returns 'inconclusive'. #[allow(dead_code)] fn mining__submit_block_with_dummy_coinbase(node: &Node, bt: &mtype::GetBlockTemplate) { - use bitcoin::hashes::Hash as _; use bitcoin::{ - absolute, block, transaction, Amount, Block, OutPoint, ScriptBuf, Sequence, Transaction, + absolute, block, transaction, Amount, Block, OutPoint, ScriptSigBuf, Sequence, Transaction, TxIn, TxMerkleNode, TxOut, Witness, }; @@ -173,33 +171,33 @@ fn mining__submit_block_with_dummy_coinbase(node: &Node, bt: &mtype::GetBlockTem let coinbase = Transaction { version: transaction::Version::ONE, lock_time: absolute::LockTime::ZERO, - input: vec![TxIn { - previous_output: OutPoint::null(), - // FIXME: (Tobin) I don't know what this script means. Core return block invalid without it? - script_sig: ScriptBuf::builder() - .push_int(bt.height.into()) - .push_int(rand::random()) // random number so that re-mining creates unique block + inputs: vec![TxIn { + previous_output: OutPoint::COINBASE_PREVOUT, + // FIXME: (Tobin) I don't know what this script means. Core returns block invalid without it? + script_sig: ScriptSigBuf::builder() + .push_int(bt.height.try_into().expect("int conversion")) + .expect("push height") + .push_int(rand::random()) + .expect("push random number so that re-mining creates unique block") .into_script(), sequence: Sequence::default(), witness: Witness::new(), }], - output: vec![TxOut { - value: Amount::from_sat(50 * 100_000_000), + outputs: vec![TxOut { + amount: Amount::from_sat(50 * 100_000_000).expect("valid amount"), script_pubkey: address.script_pubkey(), }], }; - let mut block = Block { - header: block::Header { - version: bt.version, - prev_blockhash: bt.previous_block_hash, - merkle_root: TxMerkleNode::all_zeros(), - time: bt.min_time + 3600, // Some arbitrary amount of time. - bits: bt.bits, - nonce: 0, - }, - txdata: vec![coinbase], + let mut header = block::Header { + version: bt.version, + prev_blockhash: bt.previous_block_hash, + merkle_root: TxMerkleNode::from_byte_array([0; 32]), + time: BlockTime::from_u32(bt.min_time + 3600), // Some arbitrary amount of time. + bits: bt.bits, + nonce: 0, }; + let transactions = vec![coinbase]; let mut nonces = bt.nonce_range.split(","); let nonce_start = match nonces.next() { @@ -208,12 +206,13 @@ fn mining__submit_block_with_dummy_coinbase(node: &Node, bt: &mtype::GetBlockTem }; for nonce in nonce_start..=u32::MAX { - block.header.nonce = nonce; - if block.header.target().is_met_by(block.block_hash()) { + header.nonce = nonce; + if header.target().is_met_by(header.block_hash()) { break; } } + let block = Block::new_unchecked(header, transactions); let _: () = node.client.submit_block(&block).expect("submitblock"); } diff --git a/integration_test/tests/raw_transactions.rs b/integration_test/tests/raw_transactions.rs index 70332037e..80cdb9294 100644 --- a/integration_test/tests/raw_transactions.rs +++ b/integration_test/tests/raw_transactions.rs @@ -7,10 +7,11 @@ use bitcoin::bip32::DerivationPath; use bitcoin::consensus::encode; -use bitcoin::hex::FromHex as _; +use bitcoin::ext::*; use bitcoin::opcodes::all::*; use bitcoin::{ - absolute, consensus, hex, psbt, script, transaction, Amount, ScriptBuf, Transaction, TxOut, + absolute, consensus, hex, psbt, script, transaction, Amount, ScriptPubKeyBuf, Transaction, + TxOut, }; use integration_test::{test_keys, Node, NodeExt as _, Wallet}; use node::vtype::*; @@ -43,10 +44,10 @@ fn raw_transactions__combine_psbt__modelled() { .into_model() .expect("GetTxOut into model") .tx_out; - let spend_amount = Amount::from_sat(100_000); - let fee = Amount::from_sat(1000); + let spend_amount = Amount::from_sat_u32(100_000); + let fee = Amount::from_sat_u32(1000); // Calculate the change because we do not know the value of the UTXO. - let change_amount = tx_out.value - spend_amount - fee; + let change_amount = (tx_out.amount - spend_amount - fee).expect("invalid change amount"); let inputs = vec![Input { txid, vout: 0, sequence: None }]; @@ -215,8 +216,9 @@ fn raw_transactions__decode_script__modelled() { } // Script builder code copied from rust-bitcoin script unit tests. -fn arbitrary_p2pkh_script() -> ScriptBuf { - let pubkey_hash = <[u8; 20]>::from_hex("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap(); +fn arbitrary_p2pkh_script() -> ScriptPubKeyBuf { + let pubkey_hash = + hex::decode_to_array::<20>("16e1ae70ff0fa102905d4af297f6912bda6cce19").unwrap(); script::Builder::new() .push_opcode(OP_DUP) @@ -227,13 +229,15 @@ fn arbitrary_p2pkh_script() -> ScriptBuf { .into_script() } -fn arbitrary_multisig_script() -> ScriptBuf { - let pk1 = - <[u8; 33]>::from_hex("022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e") - .unwrap(); - let pk2 = - <[u8; 33]>::from_hex("03a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c0") - .unwrap(); +fn arbitrary_multisig_script() -> ScriptPubKeyBuf { + let pk1 = hex::decode_to_array::<33>( + "022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e", + ) + .unwrap(); + let pk2 = hex::decode_to_array::<33>( + "03a767c7221e9f15f870f1ad9311f5ab937d79fcaeee15bb2c722bca515581b4c0", + ) + .unwrap(); script::Builder::new() .push_opcode(OP_PUSHNUM_1) @@ -412,7 +416,7 @@ fn raw_transactions__test_mempool_accept__modelled() { .test_mempool_accept(std::slice::from_ref(&signed_tx)) .expect("testmempoolaccept"); #[cfg(feature = "v20_and_below")] - type TestMempoolAcceptError = hex::HexToArrayError; + type TestMempoolAcceptError = hex::DecodeFixedLengthBytesError; let model: Result = json.into_model(); let test_mempool = model.unwrap(); @@ -446,9 +450,9 @@ fn create_sign_send(node: &Node) { let (_addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. - let spend_amount = Amount::from_sat(100_000); - let fee = Amount::from_sat(1000); - let change_amount = tx_out.value - spend_amount - fee; + let spend_amount = Amount::from_sat_u32(100_000); + let fee = Amount::from_sat_u32(1000); + let change_amount = (tx_out.amount - spend_amount - fee).expect("invalid change amount"); let inputs = vec![Input { txid, vout, sequence: None }]; @@ -487,7 +491,8 @@ fn create_sign_send(node: &Node) { // The proves we did everything correctly. let json: SendRawTransaction = node.client.send_raw_transaction(&sign_raw_transaction.tx).expect("sendrawtransaction"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); model.unwrap(); } @@ -504,9 +509,9 @@ fn create_sign_with_key_send(node: &Node) { let (addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. - let spend_amount = Amount::from_sat(100_000); - let fee = Amount::from_sat(1000); - let change_amount = tx_out.value - spend_amount - fee; + let spend_amount = Amount::from_sat_u32(100_000); + let fee = Amount::from_sat_u32(1000); + let change_amount = (tx_out.amount - spend_amount - fee).expect("valid change amount"); let inputs = vec![Input { txid, vout, sequence: None }]; @@ -546,7 +551,8 @@ fn create_sign_with_key_send(node: &Node) { // The proves we did everything correctly. let json: SendRawTransaction = node.client.send_raw_transaction(&sign_raw_transaction.tx).expect("sendrawtransaction"); - let model: Result = json.into_model(); + let model: Result = + json.into_model(); model.unwrap(); } @@ -565,7 +571,7 @@ fn create_fund_sign_send(node: &Node) { let inputs = vec![Input { txid, vout, sequence: None }]; let mut outputs = vec![]; - let spend_amount = Amount::from_sat(50_00_000_000); + let spend_amount = Amount::from_sat(50_00_000_000).expect("valid amount"); // Just send back to ourself. let spend_address = node.client.new_address().expect("failed to create new address"); outputs.push(Output::new(spend_address, spend_amount)); @@ -602,9 +608,9 @@ fn create_a_raw_transaction(node: &Node) -> Transaction { let (_addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. - let spend_amount = Amount::from_sat(100_000); - let fee = Amount::from_sat(1000); - let change_amount = tx_out.value - spend_amount - fee; + let spend_amount = Amount::from_sat_u32(100_000); + let fee = Amount::from_sat_u32(1000); + let change_amount = (tx_out.amount - spend_amount - fee).expect("invalid change amount"); let inputs = vec![Input { txid, vout, sequence: None }]; @@ -637,7 +643,7 @@ fn create_utxo( node: &Node, ) -> (bitcoin::Address, bitcoin::Transaction, bitcoin::Txid, bitcoin::TxOut, u64) { // TODO: We should probably pass this into `create_mined_transaction`. - const MILLION_SATS: bitcoin::Amount = bitcoin::Amount::from_sat(1000000); + const MILLION_SATS: bitcoin::Amount = bitcoin::Amount::from_sat_u32(1000000); let (addr, tx) = node.create_mined_transaction(); // A million sat transaction. let txid = tx.compute_txid(); @@ -652,7 +658,7 @@ fn create_utxo( .expect("GetTxOut into model") .tx_out; - let (tx_out, vout) = if tx_out.value == MILLION_SATS { + let (tx_out, vout) = if tx_out.amount == MILLION_SATS { (tx_out, 0) } else { let out = node @@ -672,9 +678,9 @@ fn create_a_psbt(node: &Node) -> bitcoin::Psbt { let (_addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. - let spend_amount = Amount::from_sat(100_000); - let fee = Amount::from_sat(1000); - let change_amount = tx_out.value - spend_amount - fee; + let spend_amount = Amount::from_sat_u32(100_000); + let fee = Amount::from_sat_u32(1000); + let change_amount = (tx_out.amount - spend_amount - fee).expect("invalid change amount"); let inputs = vec![Input { txid, vout, sequence: None }]; diff --git a/integration_test/tests/signer.rs b/integration_test/tests/signer.rs index baa0e25c2..692795f22 100644 --- a/integration_test/tests/signer.rs +++ b/integration_test/tests/signer.rs @@ -5,6 +5,7 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. #![allow(unused_imports)] // Because of feature gated tests. +use bitcoin::ext::*; use integration_test::{Node, NodeExt as _, Wallet}; use node::vtype::*; use node::{mtype, Input, Output}; // All the version specific types. diff --git a/integration_test/tests/util.rs b/integration_test/tests/util.rs index b3501c6c4..fe589ea94 100644 --- a/integration_test/tests/util.rs +++ b/integration_test/tests/util.rs @@ -5,6 +5,7 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. #![allow(unused_imports)] // Because of feature gated tests. +use bitcoin::ext::*; use bitcoin::{address, amount, sign_message, PrivateKey, PublicKey}; use integration_test::{Node, NodeExt as _, Wallet}; use node::mtype; @@ -107,9 +108,8 @@ fn util__sign_message_with_priv_key__modelled() { let message = "integration test message"; // Derive the address from the private key - let secp = bitcoin::secp256k1::Secp256k1::new(); - let pubkey = privkey.public_key(&secp); - let addr = bitcoin::Address::p2pkh(pubkey, privkey.network); + let pubkey = privkey.public_key(); + let addr = bitcoin::Address::p2pkh(pubkey, privkey.network()); // Sign the message with the private key let json: SignMessageWithPrivKey = diff --git a/integration_test/tests/wallet.rs b/integration_test/tests/wallet.rs index 6831c5892..8e4bc7a21 100644 --- a/integration_test/tests/wallet.rs +++ b/integration_test/tests/wallet.rs @@ -11,9 +11,10 @@ use std::time::{SystemTime, UNIX_EPOCH}; use bitcoin::address::{self, Address, KnownHrp, NetworkChecked}; use bitcoin::bip32::{Xpriv, Xpub}; +use bitcoin::ext::*; use bitcoin::{ amount, hex, key, psbt, secp256k1, sign_message, Amount, CompressedPublicKey, FeeRate, Network, - PrivateKey, PublicKey, + NetworkKind, PrivateKey, PublicKey, }; use integration_test::{Node, NodeExt as _, Wallet}; use node::vtype::*; // All the version specific types. @@ -36,7 +37,7 @@ fn wallet__abandon_transaction() { let block_hash = block_hashes.expect("blockhash").0[0]; let dest_addr = node.client.new_address().expect("newaddress"); - let amount = bitcoin::Amount::from_sat(1_000_000); + let amount = bitcoin::Amount::from_sat_u32(1_000_000); let txid = node .client @@ -118,7 +119,7 @@ fn wallet__bump_fee__modelled() { let txid = node .client - .send_to_address_rbf(&address, Amount::from_sat(10_000)) + .send_to_address_rbf(&address, Amount::from_sat_u32(10_000)) .expect("sendtoaddress") .txid() .unwrap(); @@ -140,18 +141,13 @@ fn wallet__create_wallet_descriptor() { let node = Node::with_wallet(Wallet::Default, &[]); // BIP32 HD xprv/xpub for the creation of a descriptor with a private key that is in the wallet. - let secp = secp256k1::Secp256k1::new(); let seed = [0u8; 32]; - let xprv = Xpriv::new_master(Network::Regtest, &seed).unwrap(); - let xpub = Xpub::from_priv(&secp, &xprv); + let xprv = Xpriv::new_master(Network::Regtest, &seed); + let xpub = Xpub::from_priv(&xprv); let hdkey = xpub.to_string(); // Import the private key into the wallet. - let privkey = bitcoin::PrivateKey { - compressed: true, - network: Network::Regtest.into(), - inner: xprv.private_key, - }; + let privkey = bitcoin::PrivateKey::from_secp(xprv.private_key, NetworkKind::Test); let wif = privkey.to_wif(); let raw_descriptor = format!("wpkh({})", wif); let info = node.client.get_descriptor_info(&raw_descriptor).expect("get_descriptor_info"); @@ -344,7 +340,7 @@ fn wallet__get_raw_change_address__modelled() { #[test] fn wallet__get_received_by_address__modelled() { - let amount = Amount::from_sat(10_000); + let amount = Amount::from_sat_u32(10_000); let node = Node::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -370,7 +366,7 @@ fn wallet__get_received_by_label__modelled() { let label = "test-label"; // Send some coins to the label - let amount = Amount::from_sat(10_000); + let amount = Amount::from_sat_u32(10_000); let address = node.client.new_address_with_label(label).unwrap().assume_checked(); let _ = node.client.send_to_address(&address, amount).unwrap(); node.mine_a_block(); @@ -390,7 +386,7 @@ fn wallet__get_transaction__modelled() { let txid = node .client - .send_to_address(&address, Amount::from_sat(10_000)) + .send_to_address(&address, Amount::from_sat_u32(10_000)) .expect("sendtoaddress") .txid() .unwrap(); @@ -454,9 +450,8 @@ fn wallet__import_address() { PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); // Derive the address from the private key - let secp = bitcoin::secp256k1::Secp256k1::new(); - let pubkey = privkey.public_key(&secp); - let addr = bitcoin::Address::p2pkh(pubkey, privkey.network); + let pubkey = privkey.public_key(); + let addr = bitcoin::Address::p2pkh(pubkey, privkey.network()); let _: () = node.client.import_address(&addr).expect("importaddress"); } @@ -483,10 +478,10 @@ fn wallet__import_descriptors() { // 2. Use a known private key, derive the address from it and send some coins to it. let privkey = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); - let secp = secp256k1::Secp256k1::new(); - let pubkey = privkey.public_key(&secp); - let address = Address::p2wpkh(&CompressedPublicKey(pubkey.inner), KnownHrp::Regtest); - let amount = Amount::from_sat(10_000); + let pubkey = privkey.public_key(); + let address = + Address::p2wpkh(CompressedPublicKey::from_secp(pubkey.to_inner()), KnownHrp::Regtest); + let amount = Amount::from_sat_u32(10_000); let _txid = node.client.send_to_address(&address, amount).expect("sendtoaddress"); // 3. Get the descriptor from the private key. @@ -557,7 +552,7 @@ fn wallet__list_address_groupings__modelled() { node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); - let amount = Amount::from_sat(10_000); + let amount = Amount::from_sat_u32(10_000); node.client.send_to_address(&address, amount).expect("sendtoaddress").txid().unwrap(); node.mine_a_block(); @@ -588,7 +583,7 @@ fn wallet__list_received_by_label__modelled() { let label = "test-label"; // Send some coins to the label - let amount = Amount::from_sat(10_000); + let amount = Amount::from_sat_u32(10_000); let address = node.client.new_address_with_label(label).unwrap().assume_checked(); let _ = node.client.send_to_address(&address, amount).unwrap(); node.mine_a_block(); @@ -605,7 +600,7 @@ fn wallet__list_received_by_address__modelled() { let node = Node::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); - let amount = Amount::from_sat(10_000); + let amount = Amount::from_sat_u32(10_000); let _ = node.client.send_to_address(&address, amount).expect("sendtoaddress"); node.mine_a_block(); @@ -623,7 +618,7 @@ fn wallet__list_since_block__modelled() { let node = Node::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); - let amount = Amount::from_sat(5_000); + let amount = Amount::from_sat_u32(5_000); node.client.send_to_address(&addr, amount).expect("sendtoaddress"); node.mine_a_block(); @@ -641,7 +636,7 @@ fn wallet__list_transactions__modelled() { node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); - let amount = Amount::from_sat(5_000); + let amount = Amount::from_sat_u32(5_000); node.client.send_to_address(&addr, amount).expect("sendtoaddress"); node.mine_a_block(); @@ -892,7 +887,7 @@ fn wallet__psbt_bump_fee__modelled() { let txid = node .client - .send_to_address_rbf(&address, Amount::from_sat(10_000)) + .send_to_address_rbf(&address, Amount::from_sat_u32(10_000)) .expect("sendtoaddress") .txid() .unwrap(); @@ -954,18 +949,18 @@ fn wallet__send_many__modelled() { let addr2 = node.client.new_address().expect("newaddress"); let mut amounts = BTreeMap::new(); - amounts.insert(addr1, Amount::from_sat(100_000)); - amounts.insert(addr2, Amount::from_sat(100_000)); + amounts.insert(addr1, Amount::from_sat_u32(100_000)); + amounts.insert(addr2, Amount::from_sat_u32(100_000)); let json: SendMany = node.client.send_many(amounts.clone()).expect("sendmany"); - let model: Result = json.into_model(); + let model: Result = json.into_model(); model.unwrap(); #[cfg(not(feature = "v20_and_below"))] { let json_verbose: SendManyVerbose = node.client.send_many_verbose(amounts).expect("sendmany verbose"); - let model_verbose: Result = + let model_verbose: Result = json_verbose.into_model(); model_verbose.unwrap(); } @@ -1007,8 +1002,8 @@ fn wallet__send_to_address__modelled() { let address = node.client.new_address().expect("failed to create new address"); let json: SendToAddress = - node.client.send_to_address(&address, Amount::from_sat(10_000)).expect("sendtddress"); - let model: Result = json.into_model(); + node.client.send_to_address(&address, Amount::from_sat_u32(10_000)).expect("sendtddress"); + let model: Result = json.into_model(); model.unwrap(); } @@ -1020,7 +1015,7 @@ fn wallet__set_tx_fee() { #[cfg(not(feature = "v29_and_below"))] let node = Node::with_wallet(Wallet::Default, &["-deprecatedrpc=settxfee"]); - let fee_rate = FeeRate::from_sat_per_vb(2).expect("2 sat/vb is valid"); + let fee_rate = FeeRate::from_sat_per_vb(2); let json: SetTxFee = node.client.set_tx_fee(fee_rate).expect("settxfee"); assert!(json.0); @@ -1076,7 +1071,7 @@ fn wallet__simulate_raw_transaction() { node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); - let amount = Amount::from_sat(10_000); + let amount = Amount::from_sat_u32(10_000); let txid1 = node.client.send_to_address(&address, amount).expect("sendtoaddress").txid().unwrap(); @@ -1104,7 +1099,7 @@ fn wallet__wallet_create_funded_psbt__modelled() { node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); - let outputs = BTreeMap::from([(addr, Amount::from_sat(100_000))]); + let outputs = BTreeMap::from([(addr, Amount::from_sat_u32(100_000))]); let json: WalletCreateFundedPsbt = node .client .wallet_create_funded_psbt(vec![], vec![outputs]) @@ -1123,7 +1118,7 @@ fn wallet__wallet_process_psbt__modelled() { node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); - let outputs = BTreeMap::from([(addr, Amount::from_sat(50_000))]); + let outputs = BTreeMap::from([(addr, Amount::from_sat_u32(50_000))]); let funded_psbt: WalletCreateFundedPsbt = node .client .wallet_create_funded_psbt(vec![], vec![outputs]) diff --git a/integration_test/tests/zmq.rs b/integration_test/tests/zmq.rs index 71be726de..df5565e4b 100644 --- a/integration_test/tests/zmq.rs +++ b/integration_test/tests/zmq.rs @@ -5,6 +5,7 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. #![allow(unused_imports)] // Because of feature gated tests. +use bitcoin::ext::*; use integration_test::{Node, NodeExt as _, Wallet}; use node::vtype::*; // All the version specific types. diff --git a/types/Cargo.toml b/types/Cargo.toml index 8d1690c68..bcdc3cacd 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -14,11 +14,15 @@ exclude = ["tests", "contrib"] [features] default = ["std"] -std = ["bitcoin/std"] +std = ["bitcoin/std", "encoding/std", "hex-unstable/std", "p2p/std"] serde-deny-unknown-fields = [] [dependencies] -bitcoin = { version = "0.32.0", default-features = false, features = ["serde", "base64", "secp-recovery"] } +# Branch `corepc`. hex stuff plus RC stuff (#5704, #5657, and #5710) +bitcoin = { version = "0.33.0-beta", path = "../../rust-bitcoin/bitcoin", default-features = false, features = ["serde", "base64", "secp-recovery"] } +encoding = { package = "bitcoin-consensus-encoding", path = "../../rust-bitcoin/consensus_encoding", default-features = false } +hex-unstable = { package = "hex-conservative", version = "0.3.0", default-features = false } +p2p = { package = "bitcoin-p2p-messages", path = "../../rust-bitcoin/p2p", default-features = false } serde = { version = "1.0.103", default-features = false, features = [ "derive", "alloc" ] } serde_json = { version = "1.0.117" } diff --git a/types/src/lib.rs b/types/src/lib.rs index 845e098fa..df3da82a4 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -36,11 +36,11 @@ pub mod v30; pub mod model; use core::fmt; +use core::num::NonZeroU64; use bitcoin::address::{self, Address, NetworkUnchecked}; use bitcoin::amount::ParseAmountError; -use bitcoin::hex::{self, FromHex as _}; -use bitcoin::{Amount, FeeRate, ScriptBuf, Witness}; +use bitcoin::{hex, Amount, FeeRate, ScriptPubKeyBuf, ScriptSigBuf, Witness}; use serde::{Deserialize, Serialize}; use crate::error::write_err; @@ -89,17 +89,23 @@ impl fmt::Display for NumericError { impl std::error::Error for NumericError {} /// Converts `fee_rate` in BTC/kB to `FeeRate`. -fn btc_per_kb(btc_per_kb: f64) -> Result, ParseAmountError> { +fn btc_per_kb(btc_per_kb: f64) -> Result { // TODO: After upgrade to bitcoin `v0.33` use `FeeRate::from_sat_per_kvb()`. let per_kb = Amount::from_btc(btc_per_kb)?; - Ok(FeeRate::from_sat_per_vb(per_kb.to_sat()).and_then(|fee_rate| fee_rate.checked_div(1000))) + // Just cast away high bits, there is no sane fee rate that does not fit in a u32. + let per_kb = per_kb.to_sat() as u32; + Ok(FeeRate::from_sat_per_vb(per_kb) / NonZeroU64::new(1000).expect("1000 is non-zero")) } // TODO: Remove this function if a new `Witness` constructor gets added. // https://github.com/rust-bitcoin/rust-bitcoin/issues/4350 -fn witness_from_hex_slice>(witness: &[T]) -> Result { - let bytes: Vec> = - witness.iter().map(|hex| Vec::from_hex(hex.as_ref())).collect::>()?; +fn witness_from_hex_slice>( + witness: &[T], +) -> Result { + let bytes: Vec> = witness + .iter() + .map(|hex| bitcoin::hex::decode_to_vec(hex.as_ref())) + .collect::>()?; Ok(Witness::from_slice(&bytes)) } @@ -208,7 +214,7 @@ pub struct ScriptPubKey { #[derive(Debug)] pub enum ScriptPubKeyError { /// Conversion of the `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `addresses` field failed. @@ -238,8 +244,8 @@ impl std::error::Error for ScriptPubKeyError { } impl ScriptPubKey { - fn script_buf(&self) -> Result { - ScriptBuf::from_hex(&self.hex) + fn script_buf(&self) -> Result { + ScriptPubKeyBuf::from_hex_no_length_prefix(&self.hex) } fn address(&self) -> Option, address::ParseError>> { @@ -250,7 +256,8 @@ impl ScriptPubKey { pub fn into_model(self) -> Result { use ScriptPubKeyError as E; - let script_pubkey = ScriptBuf::from_hex(&self.hex).map_err(E::Hex)?; + let script_pubkey = + ScriptPubKeyBuf::from_hex_no_length_prefix(&self.hex).map_err(E::Hex)?; let address = self.address.map(|s| s.parse::>().map_err(E::Address)).transpose()?; @@ -284,8 +291,8 @@ pub struct ScriptSig { } impl ScriptSig { - pub fn script_buf(&self) -> Result { - ScriptBuf::from_hex(&self.hex) + pub fn script_buf(&self) -> Result { + ScriptSigBuf::from_hex_no_length_prefix(&self.hex) } } @@ -298,6 +305,6 @@ mod tests { // per kB = per kvB because this is a conversion of legacy transaction weights. let f: f64 = 0.000001; let got = btc_per_kb(f).unwrap(); - assert_eq!(got, Some(FeeRate::from_sat_per_kwu(25))) + assert_eq!(got, FeeRate::from_sat_per_kwu(25)) } } diff --git a/types/src/model/blockchain.rs b/types/src/model/blockchain.rs index eb405ff9a..5c42ae9dd 100644 --- a/types/src/model/blockchain.rs +++ b/types/src/model/blockchain.rs @@ -10,8 +10,8 @@ use alloc::collections::BTreeMap; use bitcoin::address::NetworkUnchecked; use bitcoin::hashes::sha256; use bitcoin::{ - block, Address, Amount, Block, BlockHash, CompactTarget, FeeRate, Network, OutPoint, ScriptBuf, - Target, TxMerkleNode, TxOut, Txid, Weight, Work, Wtxid, + block, Address, Amount, Block, BlockHash, CompactTarget, FeeRate, Network, OutPoint, + ScriptPubKeyBuf, Target, TxMerkleNode, TxOut, Txid, Weight, WitnessScriptBuf, Work, Wtxid, }; use serde::{Deserialize, Serialize}; @@ -21,6 +21,7 @@ use super::{GetRawTransactionVerbose, ScriptPubKey}; #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct DumpTxOutSet { /// The number of coins written in the snapshot. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub coins_written: Amount, /// The hash of the base of the snapshot. pub base_hash: BlockHash, @@ -39,8 +40,8 @@ pub struct DumpTxOutSet { pub struct GetBestBlockHash(pub BlockHash); /// Models the result of JSON-RPC method `getblock` with verbosity set to 0. -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct GetBlockVerboseZero(pub Block); +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct GetBlockVerboseZero(#[serde(with = "bitcoin::as_consensus")] pub Block); /// Models the result of JSON-RPC method `getblock` with verbosity set to 1. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -134,6 +135,7 @@ pub struct GetBlockVerboseTwoTransaction { /// The transaction data (same as `getrawtransaction` verbose output). pub transaction: GetRawTransactionVerbose, /// The transaction fee in BTC (omitted if block undo data is not available). + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub fee: Option, } @@ -188,6 +190,7 @@ pub struct GetBlockVerboseThreeTransaction { /// The prevout data aligned with the transaction input order. pub prevouts: Vec>, /// The transaction fee in BTC, omitted if block undo data is not available. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub fee: Option, } @@ -200,6 +203,7 @@ pub struct GetBlockVerboseThreePrevout { /// The height of the prevout. pub height: u32, /// The value in BTC. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub value: Amount, /// The script pubkey. pub script_pubkey: ScriptPubKey, @@ -245,7 +249,7 @@ pub struct GetBlockchainInfo { /// Status of softforks in progress, maps softfork name -> [`Softfork`] (empty from v29 onwards). pub softforks: BTreeMap, /// The block challenge (aka. block script) - pub signet_challenge: Option, // Only from v29 onwards + pub signet_challenge: Option, // Only from v29 onwards /// Any network and blockchain warnings. pub warnings: Vec, } @@ -332,12 +336,13 @@ pub struct Bip9SoftforkStatistics { pub struct GetBlockCount(pub u64); /// Models the result of JSON-RPC method `getblockfilter`. -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetBlockFilter { /// The filter data. pub filter: Vec, /// The hex-encoded filter header. - pub header: bitcoin::bip158::FilterHash, + #[serde(with = "bitcoin::as_consensus")] + pub header: p2p::message_filter::FilterHash, } /// Models the result of JSON-RPC method `getblockhash`. @@ -345,8 +350,8 @@ pub struct GetBlockFilter { pub struct GetBlockHash(pub BlockHash); /// Models the result of JSON-RPC method `getblockheader`. -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct GetBlockHeader(pub block::Header); +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct GetBlockHeader(#[serde(with = "bitcoin::as_consensus")] pub block::Header); /// Models the result of JSON-RPC method `getblockheader`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -384,18 +389,20 @@ pub struct GetBlockHeaderVerbose { } /// Models the result of JSON-RPC method `getblockstats`. -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +// #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +// FIMXE: How do we serde a `Vec`? +#[derive(Clone, Debug, PartialEq)] pub struct GetBlockStats { /// Average fee in the block. pub average_fee: Amount, /// Average feerate. - pub average_fee_rate: Option, + pub average_fee_rate: FeeRate, /// Average transaction size. pub average_tx_size: u32, /// The block hash (to check for potential reorgs). pub block_hash: BlockHash, /// Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per virtual byte). - pub fee_rate_percentiles: Vec>, + pub fee_rate_percentiles: Vec, /// The height of the block. pub height: u32, /// The number of inputs (excluding coinbase). @@ -403,7 +410,7 @@ pub struct GetBlockStats { /// Maximum fee in the block. pub max_fee: Amount, /// Maximum feerate (in satoshis per virtual byte). - pub max_fee_rate: Option, + pub max_fee_rate: FeeRate, /// Maximum transaction size. pub max_tx_size: u32, /// Truncated median fee in the block. @@ -415,7 +422,7 @@ pub struct GetBlockStats { /// Minimum fee in the block. pub minimum_fee: Amount, /// Minimum feerate (in satoshis per virtual byte). - pub minimum_fee_rate: Option, + pub minimum_fee_rate: FeeRate, /// Minimum transaction size. pub minimum_tx_size: u32, /// The number of outputs. @@ -622,6 +629,7 @@ pub enum ActivityEntry { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct SpendActivity { /// The total amount of the spent output. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// The blockhash (omitted if unconfirmed). pub block_hash: Option, @@ -643,6 +651,7 @@ pub struct SpendActivity { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct ReceiveActivity { /// The total amount in BTC of the new output. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// The block that this receive is in (omitted if unconfirmed). pub block_hash: Option, @@ -726,12 +735,16 @@ pub struct MempoolEntry { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct MempoolEntryFees { /// Transaction fee in BTC. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub base: Amount, /// Transaction fee with fee deltas used for mining priority. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub modified: Amount, /// Modified fees (see above) of in-mempool ancestors (including this one). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub ancestor: Amount, /// Modified fees (see above) of in-mempool descendants (including this one). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub descendant: Amount, } @@ -756,10 +769,13 @@ pub struct GetMempoolInfo { /// Minimum fee rate in BTC/kB for a transaction to be accepted. /// /// This is the maximum of `minrelaytxfee` and the minimum mempool fee. - pub mempool_min_fee: Option, + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor")] + pub mempool_min_fee: FeeRate, /// Current minimum relay fee for transactions. - pub min_relay_tx_fee: Option, + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor")] + pub min_relay_tx_fee: FeeRate, /// Minimum fee rate increment for mempool limiting or replacement. v24 and later only. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub incremental_relay_fee: Option, /// Current number of transactions that haven't passed initial broadcast yet. v21 and later only. pub unbroadcast_count: Option, @@ -797,6 +813,7 @@ pub struct GetTxOut { /// The number of confirmations (signed to match other types with the same field name). pub confirmations: u32, /// The returned `TxOut` (strongly typed). + #[serde(with = "bitcoin::as_consensus")] pub tx_out: TxOut, /// Address that `tx_out` spends to. /// @@ -829,10 +846,12 @@ pub struct GetTxOutSetInfo { /// The estimated size of the chainstate on disk (not available when coinstatsindex is used). pub disk_size: Option, /// The total amount. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub total_amount: Amount, /// The serialized hash (only present if 'muhash' hash_type is chosen). pub muhash: Option, // FIXME: What sort of hash is this? /// The total amount of coins permanently excluded from the UTXO set (only available if coinstatsindex is used). + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub total_unspendable_amount: Option, /// Info on amounts in the block at this block height (only available if coinstatsindex is used). pub block_info: Option, @@ -842,12 +861,16 @@ pub struct GetTxOutSetInfo { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetTxOutSetInfoBlockInfo { /// Total amount of all prevouts spent in this block. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub prevout_spent: Amount, /// Coinbase subsidy amount of this block. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub coinbase: Amount, /// Total amount of new outputs created by this block. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub new_outputs_ex_coinbase: Amount, /// Total amount of unspendable outputs created in this block. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub unspendable: Amount, /// Detailed view of unspendable categories. pub unspendables: GetTxOutSetInfoUnspendables, @@ -857,12 +880,16 @@ pub struct GetTxOutSetInfoBlockInfo { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetTxOutSetInfoUnspendables { /// The unspendable amount of the Genesis block subsidy. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub genesis_block: Amount, /// Transactions overridden by duplicates (no longer possible with BIP30). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub bip30: Amount, /// Amounts sent to scripts that are unspendable (for example OP_RETURN outputs). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub scripts: Amount, /// Fee rewards that miners did not claim in their coinbase transaction. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub unclaimed_rewards: Amount, } @@ -883,6 +910,7 @@ pub struct GetTxSpendingPrevoutItem { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct LoadTxOutSet { /// The number of coins loaded from the snapshot. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub coins_loaded: Amount, /// The hash of the base of the snapshot. pub tip_hash: BlockHash, @@ -950,6 +978,7 @@ pub struct ScanTxOutSetStart { /// The unspents. pub unspents: Vec, /// The total amount of all found unspent outputs in BTC. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub total_amount: Amount, } @@ -961,10 +990,11 @@ pub struct ScanTxOutSetUnspent { /// The vout value. pub vout: u32, /// The output script. - pub script_pubkey: ScriptBuf, + pub script_pubkey: ScriptPubKeyBuf, /// A specialized descriptor for the matched output script. For v18 onwards. pub descriptor: Option, /// The total amount in BTC of the unspent output. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// Whether this is a coinbase output. For v25 onwards. pub coinbase: Option, diff --git a/types/src/model/generating.rs b/types/src/model/generating.rs index 76e6f1951..4f72c2d8a 100644 --- a/types/src/model/generating.rs +++ b/types/src/model/generating.rs @@ -26,6 +26,7 @@ pub struct GenerateBlock { /// Hash of generated block. pub hash: BlockHash, /// Hex of generated block, only present when submit=false. + #[serde(with = "bitcoin::as_consensus::opt")] pub hex: Option, } diff --git a/types/src/model/hidden.rs b/types/src/model/hidden.rs index 405f95c20..82e8afc12 100644 --- a/types/src/model/hidden.rs +++ b/types/src/model/hidden.rs @@ -23,6 +23,7 @@ pub struct EstimateRawFee { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct RawFeeDetail { /// Estimate fee rate in BTC/kB. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub fee_rate: Option, /// Exponential decay (per block) for historical moving average of confirmation data. pub decay: f64, @@ -40,8 +41,10 @@ pub struct RawFeeDetail { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct RawFeeRange { /// Start of feerate range. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub start_range: Option, /// End of feerate range. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub end_range: Option, /// Number of txs over history horizon in the feerate range that were confirmed within target. pub within_target: f64, @@ -110,5 +113,6 @@ pub struct GetOrphanTxsVerboseTwoEntry { /// List of peer ids that we store this transaction for. pub from: Vec, /// The orphan transaction. + #[serde(with = "bitcoin::as_consensus")] pub transaction: Transaction, } diff --git a/types/src/model/mining.rs b/types/src/model/mining.rs index 4b31d0086..e6814b147 100644 --- a/types/src/model/mining.rs +++ b/types/src/model/mining.rs @@ -74,6 +74,7 @@ pub struct GetBlockTemplate { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct BlockTemplateTransaction { /// The transaction. + #[serde(with = "bitcoin::as_consensus")] pub data: Transaction, /// The transaction ID. pub txid: Txid, @@ -116,7 +117,8 @@ pub struct GetMiningInfo { pub network_hash_ps: f64, /// The size of the mempool. pub pooled_tx: i64, - /// Minimum feerate of packages selected for block inclusion. + /// Minimum feerate of packages selected for block inclusion (v30 onwards). + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub block_min_tx_fee: Option, /// Current network name as defined in BIP70 (main, test, regtest). pub chain: String, @@ -151,9 +153,11 @@ pub struct GetPrioritisedTransactions(pub BTreeMap #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct PrioritisedTransaction { /// Transaction fee delta in satoshis. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub fee_delta: Amount, /// Whether this transaction is currently in mempool. pub in_mempool: bool, /// Modified fee in satoshis. Only returned if in_mempool=true. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub modified_fee: Option, } diff --git a/types/src/model/mod.rs b/types/src/model/mod.rs index d078e64b6..07ea521a9 100644 --- a/types/src/model/mod.rs +++ b/types/src/model/mod.rs @@ -20,7 +20,7 @@ mod wallet; mod zmq; use bitcoin::address::NetworkUnchecked; -use bitcoin::{Address, ScriptBuf}; +use bitcoin::{Address, ScriptPubKeyBuf}; use serde::{Deserialize, Serialize}; #[doc(inline)] @@ -87,7 +87,7 @@ pub use self::{ #[cfg_attr(feature = "serde-deny-unknown-fields", serde(deny_unknown_fields))] pub struct ScriptPubKey { /// The script_pubkey parsed from hex. - pub script_pubkey: ScriptBuf, + pub script_pubkey: ScriptPubKeyBuf, /// Number of required signatures - deprecated in Core v22. /// /// Only returned in versions prior to 22 or for version 22 onwards if diff --git a/types/src/model/network.rs b/types/src/model/network.rs index d00ada8ae..4d9a45759 100644 --- a/types/src/model/network.rs +++ b/types/src/model/network.rs @@ -36,9 +36,11 @@ pub struct GetNetworkInfo { /// Information per network. pub networks: Vec, /// Minimum relay fee rate for transactions. - pub relay_fee: Option, // `Some` if parsing succeeds. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor")] + pub relay_fee: FeeRate, /// Minimum fee rate increment for mempool limiting or replacement. - pub incremental_fee: Option, // `Some` if parsing succeeds. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor")] + pub incremental_fee: FeeRate, /// List of local addresses. pub local_addresses: Vec, /// Any network and blockchain warnings. diff --git a/types/src/model/raw_transactions.rs b/types/src/model/raw_transactions.rs index 69466998e..cb626ffb4 100644 --- a/types/src/model/raw_transactions.rs +++ b/types/src/model/raw_transactions.rs @@ -9,7 +9,10 @@ use alloc::collections::BTreeMap; use bitcoin::address::{Address, NetworkUnchecked}; use bitcoin::hashes::{hash160, sha256}; -use bitcoin::{Amount, BlockHash, FeeRate, Psbt, ScriptBuf, Sequence, Transaction, Txid, Wtxid}; +use bitcoin::{ + Amount, BlockHash, FeeRate, Psbt, ScriptPubKeyBuf, ScriptSigBuf, Sequence, Transaction, Txid, + Wtxid, +}; use serde::{Deserialize, Serialize}; /// Models the result of JSON-RPC method `analyzepsbt`. @@ -22,8 +25,10 @@ pub struct AnalyzePsbt { /// Estimated feerate of the final signed transaction in BTC/kB. /// /// Shown only if all UTXO slots in the PSBT have been filled. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub estimated_fee_rate: Option, /// The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub fee: Option, /// Role of the next person that this psbt needs to go to. pub next: String, @@ -61,7 +66,7 @@ pub struct CombinePsbt(pub Psbt); /// Models the result of JSON-RPC method `combinerawtransaction`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct CombineRawTransaction(pub Transaction); +pub struct CombineRawTransaction(#[serde(with = "bitcoin::as_consensus")] pub Transaction); /// Models the result of JSON-RPC method `converttopsbt`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -73,7 +78,7 @@ pub struct CreatePsbt(pub Psbt); /// Models the result of JSON-RPC method `createrawtransaction`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct CreateRawTransaction(pub Transaction); +pub struct CreateRawTransaction(#[serde(with = "bitcoin::as_consensus")] pub Transaction); /// Models the result of JSON-RPC method `decodepsbt`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -81,18 +86,19 @@ pub struct DecodePsbt { /// The decoded PSBT. pub psbt: Psbt, /// The transaction fee paid if all UTXOs slots in the PSBT have been filled. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub fee: Option, } /// Models the result of JSON-RPC method `decoderawtransaction`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct DecodeRawTransaction(pub Transaction); +pub struct DecodeRawTransaction(#[serde(with = "bitcoin::as_consensus")] pub Transaction); /// Models the result of JSON-RPC method `decodescript`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct DecodeScript { /// The `scriptPubKey`. - pub script_pubkey: Option, + pub script_pubkey: Option, /// Inferred descriptor for the script. v23 and later only. pub descriptor: Option, /// The output type. @@ -117,6 +123,7 @@ pub struct DescriptorProcessPsbt { /// If the transaction has a complete set of signatures. pub complete: bool, /// The transaction if complete. + #[serde(with = "bitcoin::as_consensus::opt")] pub tx: Option, } @@ -126,6 +133,7 @@ pub struct FinalizePsbt { /// The partially signed transaction if not extracted. pub psbt: Option, /// The transaction if extracted. + #[serde(with = "bitcoin::as_consensus::opt")] pub tx: Option, /// If the transaction has a complete set of signatures. pub complete: bool, @@ -135,8 +143,10 @@ pub struct FinalizePsbt { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct FundRawTransaction { /// The resulting raw transaction. + #[serde(with = "bitcoin::as_consensus")] pub tx: Transaction, /// Fee the resulting transaction pays. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub fee: Amount, /// The position of the added change output, or -1. pub change_position: i64, @@ -144,7 +154,7 @@ pub struct FundRawTransaction { /// Models the result of JSON-RPC method `getrawtransaction` with verbose set to `false`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct GetRawTransaction(pub Transaction); +pub struct GetRawTransaction(#[serde(with = "bitcoin::as_consensus")] pub Transaction); /// Models the result of JSON-RPC method `getrawtransaction` with verbose set to `true`. /// Result of JSON-RPC method `getrawtransaction` @@ -153,6 +163,7 @@ pub struct GetRawTransactionVerbose { /// Whether specified block is in the active chain or not (only present with explicit "blockhash" argument). pub in_active_chain: Option, /// The transaction (encapsulates the other data returned by original RPC call). + #[serde(with = "bitcoin::as_consensus")] pub transaction: Transaction, /// The block hash (`None` for mempool transactions). pub block_hash: Option, @@ -176,6 +187,7 @@ pub struct SendRawTransaction(pub Txid); #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct SignRawTransaction { /// The raw transaction with signature(s). + #[serde(with = "bitcoin::as_consensus")] pub tx: Transaction, /// If the transaction has a complete set of signatures. pub complete: bool, @@ -197,7 +209,7 @@ pub struct SignFail { /// The index of the output to spent and used as input. pub vout: u64, /// The signature script. - pub script_sig: ScriptBuf, + pub script_sig: ScriptSigBuf, /// Script sequence number. pub sequence: Sequence, /// Verification or signing error related to the input. @@ -236,11 +248,13 @@ pub struct SubmitPackageTxResult { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct SubmitPackageTxResultFees { /// Transaction fee. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub base_fee: Amount, /// The effective feerate. /// /// Will be `None` if the transaction was already in the mempool. For example, the package /// feerate and/or feerate with modified fees from the `prioritisetransaction` JSON-RPC method. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub effective_fee_rate: Option, /// If [`Self::effective_fee_rate`] is provided, this holds the [`Wtxid`]s of the transactions /// whose fees and vsizes are included in effective-feerate. @@ -277,9 +291,11 @@ pub struct MempoolAcceptance { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct MempoolAcceptanceFees { /// Transaction fee in BTC. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub base: Amount, /// The effective feerate in BTC per KvB. May differ from the base feerate if, for example, there /// are modified fees from `prioritisetransaction` or a package feerate was used. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub effective_feerate: Option, /// Transactions whose fees and vsizes are included in `effective_feerate`. pub effective_includes: Option>, diff --git a/types/src/model/util.rs b/types/src/model/util.rs index 546130a2d..82593d959 100644 --- a/types/src/model/util.rs +++ b/types/src/model/util.rs @@ -6,7 +6,10 @@ //! and are not specific to a specific version of Bitcoin Core. use bitcoin::address::NetworkUnchecked; -use bitcoin::{sign_message, Address, FeeRate, ScriptBuf, WitnessProgram, WitnessVersion}; +use bitcoin::{ + sign_message, Address, FeeRate, RedeemScriptBuf, ScriptPubKeyBuf, WitnessProgram, + WitnessVersion, +}; use serde::{Deserialize, Serialize}; /// Models the result of JSON-RPC method `createmultisig`. @@ -15,7 +18,7 @@ pub struct CreateMultisig { /// The value of the new multisig address. pub address: Address, /// The string value of the hex-encoded redemption script. - pub redeem_script: ScriptBuf, + pub redeem_script: RedeemScriptBuf, /// The descriptor for this multisig. v0.20 and later only. pub descriptor: Option, /// Any warnings resulting from the creation of this multisig. v23 and later only. @@ -45,6 +48,7 @@ pub struct DeriveAddressesMultipath { #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct EstimateSmartFee { /// Estimate fee rate in BTC/kB. + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor::opt")] pub fee_rate: Option, /// Errors encountered during processing. pub errors: Option>, @@ -66,7 +70,7 @@ pub struct ValidateAddress { /// The bitcoin address validated. pub address: Address, /// The hex encoded scriptPubKey generated by the address. - pub script_pubkey: ScriptBuf, + pub script_pubkey: ScriptPubKeyBuf, /// If the key is a script. pub is_script: bool, /// If the address is a witness address. diff --git a/types/src/model/wallet.rs b/types/src/model/wallet.rs index 2b0f46b72..042b92cd1 100644 --- a/types/src/model/wallet.rs +++ b/types/src/model/wallet.rs @@ -12,7 +12,8 @@ use bitcoin::bip32::{Xpriv, Xpub}; use bitcoin::hashes::hash160; use bitcoin::{ bip32, sign_message, Address, Amount, BlockHash, FeeRate, PrivateKey, Psbt, PublicKey, - ScriptBuf, SignedAmount, Transaction, Txid, WitnessProgram, WitnessVersion, + RedeemScriptBuf, ScriptPubKeyBuf, SignedAmount, Transaction, Txid, WitnessProgram, + WitnessVersion, }; use serde::{Deserialize, Serialize}; @@ -60,7 +61,7 @@ pub struct AddMultisigAddress { /// The new multisig address. pub address: Address, /// The redemption script. - pub redeem_script: ScriptBuf, + pub redeem_script: RedeemScriptBuf, /// The descriptor for this multisig. pub descriptor: Option, /// Any warnings resulting from the creation of this multisig. @@ -73,8 +74,10 @@ pub struct BumpFee { /// The id of the new transaction. pub txid: Txid, /// Fee of the replaced transaction. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub original_fee: Amount, /// Fee of the new transaction. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub fee: Amount, /// Errors encountered during processing (may be empty). pub errors: Vec, @@ -114,7 +117,7 @@ pub struct GetAddressInfo { /// The bitcoin address validated. pub address: Address, /// The hex encoded scriptPubKey generated by the address. - pub script_pubkey: ScriptBuf, + pub script_pubkey: ScriptPubKeyBuf, /// If the address is yours or not. pub is_mine: bool, /// If the address is watchonly. @@ -141,7 +144,7 @@ pub struct GetAddressInfo { pub script: Option, /// The redeemscript for the p2sh address. // TODO: Should we rename this to redeem_script? - pub hex: Option, + pub hex: Option, /// Array of pubkeys associated with the known redeemscript (only if "script" is "multisig"). pub pubkeys: Option>, /// Number of signatures required to spend multisig output (only if "script" is "multisig"). @@ -201,7 +204,7 @@ pub struct GetAddressInfoEmbedded { /// The bitcoin address validated. pub address: Address, /// The hex encoded scriptPubKey generated by the address. - pub script_pubkey: ScriptBuf, + pub script_pubkey: ScriptPubKeyBuf, /// Whether we know how to spend coins sent to this address, ignoring the possible lack of private keys. pub solvable: Option, /// A descriptor for spending coins sent to this address (only when solvable). @@ -223,7 +226,7 @@ pub struct GetAddressInfoEmbedded { /// Only if "is_script" is true and the redeemscript is known. pub script: Option, /// The redeemscript for the p2sh address. - pub hex: Option, + pub hex: Option, /// Array of pubkeys associated with the known redeemscript (only if "script" is "multisig"). pub pubkeys: Option>, /// Number of signatures required to spend multisig output (only if "script" is "multisig"). @@ -240,7 +243,7 @@ pub struct GetAddressInfoEmbedded { /// Models the result of JSON-RPC method `getbalance`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct GetBalance(pub Amount); +pub struct GetBalance(#[serde(with = "bitcoin::amount::serde::as_sat")] pub Amount); /// Models the result of JSON-RPC method `getbalances`. /// @@ -260,14 +263,18 @@ pub struct GetBalances { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetBalancesMine { /// Trusted balance (outputs created by the wallet or confirmed outputs). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub trusted: Amount, /// Untrusted pending balance (outputs created by others that are in the mempool). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub untrusted_pending: Amount, /// Balance from immature coinbase outputs. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub immature: Amount, /// Balance from coins sent to addresses that were previously spent from (potentially privacy violating). /// /// Only present if `avoid_reuse` is set. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub used: Option, } @@ -275,10 +282,13 @@ pub struct GetBalancesMine { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetBalancesWatchOnly { /// Trusted balance (outputs created by the wallet or confirmed outputs). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub trusted: Amount, /// Untrusted pending balance (outputs created by others that are in the mempool). + #[serde(with = "bitcoin::amount::serde::as_sat")] pub untrusted_pending: Amount, /// Balance from immature coinbase outputs. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub immature: Amount, } @@ -318,11 +328,11 @@ pub struct GetRawChangeAddress(pub Address); /// Models the result of JSON-RPC method `getreceivedbyaddress`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct GetReceivedByAddress(pub Amount); +pub struct GetReceivedByAddress(#[serde(with = "bitcoin::amount::serde::as_sat")] pub Amount); /// Models the result of JSON-RPC method `getreceivedbylabel`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct GetReceivedByLabel(pub Amount); +pub struct GetReceivedByLabel(#[serde(with = "bitcoin::amount::serde::as_sat")] pub Amount); /// Models the result of JSON-RPC method `gettransaction`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -377,10 +387,12 @@ pub struct GetTransaction { /// Transaction details. pub details: Vec, /// The decoded transaction (only present when `verbose` is passed). v19 and later only. + #[serde(with = "bitcoin::as_consensus::opt")] pub decoded: Option, /// Hash and height of the block this information was generated on. v26 and later only. pub last_processed_block: Option, /// The transaction, parsed from hex string. + #[serde(with = "bitcoin::as_consensus")] pub tx: Transaction, } @@ -427,7 +439,7 @@ pub struct LastProcessedBlock { /// Models the result of JSON-RPC method `getunconfirmedbalance`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -pub struct GetUnconfirmedBalance(pub Amount); +pub struct GetUnconfirmedBalance(#[serde(with = "bitcoin::amount::serde::as_sat")] pub Amount); /// Models the result of JSON-RPC method `getwalletinfo`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] @@ -439,10 +451,13 @@ pub struct GetWalletInfo { /// Database format. v21 and later only. pub format: Option, /// The total confirmed balance of the wallet in BTC. v17 to v29 only. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub balance: Option, /// The total unconfirmed balance of the wallet in BTC. v17 to v29 only. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub unconfirmed_balance: Option, /// The total immature balance of the wallet in BTC. v17 to v29 only. + #[serde(with = "bitcoin::amount::serde::as_sat::opt")] pub immature_balance: Option, /// The total number of transactions in the wallet. pub tx_count: u32, @@ -458,7 +473,8 @@ pub struct GetWalletInfo { /// for transfers, or 0 if the wallet is locked. pub unlocked_until: Option, /// The transaction fee configuration. - pub pay_tx_fee: Option, + #[serde(with = "bitcoin::fee_rate::serde::as_sat_per_vb_floor")] + pub pay_tx_fee: FeeRate, /// The Hash160 of the HD seed (only present when HD is enabled). pub hd_seed_id: Option, /// If privatekeys are disabled for this wallet (enforced watch-only wallet). @@ -505,6 +521,7 @@ pub struct ListAddressGroupingsItem { /// The bitcoin address. pub address: Address, /// The amount. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// The label. pub label: Option, @@ -535,6 +552,7 @@ pub struct ListReceivedByAddressItem { /// The receiving address. pub address: Address, /// The total amount received by the address. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// The number of confirmations of the most recent transaction included. pub confirmations: i64, // Docs do not indicate what negative value means? @@ -554,6 +572,7 @@ pub struct ListReceivedByLabelItem { /// Only returned if imported addresses were involved in transaction. pub involves_watch_only: Option, /// The total amount received by addresses with this label. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// The number of confirmations of the most recent transaction included. pub confirmations: u32, @@ -680,13 +699,14 @@ pub struct ListUnspentItem { /// The associated label, or "" for the default label. pub label: String, /// The script key. - pub script_pubkey: ScriptBuf, + pub script_pubkey: ScriptPubKeyBuf, /// The transaction amount. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub amount: Amount, /// The number of confirmations. pub confirmations: u32, // Docs do not indicate what negative value means? /// The redeemScript if scriptPubKey is P2SH. - pub redeem_script: Option, + pub redeem_script: Option, /// Whether we have the private keys to spend this output. pub spendable: bool, /// Whether we know how to spend this output, ignoring the lack of keys. @@ -721,8 +741,10 @@ pub struct PsbtBumpFee { /// The base64-encoded unsigned PSBT of the new transaction. pub psbt: Psbt, /// The fee of the replaced transaction. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub original_fee: Amount, /// The fee of the new transaction. + #[serde(with = "bitcoin::amount::serde::as_sat")] pub fee: Amount, /// Errors encountered during processing (may be empty). pub errors: Vec, @@ -745,6 +767,7 @@ pub struct Send { /// The transaction id for the send. pub txid: Option, /// If add_to_wallet is false, the hex-encoded raw transaction with signature(s). + #[serde(with = "bitcoin::as_consensus::opt")] pub hex: Option, /// If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) /// signed transaction. @@ -759,6 +782,7 @@ pub struct SendAll { /// The transaction id for the send. Only 1 transaction is created regardless of the number of addresses. pub txid: Option, /// If add_to_wallet is false, the hex-encoded raw transaction with signature(s). + #[serde(with = "bitcoin::as_consensus::opt")] pub hex: Option, /// If more signatures are needed, or if add_to_wallet is false, the base64-encoded (partially) /// signed transaction. @@ -839,5 +863,6 @@ pub struct WalletProcessPsbt { /// If the transaction has a complete set of signatures. pub complete: bool, /// The hex-encoded network transaction if complete. + #[serde(with = "bitcoin::as_consensus::opt")] pub hex: Option, } diff --git a/types/src/psbt/error.rs b/types/src/psbt/error.rs index eed6eae3f..31ac182aa 100644 --- a/types/src/psbt/error.rs +++ b/types/src/psbt/error.rs @@ -41,7 +41,7 @@ impl std::error::Error for RawTransactionError { #[derive(Debug)] pub enum RawTransactionInputError { /// Conversion of the input `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Input lacked both `txid` and `coinbase` data. MissingTxid, /// Input lacked the `vout` field for a non-coinbase input. @@ -49,9 +49,9 @@ pub enum RawTransactionInputError { /// Input lacked both `scriptSig` and `coinbase` data. MissingScriptSig, /// Conversion of the input `script_sig` field failed. - ScriptSig(hex::HexToBytesError), + ScriptSig(hex::DecodeVariableLengthBytesError), /// Conversion of one of the `witness` hex strings failed. - Witness(hex::HexToBytesError), + Witness(hex::DecodeVariableLengthBytesError), } impl fmt::Display for RawTransactionInputError { @@ -92,7 +92,7 @@ pub enum RawTransactionOutputError { /// Conversion of the output `value` field failed. Value(amount::ParseAmountError), /// Conversion of the output `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), } impl fmt::Display for RawTransactionOutputError { @@ -121,7 +121,7 @@ pub enum WitnessUtxoError { /// Conversion of the `amount` field failed. Amount(ParseAmountError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), } impl fmt::Display for WitnessUtxoError { @@ -150,7 +150,7 @@ pub enum PartialSignatureError { /// Error parsing public key. PublicKey(key::ParsePublicKeyError), /// Error parsing signature. - Signature(ecdsa::Error), + Signature(ecdsa::ParseSignatureError), } impl fmt::Display for PartialSignatureError { @@ -180,9 +180,9 @@ pub enum Bip32DerivError { /// Conversion of the pubkey failed. PubKey(key::ParsePublicKeyError), /// Conversion of the `master_fingerprint` field failed. - MasterFingerprint(hex::HexToArrayError), + MasterFingerprint(hex::DecodeFixedLengthBytesError), /// Conversion of the `path` field failed. - Path(bip32::Error), + Path(bip32::ParseChildNumberError), } impl fmt::Display for Bip32DerivError { diff --git a/types/src/psbt/mod.rs b/types/src/psbt/mod.rs index a19a29745..e3211e62c 100644 --- a/types/src/psbt/mod.rs +++ b/types/src/psbt/mod.rs @@ -4,10 +4,10 @@ mod error; use std::collections::{BTreeMap, HashMap}; -use bitcoin::hex::{self, FromHex as _}; +use bitcoin::script::{ScriptBuf, Tag}; use bitcoin::{ - absolute, bip32, ecdsa, psbt, secp256k1, transaction, Amount, OutPoint, PublicKey, ScriptBuf, - Sequence, Transaction, TxIn, TxOut, Txid, Witness, + absolute, bip32, ecdsa, hex, psbt, secp256k1, transaction, Amount, OutPoint, PublicKey, + ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, }; use serde::{Deserialize, Serialize}; @@ -35,7 +35,7 @@ pub struct RawTransaction { /// The transaction's weight (between vsize*4 - 3 and vsize*4). pub weight: u64, /// The version number. - pub version: i32, + pub version: u32, /// The lock time. #[serde(rename = "locktime")] pub lock_time: u32, @@ -52,22 +52,22 @@ impl RawTransaction { pub fn to_transaction(&self) -> Result { use RawTransactionError as E; - let version = transaction::Version::non_standard(self.version); + let version = transaction::Version::maybe_non_standard(self.version); let lock_time = absolute::LockTime::from_consensus(self.lock_time); - let input = self + let inputs = self .inputs .iter() .map(|input| input.to_input()) .collect::>() .map_err(E::Inputs)?; - let output = self + let outputs = self .outputs .iter() .map(|output| output.to_output()) .collect::>() .map_err(E::Outputs)?; - Ok(Transaction { version, lock_time, input, output }) + Ok(Transaction { version, lock_time, inputs, outputs }) } } @@ -109,7 +109,7 @@ impl RawTransactionInput { let vout = self.vout.ok_or(RawTransactionInputError::MissingVout)?; OutPoint { txid: parsed_txid, vout } } - (None, Some(_)) => OutPoint::null(), + (None, Some(_)) => OutPoint::COINBASE_PREVOUT, (None, None) => return Err(E::MissingTxid), }; @@ -117,7 +117,8 @@ impl RawTransactionInput { // if coinbase transaction, parse coinbase as scriptSig let script_sig = match (&self.script_sig, &self.coinbase) { (Some(script_sig), _) => script_sig.script_buf().map_err(E::ScriptSig)?, - (None, Some(coinbase)) => ScriptBuf::from_hex(coinbase).map_err(E::ScriptSig)?, + (None, Some(coinbase)) => + ScriptSigBuf::from_hex_no_length_prefix(coinbase).map_err(E::ScriptSig)?, (None, None) => return Err(E::MissingScriptSig), }; @@ -155,10 +156,10 @@ impl RawTransactionOutput { pub fn to_output(&self) -> Result { use RawTransactionOutputError as E; - let value = Amount::from_btc(self.value).map_err(E::Value)?; + let amount = Amount::from_btc(self.value).map_err(E::Value)?; let script_pubkey = self.script_pubkey.script_buf().map_err(E::ScriptPubKey)?; - Ok(TxOut { value, script_pubkey }) + Ok(TxOut { amount, script_pubkey }) } } @@ -179,10 +180,10 @@ impl WitnessUtxo { pub fn to_tx_out(&self) -> Result { use WitnessUtxoError as E; - let value = Amount::from_btc(self.amount).map_err(E::Amount)?; + let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; let script_pubkey = self.script_pubkey.script_buf().map_err(E::ScriptPubKey)?; - Ok(TxOut { value, script_pubkey }) + Ok(TxOut { amount, script_pubkey }) } } @@ -201,8 +202,8 @@ pub struct PsbtScript { impl PsbtScript { /// Parses the hex into a `ScriptBuf`. - pub fn script_buf(&self) -> Result { - ScriptBuf::from_hex(&self.hex) + pub fn script_buf(&self) -> Result, hex::DecodeVariableLengthBytesError> { + ScriptBuf::from_hex_no_length_prefix(&self.hex) } } @@ -248,24 +249,20 @@ pub struct FinalScript { /// Converts a map of unknown key-value pairs. pub fn into_unknown( hash_map: HashMap, -) -> Result>, hex::HexToBytesError> { +) -> Result>, hex::DecodeVariableLengthBytesError> { let mut map = BTreeMap::default(); for (k, v) in hash_map.iter() { // FIXME: This is best guess, I (Tobin) don't actually know what // is in the hex string returned by Core. - let key = Vec::from_hex(k)?; - let value = Vec::from_hex(v)?; + let key_data = bitcoin::hex::decode_to_vec(k)?; + let value = bitcoin::hex::decode_to_vec(v)?; // rust-bitcoin separates out the key type. - let mut p = key.as_slice(); + let mut p = key_data.as_slice(); let _ = crate::compact_size_decode(&mut p); // Moves p past the keylen integer. let type_value = crate::compact_size_decode(&mut p); - // In the next release of rust-bitcoin this is changed to a u64. - // Yes this looses data - c'est la vie. - let type_value: u8 = type_value as u8; - - let key = psbt::raw::Key { type_value, key }; + let key = psbt::raw::Key { type_value, key_data }; map.insert(key, value); } Ok(map) @@ -300,7 +297,7 @@ pub fn map_into_bip32_derivation( Fingerprint::from_hex(&v.master_fingerprint).map_err(E::MasterFingerprint)?; let path = v.path.parse::().map_err(E::Path)?; - map.insert(pubkey.inner, (fingerprint, path)); + map.insert(pubkey.to_inner(), (fingerprint, path)); } Ok(map) } @@ -319,7 +316,7 @@ pub fn vec_into_bip32_derivation( Fingerprint::from_hex(&deriv.master_fingerprint).map_err(E::MasterFingerprint)?; let path = deriv.path.parse::().map_err(E::Path)?; - map.insert(pubkey.inner, (fingerprint, path)); + map.insert(pubkey.to_inner(), (fingerprint, path)); } Ok(map) } diff --git a/types/src/v17/blockchain/error.rs b/types/src/v17/blockchain/error.rs index 1d72a8d05..1e3b48c9a 100644 --- a/types/src/v17/blockchain/error.rs +++ b/types/src/v17/blockchain/error.rs @@ -4,7 +4,7 @@ use core::fmt; use bitcoin::amount::{self, ParseAmountError}; use bitcoin::consensus::encode; -use bitcoin::error::UnprefixedHexError; +use bitcoin::parse_int::UnprefixedHexError; use bitcoin::{address, hex, network}; use crate::error::write_err; @@ -16,9 +16,9 @@ pub enum GetBlockVerboseOneError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `merkle_root` field failed. - MerkleRoot(hex::HexToArrayError), + MerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `hex` field failed. Tx(encode::FromHexError), /// Conversion of the transaction `bits` field failed. @@ -26,9 +26,9 @@ pub enum GetBlockVerboseOneError { /// Conversion of the transaction `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of the transaction `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `next_block_hash` field failed. - NextBlockHash(hex::HexToArrayError), + NextBlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetBlockVerboseOneError { @@ -78,7 +78,7 @@ pub enum GetBlockchainInfoError { /// Conversion of the `chain` field failed. Chain(network::ParseNetworkError), /// Conversion of the `best_block_hash` field failed. - BestBlockHash(hex::HexToArrayError), + BestBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `chain_work` field failed. ChainWork(UnprefixedHexError), } @@ -116,9 +116,10 @@ impl From for GetBlockchainInfoError { #[derive(Debug)] pub enum GetBlockHeaderError { /// Conversion of hex data to bytes failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Consensus decoding of bytes to header failed. - Header(encode::Error), + // TODO: Shorten path once after: https://github.com/rust-bitcoin/rust-bitcoin/pull/5709 + Header(encoding::DecodeError), } impl fmt::Display for GetBlockHeaderError { @@ -146,17 +147,17 @@ pub enum GetBlockHeaderVerboseError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of `merkle_root` field failed. - MerkleRoot(hex::HexToArrayError), + MerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of `bits` field failed. Bits(UnprefixedHexError), /// Conversion of `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of `next_block_hash` field failed. - NextBlockHash(hex::HexToArrayError), + NextBlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetBlockHeaderVerboseError { @@ -202,7 +203,7 @@ pub enum GetBlockStatsError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetBlockStatsError { @@ -235,7 +236,7 @@ pub enum ChainTipsError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ChainTipsError { @@ -267,7 +268,7 @@ pub enum GetChainTxStatsError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `window_final_block_hash` field failed. - WindowFinalBlockHash(hex::HexToArrayError), + WindowFinalBlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetChainTxStatsError { @@ -298,7 +299,7 @@ impl From for GetChainTxStatsError { #[derive(Debug)] pub enum MapMempoolEntryError { /// Conversion of a `txid` failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of a `MempoolEntry` value inside a map failed. MempoolEntry(MempoolEntryError), } @@ -328,13 +329,13 @@ pub enum MempoolEntryError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `MempoolEntryFees` type failed. Fees(MempoolEntryFeesError), /// Conversion of the `depends` field failed. - Depends(hex::HexToArrayError), + Depends(hex::DecodeFixedLengthBytesError), /// Conversion of the `spent_by` field failed. - SpentBy(hex::HexToArrayError), + SpentBy(hex::DecodeFixedLengthBytesError), } impl From for MempoolEntryError { @@ -448,11 +449,11 @@ pub enum GetTxOutError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `best_block` field failed. - BestBlock(hex::HexToArrayError), + BestBlock(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `value` field failed. Value(amount::ParseAmountError), /// Conversion of the `ScriptPubKey` hex to a `ScriptBuf` failed. - ScriptBuf(hex::HexToBytesError), + ScriptBuf(hex::DecodeVariableLengthBytesError), /// Conversion of the `ScriptPubKey` `address` field failed. Address(address::ParseError), } @@ -495,7 +496,7 @@ pub enum GetTxOutSetInfoError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `best_block` field failed. - BestBlock(hex::HexToArrayError), + BestBlock(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `total_amount` field failed. TotalAmount(amount::ParseAmountError), } @@ -531,13 +532,13 @@ impl From for GetTxOutSetInfoError { #[derive(Debug)] pub enum ScanTxOutSetError { /// Conversion of the `best_block` field failed. - BestBlockHash(hex::HexToArrayError), + BestBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), /// Conversion of the `total_amount` field failed. TotalAmount(amount::ParseAmountError), /// Conversion of the `amount` field failed. diff --git a/types/src/v17/blockchain/into.rs b/types/src/v17/blockchain/into.rs index a51512154..92a779700 100644 --- a/types/src/v17/blockchain/into.rs +++ b/types/src/v17/blockchain/into.rs @@ -1,10 +1,9 @@ // SPDX-License-Identifier: CC0-1.0 use bitcoin::consensus::encode; -use bitcoin::hex::FromHex; use bitcoin::{ - block, hex, Amount, Block, BlockHash, CompactTarget, FeeRate, Network, ScriptBuf, TxMerkleNode, - TxOut, Txid, Weight, Work, Wtxid, + block, hex, Amount, Block, BlockHash, CompactTarget, FeeRate, Network, ScriptPubKeyBuf, + TxMerkleNode, TxOut, Txid, Weight, Work, Wtxid, }; // TODO: Use explicit imports? @@ -12,13 +11,15 @@ use super::*; impl GetBestBlockHash { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let hash = self.0.parse::()?; Ok(model::GetBestBlockHash(hash)) } /// Converts json straight to a `bitcoin::BlockHash`. - pub fn block_hash(self) -> Result { Ok(self.into_model()?.0) } + pub fn block_hash(self) -> Result { + Ok(self.into_model()?.0) + } } impl GetBlockVerboseZero { @@ -148,13 +149,15 @@ impl GetBlockCount { impl GetBlockHash { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let hash = self.0.parse::()?; Ok(model::GetBlockHash(hash)) } /// Converts json straight to a `bitcoin::BlockHash`. - pub fn block_hash(self) -> Result { Ok(self.into_model()?.0) } + pub fn block_hash(self) -> Result { + Ok(self.into_model()?.0) + } } impl GetBlockHeader { @@ -162,8 +165,8 @@ impl GetBlockHeader { pub fn into_model(self) -> Result { use GetBlockHeaderError as E; - let v = Vec::from_hex(&self.0).map_err(E::Hex)?; - let header = encode::deserialize::(&v).map_err(E::Header)?; + let v = bitcoin::hex::decode_to_vec(&self.0).map_err(E::Hex)?; + let header = encoding::decode_from_slice::(&v).map_err(E::Header)?; Ok(model::GetBlockHeader(header)) } @@ -213,7 +216,7 @@ impl GetBlockHeaderVerbose { } /// Converts json straight to a `bitcoin::BlockHeader`. - pub fn block_header(self) -> Result { todo!() } + pub fn block_header(self) -> Result { todo!() } } impl GetBlockStats { @@ -228,7 +231,7 @@ impl GetBlockStats { .fee_rate_percentiles .iter() .map(|vb| FeeRate::from_sat_per_vb(*vb)) - .collect::>>(); + .collect::>(); let max_fee_rate = FeeRate::from_sat_per_vb(self.max_fee_rate); let minimum_fee_rate = FeeRate::from_sat_per_vb(self.minimum_fee_rate); @@ -237,32 +240,32 @@ impl GetBlockStats { let total_weight = Weight::from_vb(self.total_weight); Ok(model::GetBlockStats { - average_fee: Amount::from_sat(self.average_fee), - average_fee_rate, + average_fee: Amount::from_sat(self.average_fee).expect("TODO: Handle this error"), + average_fee_rate: average_fee_rate, average_tx_size: crate::to_u32(self.average_tx_size, "average_tx_size")?, block_hash, fee_rate_percentiles, height: crate::to_u32(self.height, "height")?, inputs: crate::to_u32(self.inputs, "inputs")?, - max_fee: Amount::from_sat(self.max_fee), + max_fee: Amount::from_sat(self.max_fee).expect("TODO: Handle this error"), max_fee_rate, max_tx_size: crate::to_u32(self.max_tx_size, "max_tx_size")?, - median_fee: Amount::from_sat(self.median_fee), + median_fee: Amount::from_sat(self.median_fee).expect("TODO: Handle this error"), median_time: crate::to_u32(self.median_time, "median_time")?, median_tx_size: crate::to_u32(self.median_tx_size, "median_tx_size")?, - minimum_fee: Amount::from_sat(self.minimum_fee), + minimum_fee: Amount::from_sat(self.minimum_fee).expect("TODO: Handle this error"), minimum_fee_rate, minimum_tx_size: crate::to_u32(self.minimum_tx_size, "minimum_tx_size")?, outputs: crate::to_u32(self.outputs, "outputs")?, - subsidy: Amount::from_sat(self.subsidy), + subsidy: Amount::from_sat(self.subsidy).expect("TODO: Handle this error"), segwit_total_size: crate::to_u32(self.segwit_total_size, "segwit_total_size")?, segwit_total_weight, segwit_txs: crate::to_u32(self.segwit_txs, "segwit_txs")?, time: crate::to_u32(self.time, "time")?, - total_out: Amount::from_sat(self.total_out), + total_out: Amount::from_sat(self.total_out).expect("TODO: Handle this error"), total_size: crate::to_u32(self.total_size, "total_size")?, total_weight, - total_fee: Amount::from_sat(self.total_fee), + total_fee: Amount::from_sat(self.total_fee).expect("TODO: Handle this error"), txs: crate::to_u32(self.txs, "txs")?, utxo_increase: self.utxo_increase, utxo_size_increase: self.utxo_size_increase, @@ -341,7 +344,9 @@ impl GetDifficulty { impl GetMempoolAncestors { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolAncestors(v)) } @@ -364,7 +369,9 @@ impl GetMempoolAncestorsVerbose { impl GetMempoolDescendants { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolDescendants(v)) } @@ -484,7 +491,7 @@ impl GetMempoolInfo { impl GetRawMempool { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetRawMempool(v)) } @@ -512,7 +519,7 @@ impl GetTxOut { let best_block = self.best_block.parse::().map_err(E::BestBlock)?; let tx_out = TxOut { - value: Amount::from_btc(self.value).map_err(E::Value)?, + amount: Amount::from_btc(self.value).map_err(E::Value)?, script_pubkey: self.script_pubkey.script_buf().map_err(E::ScriptBuf)?, }; @@ -587,7 +594,8 @@ impl ScanTxOutSetUnspent { let txid = self.txid.parse::().map_err(E::Txid)?; let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; Ok(model::ScanTxOutSetUnspent { txid, @@ -605,7 +613,7 @@ impl ScanTxOutSetUnspent { impl VerifyTxOutProof { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let proofs = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::VerifyTxOutProof(proofs)) } diff --git a/types/src/v17/blockchain/mod.rs b/types/src/v17/blockchain/mod.rs index 5ae148d63..840c563eb 100644 --- a/types/src/v17/blockchain/mod.rs +++ b/types/src/v17/blockchain/mod.rs @@ -298,7 +298,7 @@ pub struct GetBlockStats { // FIXME: Remember these docs will become silently stale when unit changes in a later version of Core. /// Average feerate (in satoshis per virtual byte). #[serde(rename = "avgfeerate")] - pub average_fee_rate: u64, + pub average_fee_rate: u32, /// Average transaction size. #[serde(rename = "avgtxsize")] pub average_tx_size: i64, @@ -308,7 +308,7 @@ pub struct GetBlockStats { /// Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per /// virtual byte). #[serde(rename = "feerate_percentiles")] - pub fee_rate_percentiles: [u64; 5], + pub fee_rate_percentiles: [u32; 5], /// The height of the block. pub height: i64, /// The number of inputs (excluding coinbase). @@ -319,7 +319,7 @@ pub struct GetBlockStats { pub max_fee: u64, /// Maximum feerate (in satoshis per virtual byte). #[serde(rename = "maxfeerate")] - pub max_fee_rate: u64, + pub max_fee_rate: u32, /// Maximum transaction size. #[serde(rename = "maxtxsize")] pub max_tx_size: i64, @@ -337,7 +337,7 @@ pub struct GetBlockStats { pub minimum_fee: u64, /// Minimum feerate (in satoshis per virtual byte). #[serde(rename = "minfeerate")] - pub minimum_fee_rate: u64, + pub minimum_fee_rate: u32, /// Minimum transaction size. #[serde(rename = "mintxsize")] pub minimum_tx_size: i64, diff --git a/types/src/v17/generating.rs b/types/src/v17/generating.rs index 90c1c551f..a35a17b4c 100644 --- a/types/src/v17/generating.rs +++ b/types/src/v17/generating.rs @@ -26,7 +26,7 @@ pub struct Generate( impl Generate { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|s| s.parse::()).collect::, _>>()?; Ok(model::Generate(v)) } @@ -50,7 +50,7 @@ pub struct GenerateToAddress( impl GenerateToAddress { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|s| s.parse::()).collect::, _>>()?; Ok(model::GenerateToAddress(v)) } diff --git a/types/src/v17/hidden/error.rs b/types/src/v17/hidden/error.rs index 1ca8334e0..7ca9859fc 100644 --- a/types/src/v17/hidden/error.rs +++ b/types/src/v17/hidden/error.rs @@ -38,7 +38,7 @@ pub enum WaitForBlockError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for WaitForBlockError { @@ -70,7 +70,7 @@ pub enum WaitForBlockHeightError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for WaitForBlockHeightError { @@ -102,7 +102,7 @@ pub enum WaitForNewBlockError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for WaitForNewBlockError { diff --git a/types/src/v17/hidden/into.rs b/types/src/v17/hidden/into.rs index 8698edd71..c5af51d72 100644 --- a/types/src/v17/hidden/into.rs +++ b/types/src/v17/hidden/into.rs @@ -25,8 +25,7 @@ impl RawFeeDetail { pub fn into_model(self) -> Result { use EstimateRawFeeError as E; - let fee_rate = - self.fee_rate.map(crate::btc_per_kb).transpose().map_err(E::FeeRate)?.flatten(); + let fee_rate = self.fee_rate.map(crate::btc_per_kb).transpose().map_err(E::FeeRate)?; let pass = self.pass.map(|p| p.into_model()).transpose()?; let fail = self.fail.map(|p| p.into_model()).transpose()?; @@ -44,8 +43,8 @@ impl RawFeeDetail { impl RawFeeRange { /// Converts version specific type to a version nonspecific, more strongly typed type. pub fn into_model(self) -> Result { - let start_range = crate::btc_per_kb(self.start_range).ok().flatten(); - let end_range = crate::btc_per_kb(self.end_range).ok().flatten(); + let start_range = crate::btc_per_kb(self.start_range).ok(); + let end_range = crate::btc_per_kb(self.end_range).ok(); Ok(model::RawFeeRange { start_range, diff --git a/types/src/v17/mining/error.rs b/types/src/v17/mining/error.rs index 651fbb172..3b1cb4324 100644 --- a/types/src/v17/mining/error.rs +++ b/types/src/v17/mining/error.rs @@ -3,8 +3,8 @@ use core::fmt; use bitcoin::amount::ParseAmountError; -use bitcoin::error::UnprefixedHexError; -use bitcoin::hex::HexToBytesError; +use bitcoin::hex::DecodeVariableLengthBytesError; +use bitcoin::parse_int::UnprefixedHexError; use bitcoin::{consensus, hex}; use crate::error::write_err; @@ -16,11 +16,11 @@ pub enum GetBlockTemplateError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `transactions` field failed. Transactions(BlockTemplateTransactionError), /// Conversion of the `target` field failed. - Target(HexToBytesError), + Target(DecodeVariableLengthBytesError), /// Conversion of the `bits` field failed. Bits(UnprefixedHexError), } @@ -64,9 +64,9 @@ pub enum BlockTemplateTransactionError { /// Conversion of the `data` field failed. Data(consensus::encode::FromHexError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash` field to `wtxid` failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the `fee` field failed. Fee(ParseAmountError), } diff --git a/types/src/v17/mining/into.rs b/types/src/v17/mining/into.rs index d67eecb16..81bd2b12f 100644 --- a/types/src/v17/mining/into.rs +++ b/types/src/v17/mining/into.rs @@ -1,6 +1,5 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::hex::FromHex as _; use bitcoin::{ block, consensus, BlockHash, CompactTarget, SignedAmount, Transaction, Txid, Weight, Wtxid, }; @@ -27,8 +26,9 @@ impl GetBlockTemplate { .map(|t| t.into_model()) .collect::, _>>() .map_err(E::Transactions)?; - let coinbase_value = SignedAmount::from_sat(self.coinbase_value); - let target = Vec::from_hex(&self.target).map_err(E::Target)?; + let coinbase_value = + SignedAmount::from_sat(self.coinbase_value).expect("TODO: Handle this error"); + let target = bitcoin::hex::decode_to_vec(&self.target).map_err(E::Target)?; let sigop_limit = crate::to_u32(self.sigop_limit, "sigop_limit")?; let weight_limit = crate::to_u32(self.weight_limit, "weight_limit")?; let size_limit = crate::to_u32(self.size_limit, "size_limit")?; @@ -78,7 +78,7 @@ impl BlockTemplateTransaction { .iter() .map(|x| crate::to_u32(*x, "depend")) .collect::, _>>()?; - let fee = SignedAmount::from_sat(self.fee); + let fee = SignedAmount::from_sat(self.fee).expect("TODO: Handle this error"); let sigops = crate::to_u32(self.sigops, "sigops")?; let weight = Weight::from_wu(self.weight); // FIXME: Is this the correct unit? diff --git a/types/src/v17/raw_transactions/error.rs b/types/src/v17/raw_transactions/error.rs index fc40154c6..2ddd29f36 100644 --- a/types/src/v17/raw_transactions/error.rs +++ b/types/src/v17/raw_transactions/error.rs @@ -19,7 +19,7 @@ pub enum DecodePsbtError { /// Conversion of the `tx` field to `unsigned_tx` failed. Tx(RawTransactionError), /// Conversion of one the map items in the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), /// Conversion of one of the PSBT inputs failed. Inputs(PsbtInputError), /// Conversion of one of the PSBT outputs failed. @@ -68,17 +68,17 @@ pub enum PsbtInputError { /// Conversion of the `sighash` field failed. Sighash(sighash::SighashTypeParseError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `final_script_sig` field failed. - FinalScriptSig(hex::HexToBytesError), + FinalScriptSig(hex::DecodeVariableLengthBytesError), /// Conversion of the `final_script_witness` field failed. - FinalScriptWitness(hex::HexToBytesError), + FinalScriptWitness(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtInputError { @@ -128,13 +128,13 @@ impl std::error::Error for PsbtInputError { #[derive(Debug)] pub enum PsbtOutputError { /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtOutputError { @@ -167,7 +167,7 @@ impl std::error::Error for PsbtOutputError { #[derive(Debug)] pub enum DecodeScriptError { /// Conversion of the transaction `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the transaction `addresses` field failed. Addresses(address::ParseError), /// Conversion of the transaction `p2sh` field failed. @@ -260,7 +260,7 @@ pub enum GetRawTransactionVerboseError { /// Conversion of one of the transaction outputs failed. Outputs(RawTransactionOutputError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetRawTransactionVerboseError { @@ -319,9 +319,9 @@ impl std::error::Error for SignRawTransactionError { #[derive(Debug)] pub enum SignFailError { /// Conversion of the transaction `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `script_sig` field failed. - ScriptSig(hex::HexToBytesError), + ScriptSig(hex::DecodeVariableLengthBytesError), } impl fmt::Display for SignFailError { diff --git a/types/src/v17/raw_transactions/into.rs b/types/src/v17/raw_transactions/into.rs index f91f02643..a79f4f89c 100644 --- a/types/src/v17/raw_transactions/into.rs +++ b/types/src/v17/raw_transactions/into.rs @@ -4,8 +4,8 @@ use std::collections::BTreeMap; use bitcoin::psbt::{self, Psbt, PsbtParseError, PsbtSighashType}; use bitcoin::{ - absolute, consensus, hex, transaction, Address, Amount, BlockHash, ScriptBuf, Sequence, - Transaction, Txid, + absolute, consensus, hex, transaction, Address, Amount, BlockHash, ScriptPubKeyBuf, + ScriptSigBuf, Sequence, Transaction, Txid, }; use super::{ @@ -196,6 +196,9 @@ impl PsbtInput { let tap_internal_key = None; let tap_merkle_root = None; + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + Ok(psbt::Input { non_witness_utxo, witness_utxo, @@ -216,6 +219,7 @@ impl PsbtInput { tap_key_origins, tap_internal_key, tap_merkle_root, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -255,6 +259,9 @@ impl PsbtOutput { let tap_tree = None; let tap_key_origins = BTreeMap::default(); + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + Ok(psbt::Output { redeem_script, witness_script, @@ -262,6 +269,7 @@ impl PsbtOutput { tap_internal_key, tap_tree, tap_key_origins, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -288,7 +296,7 @@ impl DecodeScript { use DecodeScriptError as E; let script_pubkey = match self.hex { - Some(hex) => Some(ScriptBuf::from_hex(&hex).map_err(E::Hex)?), + Some(hex) => Some(ScriptPubKeyBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)?), None => None, }; let addresses = match self.addresses { @@ -368,23 +376,23 @@ impl GetRawTransactionVerbose { ) -> Result { use GetRawTransactionVerboseError as E; - let version = transaction::Version::non_standard(self.version); + let version = transaction::Version::maybe_non_standard(self.version); let lock_time = absolute::LockTime::from_consensus(self.lock_time); - let input = self + let inputs = self .inputs .into_iter() .map(|input| input.to_input()) .collect::>() .map_err(E::Inputs)?; - let output = self + let outputs = self .outputs .into_iter() .map(|output| output.to_output()) .collect::>() .map_err(E::Outputs)?; - let transaction = Transaction { version, lock_time, input, output }; + let transaction = Transaction { version, lock_time, inputs, outputs }; let block_hash = self.block_hash.map(|s| s.parse::()).transpose().map_err(E::BlockHash)?; @@ -401,13 +409,13 @@ impl GetRawTransactionVerbose { impl SendRawTransaction { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let txid = self.0.parse::()?; Ok(model::SendRawTransaction(txid)) } /// Converts json straight to a `bitcoin::Txid`. - pub fn txid(self) -> Result { + pub fn txid(self) -> Result { let model = self.into_model()?; Ok(model.0) } @@ -439,7 +447,8 @@ impl SignFail { use SignFailError as E; let txid = self.txid.parse::().map_err(E::Txid)?; - let script_sig = ScriptBuf::from_hex(&self.script_sig).map_err(E::ScriptSig)?; + let script_sig = + ScriptSigBuf::from_hex_no_length_prefix(&self.script_sig).map_err(E::ScriptSig)?; let sequence = Sequence::from_consensus(self.sequence); Ok(model::SignFail { txid, vout: self.vout, script_sig, sequence, error: self.error }) @@ -448,7 +457,7 @@ impl SignFail { impl TestMempoolAccept { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let results = self.0.into_iter().map(|r| r.into_model()).collect::>()?; Ok(model::TestMempoolAccept { results }) @@ -457,7 +466,7 @@ impl TestMempoolAccept { impl MempoolAcceptance { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let txid = self.txid.parse::()?; Ok(model::MempoolAcceptance { diff --git a/types/src/v17/raw_transactions/mod.rs b/types/src/v17/raw_transactions/mod.rs index 026e7a2ce..438370e74 100644 --- a/types/src/v17/raw_transactions/mod.rs +++ b/types/src/v17/raw_transactions/mod.rs @@ -354,7 +354,7 @@ pub struct GetRawTransactionVerbose { /// The transaction's weight (between vsize*4-3 and vsize*4). pub weight: u64, /// The version. - pub version: i32, + pub version: u32, /// The lock time. #[serde(rename = "locktime")] pub lock_time: u32, diff --git a/types/src/v17/util/error.rs b/types/src/v17/util/error.rs index 431d52ada..618a756ae 100644 --- a/types/src/v17/util/error.rs +++ b/types/src/v17/util/error.rs @@ -11,7 +11,7 @@ pub enum CreateMultisigError { /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), } impl fmt::Display for CreateMultisigError { @@ -40,13 +40,13 @@ pub enum ValidateAddressError { /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), /// The `witness_version` field's value was too big for a u8. WitnessVersionValue(i64), /// Conversion of the `witness_version` field failed. WitnessVersion(witness_version::TryFromError), /// Conversion of the `witness_program` field hex string to bytes failed. - WitnessProgramBytes(hex::HexToBytesError), + WitnessProgramBytes(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_program` field failed. WitnessProgram(witness_program::Error), } diff --git a/types/src/v17/util/into.rs b/types/src/v17/util/into.rs index 39db0cb36..1649d7a69 100644 --- a/types/src/v17/util/into.rs +++ b/types/src/v17/util/into.rs @@ -1,7 +1,8 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::hex::FromHex; -use bitcoin::{amount, sign_message, Address, ScriptBuf, WitnessProgram, WitnessVersion}; +use bitcoin::{ + amount, sign_message, Address, RedeemScriptBuf, ScriptPubKeyBuf, WitnessProgram, WitnessVersion, +}; use super::{ CreateMultisig, CreateMultisigError, EstimateSmartFee, SignMessageWithPrivKey, ValidateAddress, @@ -15,7 +16,8 @@ impl CreateMultisig { use CreateMultisigError as E; let address = self.address.parse::>().map_err(E::Address)?; - let redeem_script = ScriptBuf::from_hex(&self.redeem_script).map_err(E::RedeemScript)?; + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix(&self.redeem_script) + .map_err(E::RedeemScript)?; Ok(model::CreateMultisig { address, redeem_script, descriptor: None, warnings: None }) } @@ -23,8 +25,9 @@ impl CreateMultisig { impl EstimateSmartFee { pub fn into_model(self) -> Result { + // TODO: Be smarter Tobin, use combinators. let fee_rate = match self.fee_rate { - Some(f) => crate::btc_per_kb(f)?, + Some(f) => Some(crate::btc_per_kb(f)?), None => None, }; Ok(model::EstimateSmartFee { fee_rate, errors: self.errors, blocks: self.blocks }) @@ -48,7 +51,8 @@ impl ValidateAddress { use ValidateAddressError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -58,7 +62,7 @@ impl ValidateAddress { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; diff --git a/types/src/v17/wallet/error.rs b/types/src/v17/wallet/error.rs index ece135d2f..1407f5f4e 100644 --- a/types/src/v17/wallet/error.rs +++ b/types/src/v17/wallet/error.rs @@ -16,7 +16,7 @@ pub enum AddMultisigAddressError { /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), } impl fmt::Display for AddMultisigAddressError { @@ -43,7 +43,7 @@ impl std::error::Error for AddMultisigAddressError { #[derive(Debug)] pub enum BumpFeeError { /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `original_fee` field failed. OriginalFee(ParseAmountError), /// Conversion of the `fee` field failed. @@ -80,17 +80,17 @@ pub enum GetAddressInfoError { /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), /// The `witness_version` field's value was too big for a u8. WitnessVersionValue(i64), /// Conversion of the `witness_version` field failed. WitnessVersion(witness_version::TryFromError), /// Conversion of the `witness_program` field hex string to bytes failed. - WitnessProgramBytes(hex::HexToBytesError), + WitnessProgramBytes(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_program` field failed. WitnessProgram(witness_program::Error), /// Conversion of the `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the `pubkeys` field failed. PubKeys(key::ParsePublicKeyError), /// Conversion of the `pubkey` field failed. @@ -98,9 +98,9 @@ pub enum GetAddressInfoError { /// Conversion of the `embedded` field failed. Embedded(GetAddressInfoEmbeddedError), /// Conversion of the `hd_key_path` field failed. - HdKeyPath(bip32::Error), + HdKeyPath(bip32::ParseChildNumberError), /// Conversion of the `hd_seed_id` field failed. - HdSeedId(hex::HexToArrayError), + HdSeedId(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetAddressInfoError { @@ -162,17 +162,17 @@ pub enum GetAddressInfoEmbeddedError { /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), /// The `witness_version` field's value was too big for a u8. WitnessVersionValue(i64), /// Conversion of the `witness_version` field failed. WitnessVersion(witness_version::TryFromError), /// Conversion of the `witness_program` field hex string to bytes failed. - WitnessProgramBytes(hex::HexToBytesError), + WitnessProgramBytes(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_program` field failed. WitnessProgram(witness_program::Error), /// Conversion of the `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the `pubkeys` field failed. PubKeys(key::ParsePublicKeyError), /// Conversion of the `pubkey` field failed. @@ -232,11 +232,11 @@ pub enum GetTransactionError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `hex` field failed. Tx(encode::FromHexError), /// Conversion of the `details` field failed. @@ -326,7 +326,7 @@ pub enum GetWalletInfoError { /// Conversion of the `pay_tx_fee` field failed. PayTxFee(ParseAmountError), /// Conversion of the `hd_seed_id` field failed. - HdSeedId(hex::HexToArrayError), + HdSeedId(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetWalletInfoError { @@ -398,7 +398,7 @@ pub enum ListLockUnspentItemError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListLockUnspentItemError { @@ -432,7 +432,7 @@ pub enum ListReceivedByAddressError { /// Conversion of the `amount` field failed. Amount(ParseAmountError), /// Conversion of txid in the `txids` list (with index) failed. - Txids(usize, hex::HexToArrayError), + Txids(usize, hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListReceivedByAddressError { @@ -465,7 +465,7 @@ pub enum ListSinceBlockError { /// Conversion of item in `removed` list failed. Removed(TransactionItemError), /// Conversion of the `last_block` field failed. - LastBlock(hex::HexToArrayError), + LastBlock(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListSinceBlockError { @@ -503,9 +503,9 @@ pub enum TransactionItemError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TransactionItemError { @@ -546,15 +546,15 @@ pub enum ListUnspentItemError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), /// Conversion of the `amount` field failed. Amount(ParseAmountError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `fee` field failed. Fee(ParseAmountError), } diff --git a/types/src/v17/wallet/into.rs b/types/src/v17/wallet/into.rs index 6a7be1efa..19ab8a52d 100644 --- a/types/src/v17/wallet/into.rs +++ b/types/src/v17/wallet/into.rs @@ -4,12 +4,11 @@ use bitcoin::address::NetworkUnchecked; use bitcoin::amount::ParseAmountError; use bitcoin::consensus::encode; use bitcoin::hashes::hash160; -use bitcoin::hex::FromHex; use bitcoin::key::{self, PrivateKey, PublicKey}; use bitcoin::psbt::PsbtParseError; use bitcoin::{ - address, bip32, sign_message, Address, Amount, BlockHash, Psbt, ScriptBuf, SignedAmount, - Transaction, Txid, WitnessProgram, WitnessVersion, + address, bip32, sign_message, Address, Amount, BlockHash, Psbt, RedeemScriptBuf, + ScriptPubKeyBuf, SignedAmount, Transaction, Txid, WitnessProgram, WitnessVersion, }; // TODO: Use explicit imports? @@ -64,7 +63,8 @@ impl AddMultisigAddress { use AddMultisigAddressError as E; let address = self.address.parse::>().map_err(E::Address)?; - let redeem_script = ScriptBuf::from_hex(&self.redeem_script).map_err(E::RedeemScript)?; + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix(&self.redeem_script) + .map_err(E::RedeemScript)?; Ok(model::AddMultisigAddress { address, @@ -131,7 +131,8 @@ impl GetAddressInfo { use GetAddressInfoError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -141,7 +142,7 @@ impl GetAddressInfo { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -150,8 +151,10 @@ impl GetAddressInfo { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = self .pubkeys .map(|pubkeys| { @@ -232,7 +235,8 @@ impl GetAddressInfoEmbedded { use GetAddressInfoEmbeddedError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -242,7 +246,7 @@ impl GetAddressInfoEmbedded { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -251,8 +255,10 @@ impl GetAddressInfoEmbedded { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = None; let sigs_required = self.sigs_required.map(|s| crate::to_u32(s, "sigs_required")).transpose()?; @@ -592,7 +598,7 @@ impl TransactionItem { .fee .map(|f| SignedAmount::from_btc(f).map_err(E::Fee)) .transpose()? // optional historically - .unwrap_or_else(|| SignedAmount::from_sat(0)); + .unwrap_or_else(|| SignedAmount::from_sat(0).expect("TODO: Handle this error")); let block_hash = self.block_hash.parse::().map_err(E::BlockHash)?; let block_index = crate::to_u32(self.block_index, "block_index")?; let txid = self.txid.map(|s| s.parse::().map_err(E::Txid)).transpose()?; @@ -658,13 +664,14 @@ impl ListUnspentItem { let txid = self.txid.parse::().map_err(E::Txid)?; let vout = crate::to_u32(self.vout, "vout")?; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; let confirmations = crate::to_u32(self.confirmations, "confirmations")?; let redeem_script = self .redeem_script - .map(|hex| ScriptBuf::from_hex(&hex).map_err(E::RedeemScript)) + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::RedeemScript)) .transpose()?; Ok(model::ListUnspentItem { @@ -709,7 +716,7 @@ impl RescanBlockchain { impl SendMany { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let txid = self.0.parse::()?; Ok(model::SendMany(txid)) } @@ -717,7 +724,7 @@ impl SendMany { impl SendToAddress { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let txid = self.0.parse::()?; Ok(model::SendToAddress { txid }) } diff --git a/types/src/v17/wallet/mod.rs b/types/src/v17/wallet/mod.rs index 7dcebb3c7..6899c617d 100644 --- a/types/src/v17/wallet/mod.rs +++ b/types/src/v17/wallet/mod.rs @@ -932,7 +932,9 @@ pub struct SendToAddress(pub String); impl SendToAddress { /// Converts json straight to a `bitcoin::Txid`. - pub fn txid(self) -> Result { Ok(self.into_model()?.txid) } + pub fn txid(self) -> Result { + Ok(self.into_model()?.txid) + } } /// Result of JSON-RPC method `settxfee`. diff --git a/types/src/v18/blockchain/into.rs b/types/src/v18/blockchain/into.rs index 2f6e77ba4..990fcf6ec 100644 --- a/types/src/v18/blockchain/into.rs +++ b/types/src/v18/blockchain/into.rs @@ -2,7 +2,7 @@ use alloc::collections::BTreeMap; -use bitcoin::{hex, Amount, ScriptBuf, Txid, Wtxid}; +use bitcoin::{hex, Amount, ScriptPubKeyBuf, Txid, Wtxid}; use super::{ GetMempoolAncestors, GetMempoolAncestorsVerbose, GetMempoolDescendants, @@ -14,7 +14,9 @@ use crate::model; impl GetMempoolAncestors { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolAncestors(v)) } @@ -37,7 +39,9 @@ impl GetMempoolAncestorsVerbose { impl GetMempoolDescendants { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolDescendants(v)) } @@ -115,7 +119,7 @@ impl MempoolEntry { impl GetRawMempool { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetRawMempool(v)) } @@ -164,7 +168,8 @@ impl ScanTxOutSetUnspent { let txid = self.txid.parse::().map_err(E::Txid)?; let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; Ok(model::ScanTxOutSetUnspent { txid, diff --git a/types/src/v18/raw_transactions/error.rs b/types/src/v18/raw_transactions/error.rs index 0044c0716..8f7a0390e 100644 --- a/types/src/v18/raw_transactions/error.rs +++ b/types/src/v18/raw_transactions/error.rs @@ -44,13 +44,13 @@ impl std::error::Error for AnalyzePsbtError { #[derive(Debug)] pub enum AnalyzePsbtInputMissingError { /// Conversion of the `pubkeys` field failed. - PubKeys(hex::HexToArrayError), + PubKeys(hex::DecodeFixedLengthBytesError), /// Conversion of the `signatures` field failed. - Signatures(hex::HexToArrayError), + Signatures(hex::DecodeFixedLengthBytesError), /// Conversion of the `RedeemScript` field failed. - RedeemScript(hex::HexToArrayError), + RedeemScript(hex::DecodeFixedLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToArrayError), + WitnessScript(hex::DecodeFixedLengthBytesError), } impl fmt::Display for AnalyzePsbtInputMissingError { diff --git a/types/src/v18/raw_transactions/into.rs b/types/src/v18/raw_transactions/into.rs index 333b4f04e..ff27346bf 100644 --- a/types/src/v18/raw_transactions/into.rs +++ b/types/src/v18/raw_transactions/into.rs @@ -25,8 +25,7 @@ impl AnalyzePsbt { .estimated_fee_rate .map(crate::btc_per_kb) .transpose() - .map_err(E::EstimatedFeeRate)? - .flatten(); + .map_err(E::EstimatedFeeRate)?; let fee = self.fee.map(Amount::from_btc).transpose().map_err(E::Fee)?; Ok(model::AnalyzePsbt { diff --git a/types/src/v18/wallet/error.rs b/types/src/v18/wallet/error.rs index 52c8cc1ae..51185bd13 100644 --- a/types/src/v18/wallet/error.rs +++ b/types/src/v18/wallet/error.rs @@ -17,17 +17,17 @@ pub enum GetAddressInfoError { /// Conversion of the `address` field failed. Address(address::ParseError), /// Conversion of the `script_pubkey` field failed. - ScriptPubKey(hex::HexToBytesError), + ScriptPubKey(hex::DecodeVariableLengthBytesError), /// The `witness_version` field's value was too big for a u8. WitnessVersionValue(i64), /// Conversion of the `witness_version` field failed. WitnessVersion(witness_version::TryFromError), /// Conversion of the `witness_program` field hex string to bytes failed. - WitnessProgramBytes(hex::HexToBytesError), + WitnessProgramBytes(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_program` field failed. WitnessProgram(witness_program::Error), /// Conversion of the `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the `pubkeys` field failed. PubKeys(key::ParsePublicKeyError), /// Conversion of the `pubkey` field failed. @@ -35,11 +35,11 @@ pub enum GetAddressInfoError { /// Conversion of the `embedded` field failed. Embedded(GetAddressInfoEmbeddedError), /// Conversion of the `hd_key_path` field failed. - HdKeyPath(bip32::Error), + HdKeyPath(bip32::ParseChildNumberError), /// Conversion of the `hd_seed_id` field failed. - HdSeedId(hex::HexToArrayError), + HdSeedId(hex::DecodeFixedLengthBytesError), /// Conversion of the `hd_master_fingerprint` field failed. - HdMasterFingerprint(hex::HexToArrayError), + HdMasterFingerprint(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetAddressInfoError { diff --git a/types/src/v18/wallet/into.rs b/types/src/v18/wallet/into.rs index e53fb7f1a..a8505945d 100644 --- a/types/src/v18/wallet/into.rs +++ b/types/src/v18/wallet/into.rs @@ -2,9 +2,10 @@ use bitcoin::amount::ParseAmountError; use bitcoin::hashes::hash160; -use bitcoin::hex::FromHex; use bitcoin::key::PublicKey; -use bitcoin::{bip32, Address, Amount, ScriptBuf, Txid, WitnessProgram, WitnessVersion}; +use bitcoin::{ + bip32, Address, Amount, RedeemScriptBuf, ScriptPubKeyBuf, Txid, WitnessProgram, WitnessVersion, +}; use super::{ GetAddressInfo, GetAddressInfoEmbedded, GetAddressInfoEmbeddedError, GetAddressInfoError, @@ -21,7 +22,8 @@ impl GetAddressInfo { use GetAddressInfoError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -31,7 +33,7 @@ impl GetAddressInfo { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -40,8 +42,10 @@ impl GetAddressInfo { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = self .pubkeys .map(|pubkeys| { @@ -107,7 +111,8 @@ impl GetAddressInfoEmbedded { use GetAddressInfoEmbeddedError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -117,7 +122,7 @@ impl GetAddressInfoEmbedded { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -126,8 +131,10 @@ impl GetAddressInfoEmbedded { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = None; let sigs_required = self.sigs_required.map(|s| crate::to_u32(s, "sigs_required")).transpose()?; @@ -300,13 +307,14 @@ impl ListUnspentItem { let txid = self.txid.parse::().map_err(E::Txid)?; let vout = crate::to_u32(self.vout, "vout")?; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; let confirmations = crate::to_u32(self.confirmations, "confirmations")?; let redeem_script = self .redeem_script - .map(|hex| ScriptBuf::from_hex(&hex).map_err(E::RedeemScript)) + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::RedeemScript)) .transpose()?; Ok(model::ListUnspentItem { txid, diff --git a/types/src/v19/blockchain/error.rs b/types/src/v19/blockchain/error.rs index 8d8dff0bc..16188ade0 100644 --- a/types/src/v19/blockchain/error.rs +++ b/types/src/v19/blockchain/error.rs @@ -3,7 +3,7 @@ use core::fmt; use bitcoin::amount::ParseAmountError; -use bitcoin::error::UnprefixedHexError; +use bitcoin::parse_int::UnprefixedHexError; use bitcoin::{hex, network}; use crate::error::write_err; @@ -17,7 +17,7 @@ pub enum GetBlockchainInfoError { /// Conversion of the `chain` field failed. Chain(network::ParseNetworkError), /// Conversion of the `best_block_hash` field failed. - BestBlockHash(hex::HexToArrayError), + BestBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `chain_work` field failed. ChainWork(UnprefixedHexError), } @@ -56,9 +56,9 @@ impl From for GetBlockchainInfoError { #[derive(Debug)] pub enum GetBlockFilterError { /// Conversion of the `filter` field failed. - Filter(hex::HexToBytesError), + Filter(hex::DecodeVariableLengthBytesError), /// Conversion of the `header` field failed. - Header(hex::HexToArrayError), + Header(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetBlockFilterError { @@ -84,7 +84,7 @@ impl std::error::Error for GetBlockFilterError { #[derive(Debug)] pub enum MapMempoolEntryError { /// Conversion of a `txid` failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of a `MempoolEntry` failed. MempoolEntry(MempoolEntryError), } @@ -114,13 +114,13 @@ pub enum MempoolEntryError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `MempoolEntryFees` type failed. Fees(MempoolEntryFeesError), /// Conversion of the `depends` field failed. - Depends(hex::HexToArrayError), + Depends(hex::DecodeFixedLengthBytesError), /// Conversion of the `spent_by` field failed. - SpentBy(hex::HexToArrayError), + SpentBy(hex::DecodeFixedLengthBytesError), } impl From for MempoolEntryError { diff --git a/types/src/v19/blockchain/into.rs b/types/src/v19/blockchain/into.rs index fd60814dc..14e9d1519 100644 --- a/types/src/v19/blockchain/into.rs +++ b/types/src/v19/blockchain/into.rs @@ -2,8 +2,7 @@ use std::collections::BTreeMap; -use bitcoin::hex::{self, FromHex as _}; -use bitcoin::{bip158, Amount, BlockHash, Network, Txid, Work, Wtxid}; +use bitcoin::{hex, Amount, BlockHash, Network, Txid, Work, Wtxid}; use super::error::{ GetBlockFilterError, GetBlockchainInfoError, MapMempoolEntryError, MempoolEntryError, @@ -62,8 +61,8 @@ impl GetBlockFilter { pub fn into_model(self) -> Result { use GetBlockFilterError as E; - let filter = Vec::from_hex(&self.filter).map_err(E::Filter)?; - let header = self.header.parse::().map_err(E::Header)?; + let filter = bitcoin::hex::decode_to_vec(&self.filter).map_err(E::Filter)?; + let header = self.header.parse::().map_err(E::Header)?; Ok(model::GetBlockFilter { filter, header }) } } @@ -97,7 +96,9 @@ impl GetChainTxStats { impl GetMempoolAncestors { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolAncestors(v)) } @@ -120,7 +121,9 @@ impl GetMempoolAncestorsVerbose { impl GetMempoolDescendants { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolDescendants(v)) } @@ -241,7 +244,7 @@ impl GetMempoolInfo { impl GetRawMempool { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetRawMempool(v)) } diff --git a/types/src/v20/generating.rs b/types/src/v20/generating.rs index 83a203301..98090a8b8 100644 --- a/types/src/v20/generating.rs +++ b/types/src/v20/generating.rs @@ -28,7 +28,9 @@ pub struct GenerateToDescriptor( impl GenerateToDescriptor { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|s| s.parse()).collect::, _>>()?; Ok(model::GenerateToDescriptor(v)) } diff --git a/types/src/v20/util/into.rs b/types/src/v20/util/into.rs index e30113e9c..1c333633e 100644 --- a/types/src/v20/util/into.rs +++ b/types/src/v20/util/into.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::{Address, ScriptBuf}; +use bitcoin::{Address, RedeemScriptBuf}; use super::{CreateMultisig, CreateMultisigError}; use crate::model; @@ -11,7 +11,8 @@ impl CreateMultisig { use CreateMultisigError as E; let address = self.address.parse::>().map_err(E::Address)?; - let redeem_script = ScriptBuf::from_hex(&self.redeem_script).map_err(E::RedeemScript)?; + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix(&self.redeem_script) + .map_err(E::RedeemScript)?; Ok(model::CreateMultisig { address, diff --git a/types/src/v20/wallet/error.rs b/types/src/v20/wallet/error.rs index d11a6559e..0e90eaac4 100644 --- a/types/src/v20/wallet/error.rs +++ b/types/src/v20/wallet/error.rs @@ -18,7 +18,7 @@ pub enum ListSinceBlockError { /// Conversion of item in `removed` list failed. Removed(TransactionItemError), /// Conversion of the `last_block` field failed. - LastBlock(hex::HexToArrayError), + LastBlock(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListSinceBlockError { @@ -60,11 +60,11 @@ pub enum TransactionItemError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of an item in the `wallet_conflicts` list failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TransactionItemError { diff --git a/types/src/v20/wallet/into.rs b/types/src/v20/wallet/into.rs index 20223daa0..59e6fa352 100644 --- a/types/src/v20/wallet/into.rs +++ b/types/src/v20/wallet/into.rs @@ -1,11 +1,10 @@ // SPDX-License-Identifier: CC0-1.0 use bitcoin::consensus::encode; use bitcoin::hashes::hash160; -use bitcoin::hex::FromHex; use bitcoin::key::PublicKey; use bitcoin::{ - bip32, Address, BlockHash, ScriptBuf, SignedAmount, Transaction, Txid, WitnessProgram, - WitnessVersion, + bip32, Address, BlockHash, RedeemScriptBuf, ScriptPubKeyBuf, SignedAmount, Transaction, Txid, + WitnessProgram, WitnessVersion, }; use super::{ @@ -22,7 +21,8 @@ impl AddMultisigAddress { use AddMultisigAddressError as E; let address = self.address.parse::>().map_err(E::Address)?; - let redeem_script = ScriptBuf::from_hex(&self.redeem_script).map_err(E::RedeemScript)?; + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix(&self.redeem_script) + .map_err(E::RedeemScript)?; Ok(model::AddMultisigAddress { address, @@ -39,7 +39,8 @@ impl GetAddressInfo { use GetAddressInfoError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -49,7 +50,7 @@ impl GetAddressInfo { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -58,8 +59,10 @@ impl GetAddressInfo { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = self .pubkeys .map(|pubkeys| { @@ -124,7 +127,8 @@ impl GetAddressInfoEmbedded { use GetAddressInfoEmbeddedError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -134,7 +138,7 @@ impl GetAddressInfoEmbedded { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -143,8 +147,10 @@ impl GetAddressInfoEmbedded { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = None; let sigs_required = self.sigs_required.map(|s| crate::to_u32(s, "sigs_required")).transpose()?; @@ -293,7 +299,7 @@ impl TransactionItem { .fee .map(|f| SignedAmount::from_btc(f).map_err(E::Fee)) .transpose()? // optional historically - .unwrap_or_else(|| SignedAmount::from_sat(0)); + .unwrap_or_else(|| SignedAmount::from_sat(0).expect("TODO: Handle this error")); let block_hash = self.block_hash.parse::().map_err(E::BlockHash)?; let block_height = crate::to_u32(self.block_height, "block_height")?; let block_index = crate::to_u32(self.block_index, "block_index")?; diff --git a/types/src/v21/blockchain/into.rs b/types/src/v21/blockchain/into.rs index 4c53d0b29..2ba715b38 100644 --- a/types/src/v21/blockchain/into.rs +++ b/types/src/v21/blockchain/into.rs @@ -54,7 +54,9 @@ impl GetBlockchainInfo { impl GetMempoolAncestors { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolAncestors(v)) } @@ -77,7 +79,9 @@ impl GetMempoolAncestorsVerbose { impl GetMempoolDescendants { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolDescendants(v)) } @@ -185,7 +189,7 @@ impl GetMempoolInfo { impl GetRawMempool { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetRawMempool(v)) } @@ -208,7 +212,9 @@ impl GetRawMempoolVerbose { impl GetRawMempoolSequence { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let txids = self.txids.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetRawMempoolSequence { txids, mempool_sequence: self.mempool_sequence }) } diff --git a/types/src/v21/generating/into.rs b/types/src/v21/generating/into.rs index a0c79ac2a..8c528b250 100644 --- a/types/src/v21/generating/into.rs +++ b/types/src/v21/generating/into.rs @@ -11,7 +11,7 @@ use crate::model; impl GenerateBlock { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let hash = self.hash.parse::()?; Ok(model::GenerateBlock { hash, diff --git a/types/src/v21/raw_transactions/error.rs b/types/src/v21/raw_transactions/error.rs index 7f80cc639..fb0759c55 100644 --- a/types/src/v21/raw_transactions/error.rs +++ b/types/src/v21/raw_transactions/error.rs @@ -43,7 +43,7 @@ pub enum MempoolAcceptanceError { /// Conversion of a numeric field failed. Numeric(NumericError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `base` fee field failed. Base(ParseAmountError), } diff --git a/types/src/v21/wallet/error.rs b/types/src/v21/wallet/error.rs index c50de8ed6..1021734ae 100644 --- a/types/src/v21/wallet/error.rs +++ b/types/src/v21/wallet/error.rs @@ -47,7 +47,7 @@ impl std::error::Error for PsbtBumpFeeError { #[derive(Debug)] pub enum SendError { /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `hex` field failed. Hex(encode::FromHexError), /// Conversion of the `psbt` field failed. diff --git a/types/src/v21/wallet/into.rs b/types/src/v21/wallet/into.rs index 0417993d3..cab2faadb 100644 --- a/types/src/v21/wallet/into.rs +++ b/types/src/v21/wallet/into.rs @@ -50,7 +50,7 @@ impl Send { impl SendMany { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let txid = self.0.parse::()?; Ok(model::SendMany(txid)) } @@ -58,7 +58,7 @@ impl SendMany { impl SendManyVerbose { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let txid = self.txid.parse::()?; Ok(model::SendManyVerbose { txid, fee_reason: self.fee_reason }) } diff --git a/types/src/v22/raw_transactions/error.rs b/types/src/v22/raw_transactions/error.rs index ef7956956..7b75eed23 100644 --- a/types/src/v22/raw_transactions/error.rs +++ b/types/src/v22/raw_transactions/error.rs @@ -12,7 +12,7 @@ use crate::NumericError; #[derive(Debug)] pub enum DecodeScriptError { /// Conversion of the transaction `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the transaction `address` field failed. Address(address::ParseError), /// Conversion of the transaction `addresses` field failed. @@ -80,9 +80,9 @@ pub enum MempoolAcceptanceError { /// Conversion of a numeric field failed. Numeric(NumericError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `base` fee field failed. Base(ParseAmountError), } diff --git a/types/src/v22/wallet/into.rs b/types/src/v22/wallet/into.rs index 656c068cf..847cd34cf 100644 --- a/types/src/v22/wallet/into.rs +++ b/types/src/v22/wallet/into.rs @@ -1,9 +1,10 @@ // SPDX-License-Identifier: CC0-1.0 use bitcoin::hashes::hash160; -use bitcoin::hex::FromHex; use bitcoin::key::PublicKey; -use bitcoin::{address, bip32, Address, ScriptBuf, WitnessProgram, WitnessVersion}; +use bitcoin::{ + address, bip32, Address, RedeemScriptBuf, ScriptPubKeyBuf, WitnessProgram, WitnessVersion, +}; use super::{ GetAddressInfo, GetAddressInfoEmbedded, GetAddressInfoEmbeddedError, GetAddressInfoError, @@ -17,7 +18,8 @@ impl GetAddressInfo { use GetAddressInfoError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -27,7 +29,7 @@ impl GetAddressInfo { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -36,8 +38,10 @@ impl GetAddressInfo { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = self .pubkeys .map(|pubkeys| { @@ -102,7 +106,8 @@ impl GetAddressInfoEmbedded { use GetAddressInfoEmbeddedError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -112,7 +117,7 @@ impl GetAddressInfoEmbedded { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -121,8 +126,10 @@ impl GetAddressInfoEmbedded { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = None; let sigs_required = self.sigs_required.map(|s| crate::to_u32(s, "sigs_required")).transpose()?; diff --git a/types/src/v23/blockchain/error.rs b/types/src/v23/blockchain/error.rs index 00abf937c..dfb87b6c9 100644 --- a/types/src/v23/blockchain/error.rs +++ b/types/src/v23/blockchain/error.rs @@ -10,7 +10,7 @@ use crate::NumericError; #[derive(Debug)] pub enum GetDeploymentInfoError { /// Conversion of the `hash field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `deployments` field failed. Deployment(NumericError), } diff --git a/types/src/v23/blockchain/into.rs b/types/src/v23/blockchain/into.rs index 7a6814d30..4e8bd6956 100644 --- a/types/src/v23/blockchain/into.rs +++ b/types/src/v23/blockchain/into.rs @@ -112,7 +112,9 @@ impl Bip9Statistics { impl GetMempoolAncestors { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolAncestors(v)) } @@ -135,7 +137,9 @@ impl GetMempoolAncestorsVerbose { impl GetMempoolDescendants { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolDescendants(v)) } @@ -214,7 +218,7 @@ impl MempoolEntry { impl GetRawMempool { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model(self) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetRawMempool(v)) } diff --git a/types/src/v23/raw_transactions/error.rs b/types/src/v23/raw_transactions/error.rs index 3ca2d2d1b..4ebbb4acb 100644 --- a/types/src/v23/raw_transactions/error.rs +++ b/types/src/v23/raw_transactions/error.rs @@ -16,9 +16,9 @@ pub enum DecodePsbtError { /// Conversion of the `global_xpubs` field failed. GlobalXpubs(GlobalXpubError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of one the map items in the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), /// Conversion of one of the PSBT inputs failed. Inputs(PsbtInputError), /// Conversion of one of the PSBT outputs failed. @@ -65,11 +65,11 @@ impl std::error::Error for DecodePsbtError { #[derive(Debug)] pub enum GlobalXpubError { /// Conversion of the `xpub` field failed. - Xpub(bip32::Error), + Xpub(bip32::ParseError), /// Conversion of the `master_fingerprint` field failed. - MasterFingerprint(hex::HexToArrayError), + MasterFingerprint(hex::DecodeFixedLengthBytesError), /// Conversion of the `path` field failed. - Path(bip32::Error), + Path(bip32::ParseChildNumberError), } impl fmt::Display for GlobalXpubError { @@ -106,35 +106,35 @@ pub enum PsbtInputError { /// Conversion of the `sighash` field failed. Sighash(sighash::SighashTypeParseError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `final_script_sig` field failed. - FinalScriptSig(hex::HexToBytesError), + FinalScriptSig(hex::DecodeVariableLengthBytesError), /// Conversion of the `final_script_witness` field failed. - FinalScriptWitness(hex::HexToBytesError), + FinalScriptWitness(hex::DecodeVariableLengthBytesError), /// Conversion of the `ripemd160` hash failed. - Ripemd160(hex::HexToArrayError), + Ripemd160(hex::DecodeFixedLengthBytesError), /// Conversion of the `ripemd160` preimage failed. - Ripemd160Preimage(hex::HexToBytesError), + Ripemd160Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `sha256` hash failed. - Sha256(hex::HexToArrayError), + Sha256(hex::DecodeFixedLengthBytesError), /// Conversion of the `sha256` preimage failed. - Sha256Preimage(hex::HexToBytesError), + Sha256Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `hash160` hash failed. - Hash160(hex::HexToArrayError), + Hash160(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash160` preimage failed. - Hash160Preimage(hex::HexToBytesError), + Hash160Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `hash256` hash failed. - Hash256(hex::HexToArrayError), + Hash256(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash256` preimage failed. - Hash256Preimage(hex::HexToBytesError), + Hash256Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtInputError { @@ -207,15 +207,15 @@ impl std::error::Error for PsbtInputError { #[derive(Debug)] pub enum PsbtOutputError { /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtOutputError { @@ -251,7 +251,7 @@ impl std::error::Error for PsbtOutputError { #[derive(Debug)] pub enum DecodeScriptError { /// Conversion of the transaction `hex` field failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Conversion of the transaction `address` field failed. Address(address::ParseError), /// Conversion of the transaction `addresses` field failed. diff --git a/types/src/v23/raw_transactions/into.rs b/types/src/v23/raw_transactions/into.rs index 050c5025a..58cacce57 100644 --- a/types/src/v23/raw_transactions/into.rs +++ b/types/src/v23/raw_transactions/into.rs @@ -4,9 +4,8 @@ use std::collections::BTreeMap; use bitcoin::bip32::{DerivationPath, Fingerprint, KeySource, Xpub}; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; -use bitcoin::hex::{self, FromHex as _}; use bitcoin::psbt::{self, raw, PsbtSighashType}; -use bitcoin::{Address, Amount}; +use bitcoin::{hex, Address, Amount}; use super::{ DecodePsbt, DecodePsbtError, DecodeScript, DecodeScriptError, GlobalXpub, GlobalXpubError, @@ -89,18 +88,12 @@ impl Proprietary { /// Converts this proprietary list element to a map entry suitable to use in `bitcoin::Psbt`. pub fn to_key_value_pair( &self, - ) -> Result<(raw::ProprietaryKey, Vec), hex::HexToBytesError> { - // FIXME: Remove cast once rust-bitcoin 0.33 is out. - // - // This is changed to a u64 in the upcoming rust-bitcoin - // release, until then just ignore any additional bits. - let subtype = self.subtype as u8; - - let prefix = Vec::from_hex(&self.identifier)?; - let key = Vec::from_hex(&self.key)?; - let value = Vec::from_hex(&self.value)?; - - Ok((raw::ProprietaryKey { prefix, subtype, key }, value)) + ) -> Result<(raw::ProprietaryKey, Vec), hex::DecodeVariableLengthBytesError> { + let prefix = bitcoin::hex::decode_to_vec(&self.identifier)?; + let key = bitcoin::hex::decode_to_vec(&self.key)?; + let value = bitcoin::hex::decode_to_vec(&self.value)?; + + Ok((raw::ProprietaryKey { prefix, subtype: self.subtype, key }, value)) } } @@ -156,7 +149,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Ripemd160)?; - let preimage = Vec::from_hex(preimage).map_err(E::Ripemd160Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Ripemd160Preimage)?; preimages.insert(hash, preimage); } preimages @@ -168,7 +162,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Sha256)?; - let preimage = Vec::from_hex(preimage).map_err(E::Sha256Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Sha256Preimage)?; preimages.insert(hash, preimage); } preimages @@ -180,7 +175,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Hash160)?; - let preimage = Vec::from_hex(preimage).map_err(E::Hash160Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Hash160Preimage)?; preimages.insert(hash, preimage); } preimages @@ -192,7 +188,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Hash256)?; - let preimage = Vec::from_hex(preimage).map_err(E::Hash256Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Hash256Preimage)?; preimages.insert(hash, preimage); } preimages @@ -225,6 +222,9 @@ impl PsbtInput { let tap_internal_key = None; let tap_merkle_root = None; + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + Ok(psbt::Input { non_witness_utxo, witness_utxo, @@ -245,6 +245,7 @@ impl PsbtInput { tap_key_origins, tap_internal_key, tap_merkle_root, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -294,6 +295,9 @@ impl PsbtOutput { let tap_tree = None; let tap_key_origins = BTreeMap::default(); + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + Ok(psbt::Output { redeem_script, witness_script, @@ -301,6 +305,7 @@ impl PsbtOutput { tap_internal_key, tap_tree, tap_key_origins, + musig2_participant_pubkeys, proprietary, unknown, }) diff --git a/types/src/v23/raw_transactions/mod.rs b/types/src/v23/raw_transactions/mod.rs index d146b13b9..8b3865308 100644 --- a/types/src/v23/raw_transactions/mod.rs +++ b/types/src/v23/raw_transactions/mod.rs @@ -69,7 +69,7 @@ pub struct Proprietary { /// The hex string for the proprietary identifier. identifier: String, /// The number for the subtype. - subtype: i64, + subtype: u64, /// The hex for the key. key: String, /// The hex for the value. diff --git a/types/src/v23/util/into.rs b/types/src/v23/util/into.rs index 9411399c3..39d464b20 100644 --- a/types/src/v23/util/into.rs +++ b/types/src/v23/util/into.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::{Address, ScriptBuf}; +use bitcoin::{Address, RedeemScriptBuf}; use super::{CreateMultisig, CreateMultisigError}; use crate::model; @@ -11,7 +11,8 @@ impl CreateMultisig { use CreateMultisigError as E; let address = self.address.parse::>().map_err(E::Address)?; - let redeem_script = ScriptBuf::from_hex(&self.redeem_script).map_err(E::RedeemScript)?; + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix(&self.redeem_script) + .map_err(E::RedeemScript)?; Ok(model::CreateMultisig { address, diff --git a/types/src/v23/wallet/error.rs b/types/src/v23/wallet/error.rs index 6deb275a8..376f84efa 100644 --- a/types/src/v23/wallet/error.rs +++ b/types/src/v23/wallet/error.rs @@ -20,15 +20,15 @@ pub enum GetTransactionError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaced_by_txid` field failed. - ReplacedByTxid(hex::HexToArrayError), + ReplacedByTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaces_txid` field failed. - ReplacesTxid(hex::HexToArrayError), + ReplacesTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `hex` field failed. Tx(encode::FromHexError), /// Conversion of the `details` field failed. @@ -43,7 +43,7 @@ pub enum ListSinceBlockError { /// Conversion of the `removed` field failed. Removed(TransactionItemError), /// Conversion of the `last_block` field failed. - LastBlock(hex::HexToArrayError), + LastBlock(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListSinceBlockError { @@ -81,15 +81,15 @@ pub enum TransactionItemError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaced_by_txid` field failed. - ReplacedByTxid(hex::HexToArrayError), + ReplacedByTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaces_txid` field failed. - ReplacesTxid(hex::HexToArrayError), + ReplacesTxid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TransactionItemError { diff --git a/types/src/v23/wallet/into.rs b/types/src/v23/wallet/into.rs index 2261e1188..9b00fff21 100644 --- a/types/src/v23/wallet/into.rs +++ b/types/src/v23/wallet/into.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: CC0-1.0 use bitcoin::consensus::encode; -use bitcoin::{Address, BlockHash, ScriptBuf, SignedAmount, Transaction, Txid}; +use bitcoin::{Address, BlockHash, RedeemScriptBuf, SignedAmount, Transaction, Txid}; use super::{ AddMultisigAddress, AddMultisigAddressError, GetTransaction, GetTransactionError, @@ -16,7 +16,8 @@ impl AddMultisigAddress { use AddMultisigAddressError as E; let address = self.address.parse::>().map_err(E::Address)?; - let redeem_script = ScriptBuf::from_hex(&self.redeem_script).map_err(E::RedeemScript)?; + let redeem_script = RedeemScriptBuf::from_hex_no_length_prefix(&self.redeem_script) + .map_err(E::RedeemScript)?; Ok(model::AddMultisigAddress { address, @@ -182,7 +183,7 @@ impl TransactionItem { .fee .map(|f| SignedAmount::from_btc(f).map_err(E::Fee)) .transpose()? // optional historically - .unwrap_or_else(|| SignedAmount::from_sat(0)); + .unwrap_or_else(|| SignedAmount::from_sat(0).expect("TODO: Handle this error")); let block_hash = self.block_hash.map(|h| h.parse::().map_err(E::BlockHash)).transpose()?; let block_height = diff --git a/types/src/v24/blockchain/error.rs b/types/src/v24/blockchain/error.rs index 5326b1423..3ce0d404e 100644 --- a/types/src/v24/blockchain/error.rs +++ b/types/src/v24/blockchain/error.rs @@ -9,9 +9,9 @@ use crate::error::write_err; #[derive(Debug)] pub enum GetTxSpendingPrevoutError { /// Conversion of the `outpoint` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `spending_txid` field failed. - SpendingTxid(hex::HexToArrayError), + SpendingTxid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetTxSpendingPrevoutError { diff --git a/types/src/v24/blockchain/into.rs b/types/src/v24/blockchain/into.rs index 4523a7e28..afbab3ac9 100644 --- a/types/src/v24/blockchain/into.rs +++ b/types/src/v24/blockchain/into.rs @@ -14,7 +14,9 @@ use crate::model; impl GetMempoolAncestors { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolAncestors(v)) } @@ -37,7 +39,9 @@ impl GetMempoolAncestorsVerbose { impl GetMempoolDescendants { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let v = self.0.iter().map(|t| t.parse::()).collect::, _>>()?; Ok(model::GetMempoolDescendants(v)) } @@ -150,7 +154,7 @@ impl GetMempoolInfo { max_mempool, mempool_min_fee, min_relay_tx_fee, - incremental_relay_fee, + incremental_relay_fee: Some(incremental_relay_fee), unbroadcast_count, full_rbf: Some(self.full_rbf), permit_bare_multisig: None, diff --git a/types/src/v24/raw_transactions/error.rs b/types/src/v24/raw_transactions/error.rs index 87e7dd333..00a95a8a5 100644 --- a/types/src/v24/raw_transactions/error.rs +++ b/types/src/v24/raw_transactions/error.rs @@ -3,8 +3,10 @@ use core::fmt; use bitcoin::amount::ParseAmountError; -use bitcoin::taproot::{IncompleteBuilderError, TaprootBuilderError, TaprootError}; -use bitcoin::{bip32, hex, secp256k1, sighash}; +use bitcoin::taproot::{ + IncompleteBuilderError, InvalidTaprootLeafVersionError, TaprootBuilderError, TaprootError, +}; +use bitcoin::{bip32, hex, key, sighash}; use super::{Bip32DerivError, PartialSignatureError, RawTransactionError, WitnessUtxoError}; use crate::error::write_err; @@ -17,9 +19,9 @@ pub enum DecodePsbtError { /// Conversion of the `global_xpubs` field failed. GlobalXpubs(GlobalXpubError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of one the map items in the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), /// Conversion of one of the PSBT inputs failed. Inputs(PsbtInputError), /// Conversion of one of the PSBT outputs failed. @@ -66,11 +68,11 @@ impl std::error::Error for DecodePsbtError { #[derive(Debug)] pub enum GlobalXpubError { /// Conversion of the `xpub` field failed. - Xpub(bip32::Error), + Xpub(bip32::ParseError), /// Conversion of the `master_fingerprint` field failed. - MasterFingerprint(hex::HexToArrayError), + MasterFingerprint(hex::DecodeFixedLengthBytesError), /// Conversion of the `path` field failed. - Path(bip32::Error), + Path(bip32::ParseChildNumberError), } impl fmt::Display for GlobalXpubError { @@ -107,31 +109,31 @@ pub enum PsbtInputError { /// Conversion of the `sighash` field failed. Sighash(sighash::SighashTypeParseError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `final_script_sig` field failed. - FinalScriptSig(hex::HexToBytesError), + FinalScriptSig(hex::DecodeVariableLengthBytesError), /// Conversion of the `final_script_witness` field failed. - FinalScriptWitness(hex::HexToBytesError), + FinalScriptWitness(hex::DecodeVariableLengthBytesError), /// Conversion of the `ripemd160` hash failed. - Ripemd160(hex::HexToArrayError), + Ripemd160(hex::DecodeFixedLengthBytesError), /// Conversion of the `ripemd160` preimage failed. - Ripemd160Preimage(hex::HexToBytesError), + Ripemd160Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `sha256` hash failed. - Sha256(hex::HexToArrayError), + Sha256(hex::DecodeFixedLengthBytesError), /// Conversion of the `sha256` preimage failed. - Sha256Preimage(hex::HexToBytesError), + Sha256Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `hash160` hash failed. - Hash160(hex::HexToArrayError), + Hash160(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash160` preimage failed. - Hash160Preimage(hex::HexToBytesError), + Hash160Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `hash256` hash failed. - Hash256(hex::HexToArrayError), + Hash256(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash256` preimage failed. - Hash256Preimage(hex::HexToBytesError), + Hash256Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `taproot_key_path_sig` field failed. TaprootKeyPathSig(super::taproot::Error), /// Conversion of the `taproot_script_path_sigs` field failed. @@ -141,13 +143,13 @@ pub enum PsbtInputError { /// Conversion of the `taproot_bip32_derives` field failed. TaprootBip32Derivs(TaprootBip32DerivsError), /// Conversion of the `taproot_internal_key` field failed. - TaprootInternalKey(secp256k1::Error), + TaprootInternalKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `taproot_merkle_root` field failed. - TaprootMerkleRoot(hex::HexToArrayError), + TaprootMerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtInputError { @@ -238,21 +240,21 @@ impl std::error::Error for PsbtInputError { #[derive(Debug)] pub enum PsbtOutputError { /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `taproot_internal_key` field failed. - TaprootInternalKey(secp256k1::Error), + TaprootInternalKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `taproot_tree` field failed. TaprootTree(TaprootLeafError), /// Conversion of the `taproot_bip32_derives` field failed. TaprootBip32Derivs(TaprootBip32DerivsError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtOutputError { @@ -297,9 +299,9 @@ impl std::error::Error for PsbtOutputError { #[derive(Debug)] pub enum TaprootScriptPathSigError { /// Conversion of the `pubkey` field failed. - PubKey(secp256k1::Error), + PubKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `leaf_hash` field failed. - LeafHash(hex::HexToArrayError), + LeafHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `sig` field failed. Sig(super::taproot::Error), } @@ -329,9 +331,9 @@ impl std::error::Error for TaprootScriptPathSigError { #[derive(Debug)] pub enum TaprootScriptError { /// Conversion of the `script` field failed. - Script(hex::HexToBytesError), + Script(hex::DecodeVariableLengthBytesError), /// Conversion of the `leaf_ver` field failed. - LeafVer(TaprootError), + LeafVer(InvalidTaprootLeafVersionError), /// Conversion of the `control_blocks` field failed. ControlBlocks(ControlBlocksError), } @@ -366,7 +368,7 @@ pub enum ControlBlocksError { /// Multiple control blocks returned by Core for this script. Multiple(usize), /// Failed to parse control block hex string. - Parse(hex::HexToBytesError), + Parse(hex::DecodeVariableLengthBytesError), /// Failed to decode parsed bytes. Decode(TaprootError), } @@ -399,13 +401,13 @@ impl std::error::Error for ControlBlocksError { #[derive(Debug)] pub enum TaprootBip32DerivsError { /// Conversion of the `pubkey` field failed. - PubKey(secp256k1::Error), + PubKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `master_fingerprint` field failed. - MasterFingerprint(hex::HexToArrayError), + MasterFingerprint(hex::DecodeFixedLengthBytesError), /// Conversion of the `path` field failed. - Path(bip32::Error), + Path(bip32::ParseChildNumberError), /// Conversion of one of the leaf hashes failed. - LeafHashes(hex::HexToArrayError), + LeafHashes(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TaprootBip32DerivsError { @@ -437,9 +439,9 @@ impl std::error::Error for TaprootBip32DerivsError { #[derive(Debug)] pub enum TaprootLeafError { /// Conversion of the `leaf_ver` field failed. - LeafVer(TaprootError), + LeafVer(InvalidTaprootLeafVersionError), /// Conversion of the `script` field failed. - Script(hex::HexToBytesError), + Script(hex::DecodeVariableLengthBytesError), /// Failed to add leaf to builder. TaprootBuilder(TaprootBuilderError), /// Failed to convert builder into a tap tree. diff --git a/types/src/v24/raw_transactions/into.rs b/types/src/v24/raw_transactions/into.rs index fc3c01563..c8b01b89b 100644 --- a/types/src/v24/raw_transactions/into.rs +++ b/types/src/v24/raw_transactions/into.rs @@ -4,12 +4,11 @@ use std::collections::BTreeMap; use bitcoin::bip32::{DerivationPath, Fingerprint, KeySource, Xpub}; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; -use bitcoin::hex::{self, FromHex as _}; use bitcoin::psbt::{self, raw, PsbtSighashType}; use bitcoin::taproot::{ ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder, }; -use bitcoin::{Amount, ScriptBuf, XOnlyPublicKey}; +use bitcoin::{hex, Amount, TapScriptBuf, XOnlyPublicKey}; use super::{ taproot, ControlBlocksError, DecodePsbt, DecodePsbtError, GlobalXpub, GlobalXpubError, @@ -94,18 +93,12 @@ impl Proprietary { /// Converts this proprietary list element to a map entry suitable to use in `bitcoin::Psbt`. pub fn to_key_value_pair( &self, - ) -> Result<(raw::ProprietaryKey, Vec), hex::HexToBytesError> { - // FIXME: Remove cast once rust-bitcoin 0.33 is out. - // - // This is changed to a u64 in the upcoming rust-bitcoin - // release, until then just ignore any additional bits. - let subtype = self.subtype as u8; - - let prefix = Vec::from_hex(&self.identifier)?; - let key = Vec::from_hex(&self.key)?; - let value = Vec::from_hex(&self.value)?; - - Ok((raw::ProprietaryKey { prefix, subtype, key }, value)) + ) -> Result<(raw::ProprietaryKey, Vec), hex::DecodeVariableLengthBytesError> { + let prefix = bitcoin::hex::decode_to_vec(&self.identifier)?; + let key = bitcoin::hex::decode_to_vec(&self.key)?; + let value = bitcoin::hex::decode_to_vec(&self.value)?; + + Ok((raw::ProprietaryKey { prefix, subtype: self.subtype, key }, value)) } } @@ -161,7 +154,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Ripemd160)?; - let preimage = Vec::from_hex(preimage).map_err(E::Ripemd160Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Ripemd160Preimage)?; preimages.insert(hash, preimage); } preimages @@ -173,7 +167,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Sha256)?; - let preimage = Vec::from_hex(preimage).map_err(E::Sha256Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Sha256Preimage)?; preimages.insert(hash, preimage); } preimages @@ -185,7 +180,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Hash160)?; - let preimage = Vec::from_hex(preimage).map_err(E::Hash160Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Hash160Preimage)?; preimages.insert(hash, preimage); } preimages @@ -197,7 +193,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Hash256)?; - let preimage = Vec::from_hex(preimage).map_err(E::Hash256Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Hash256Preimage)?; preimages.insert(hash, preimage); } preimages @@ -274,6 +271,9 @@ impl PsbtInput { None => BTreeMap::default(), }; + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + Ok(psbt::Input { non_witness_utxo, witness_utxo, @@ -294,6 +294,7 @@ impl PsbtInput { tap_key_origins, tap_internal_key, tap_merkle_root, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -359,6 +360,9 @@ impl PsbtOutput { None => BTreeMap::default(), }; + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + Ok(psbt::Output { redeem_script, witness_script, @@ -366,6 +370,7 @@ impl PsbtOutput { tap_internal_key, tap_tree, tap_key_origins, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -392,10 +397,10 @@ impl TaprootScript { /// Converts list element to a map entry suitable to use in `bitcoin::psbt::Input`. pub fn to_key_value_pair( &self, - ) -> Result<(ControlBlock, (ScriptBuf, LeafVersion)), TaprootScriptError> { + ) -> Result<(ControlBlock, (TapScriptBuf, LeafVersion)), TaprootScriptError> { use TaprootScriptError as E; - let script = ScriptBuf::from_hex(&self.script).map_err(E::Script)?; + let script = TapScriptBuf::from_hex_no_length_prefix(&self.script).map_err(E::Script)?; let leaf_version = self.leaf_version as u8; // FIXME: Is this cast ok? let version = LeafVersion::from_consensus(leaf_version).map_err(E::LeafVer)?; @@ -415,7 +420,7 @@ fn control_block(control_blocks: &[String]) -> Result Err(E::Missing), 1 => { - let bytes = Vec::from_hex(&control_blocks[0]).map_err(E::Parse)?; + let bytes = bitcoin::hex::decode_to_vec(&control_blocks[0]).map_err(E::Parse)?; Ok(ControlBlock::decode(&bytes).map_err(E::Decode)?) } n => Err(E::Multiple(n)), @@ -455,7 +460,7 @@ fn build_taproot_tree(leaves: Vec) -> Result Result { use Error as E; - let bytes = Vec::from_hex(sig).map_err(E::Hex)?; + let bytes = bitcoin::hex::decode_to_vec(sig).map_err(E::Hex)?; let (sighash_byte, signature) = bytes.split_last().ok_or(E::EmptySignature)?; Ok(Signature { signature: secp256k1::schnorr::Signature::from_slice(signature) @@ -233,7 +232,7 @@ pub mod taproot { #[non_exhaustive] pub enum Error { /// Hex decoding error. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Non-standard sighash type. SighashType(InvalidSighashTypeError), /// Signature was empty. diff --git a/types/src/v24/wallet/error.rs b/types/src/v24/wallet/error.rs index 3b1f8ee04..b9f128004 100644 --- a/types/src/v24/wallet/error.rs +++ b/types/src/v24/wallet/error.rs @@ -21,19 +21,19 @@ pub enum GetTransactionError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaced_by_txid` field failed. - ReplacedByTxid(hex::HexToArrayError), + ReplacedByTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaces_txid` field failed. - ReplacesTxid(hex::HexToArrayError), + ReplacesTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `mempool_conflicts` field failed. - MempoolConflicts(hex::HexToArrayError), + MempoolConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `hex` field failed. Tx(encode::FromHexError), /// Conversion of the `details` field failed. @@ -96,7 +96,7 @@ pub enum ListSinceBlockError { /// Conversion of the `removed` field failed. Removed(TransactionItemError), /// Conversion of the `last_block` field failed. - LastBlock(hex::HexToArrayError), + LastBlock(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListSinceBlockError { @@ -134,17 +134,17 @@ pub enum TransactionItemError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaced_by_txid` field failed. - ReplacedByTxid(hex::HexToArrayError), + ReplacedByTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaces_txid` field failed. - ReplacesTxid(hex::HexToArrayError), + ReplacesTxid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TransactionItemError { @@ -194,7 +194,7 @@ impl From for TransactionItemError { #[derive(Debug)] pub enum SendAllError { /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `hex` field failed. Hex(encode::FromHexError), /// Conversion of the `psbt` field failed. diff --git a/types/src/v24/wallet/into.rs b/types/src/v24/wallet/into.rs index b7ca1ab5c..9a1d0d2a5 100644 --- a/types/src/v24/wallet/into.rs +++ b/types/src/v24/wallet/into.rs @@ -2,7 +2,9 @@ use bitcoin::amount::ParseAmountError; use bitcoin::consensus::encode; -use bitcoin::{Address, Amount, BlockHash, ScriptBuf, SignedAmount, Transaction, Txid}; +use bitcoin::{ + Address, Amount, BlockHash, RedeemScriptBuf, ScriptPubKeyBuf, SignedAmount, Transaction, Txid, +}; use super::{ GetTransaction, GetTransactionDetail, GetTransactionDetailError, GetTransactionError, @@ -138,7 +140,7 @@ impl TransactionItem { .fee .map(|f| SignedAmount::from_btc(f).map_err(E::Fee)) .transpose()? // optional historically - .unwrap_or_else(|| SignedAmount::from_sat(0)); + .unwrap_or_else(|| SignedAmount::from_sat(0).expect("TODO: Handle this error")); let block_hash = self.block_hash.map(|h| h.parse::().map_err(E::BlockHash)).transpose()?; let block_height = @@ -219,14 +221,15 @@ impl ListUnspentItem { let txid = self.txid.parse::().map_err(E::Txid)?; let vout = crate::to_u32(self.vout, "vout")?; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let label = self.label.unwrap_or_default(); let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; let confirmations = crate::to_u32(self.confirmations, "confirmations")?; let redeem_script = self .redeem_script - .map(|hex| ScriptBuf::from_hex(&hex).map_err(E::RedeemScript)) + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::RedeemScript)) .transpose()?; Ok(model::ListUnspentItem { diff --git a/types/src/v25/blockchain/error.rs b/types/src/v25/blockchain/error.rs index 84e1a1153..e8e2fe622 100644 --- a/types/src/v25/blockchain/error.rs +++ b/types/src/v25/blockchain/error.rs @@ -13,7 +13,7 @@ pub enum ScanBlocksStartError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `relevant_blocks` field failed. - RelevantBlocks(hex::HexToArrayError), + RelevantBlocks(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ScanBlocksStartError { diff --git a/types/src/v25/blockchain/into.rs b/types/src/v25/blockchain/into.rs index 64da233cc..d743d3a7a 100644 --- a/types/src/v25/blockchain/into.rs +++ b/types/src/v25/blockchain/into.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::{Amount, BlockHash, FeeRate, ScriptBuf, Txid, Weight}; +use bitcoin::{Amount, BlockHash, FeeRate, ScriptPubKeyBuf, Txid, Weight}; use super::error::ScanBlocksStartError; use super::{ @@ -21,7 +21,7 @@ impl GetBlockStats { .fee_rate_percentiles .iter() .map(|vb| FeeRate::from_sat_per_vb(*vb)) - .collect::>>(); + .collect::>(); let max_fee_rate = FeeRate::from_sat_per_vb(self.max_fee_rate); let minimum_fee_rate = FeeRate::from_sat_per_vb(self.minimum_fee_rate); @@ -30,32 +30,32 @@ impl GetBlockStats { let total_weight = Weight::from_vb(self.total_weight); Ok(model::GetBlockStats { - average_fee: Amount::from_sat(self.average_fee), + average_fee: Amount::from_sat(self.average_fee).expect("TODO: Handle this error"), average_fee_rate, average_tx_size: crate::to_u32(self.average_tx_size, "average_tx_size")?, block_hash, fee_rate_percentiles, height: crate::to_u32(self.height, "height")?, inputs: crate::to_u32(self.inputs, "inputs")?, - max_fee: Amount::from_sat(self.max_fee), + max_fee: Amount::from_sat(self.max_fee).expect("TODO: Handle this error"), max_fee_rate, max_tx_size: crate::to_u32(self.max_tx_size, "max_tx_size")?, - median_fee: Amount::from_sat(self.median_fee), + median_fee: Amount::from_sat(self.median_fee).expect("TODO: Handle this error"), median_time: crate::to_u32(self.median_time, "median_time")?, median_tx_size: crate::to_u32(self.median_tx_size, "median_tx_size")?, - minimum_fee: Amount::from_sat(self.minimum_fee), + minimum_fee: Amount::from_sat(self.minimum_fee).expect("TODO: Handle this error"), minimum_fee_rate, minimum_tx_size: crate::to_u32(self.minimum_tx_size, "minimum_tx_size")?, outputs: crate::to_u32(self.outputs, "outputs")?, - subsidy: Amount::from_sat(self.subsidy), + subsidy: Amount::from_sat(self.subsidy).expect("TODO: Handle this error"), segwit_total_size: crate::to_u32(self.segwit_total_size, "segwit_total_size")?, segwit_total_weight, segwit_txs: crate::to_u32(self.segwit_txs, "segwit_txs")?, time: crate::to_u32(self.time, "time")?, - total_out: Amount::from_sat(self.total_out), + total_out: Amount::from_sat(self.total_out).expect("TODO: Handle this error"), total_size: crate::to_u32(self.total_size, "total_size")?, total_weight, - total_fee: Amount::from_sat(self.total_fee), + total_fee: Amount::from_sat(self.total_fee).expect("TODO: Handle this error"), txs: crate::to_u32(self.txs, "txs")?, utxo_increase: self.utxo_increase, utxo_size_increase: self.utxo_size_increase, @@ -115,7 +115,8 @@ impl ScanTxOutSetUnspent { let txid = self.txid.parse::().map_err(E::Txid)?; let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; Ok(model::ScanTxOutSetUnspent { txid, diff --git a/types/src/v25/blockchain/mod.rs b/types/src/v25/blockchain/mod.rs index 6d1003750..aca38c91e 100644 --- a/types/src/v25/blockchain/mod.rs +++ b/types/src/v25/blockchain/mod.rs @@ -34,7 +34,7 @@ pub struct GetBlockStats { // FIXME: Remember these docs will become silently stale when unit changes in a later version of Core. /// Average feerate (in satoshis per virtual byte). #[serde(rename = "avgfeerate")] - pub average_fee_rate: u64, + pub average_fee_rate: u32, /// Average transaction size. #[serde(rename = "avgtxsize")] pub average_tx_size: i64, @@ -44,7 +44,7 @@ pub struct GetBlockStats { /// Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in satoshis per /// virtual byte). #[serde(rename = "feerate_percentiles")] - pub fee_rate_percentiles: [u64; 5], + pub fee_rate_percentiles: [u32; 5], /// The height of the block. pub height: i64, /// The number of inputs (excluding coinbase). @@ -55,7 +55,7 @@ pub struct GetBlockStats { pub max_fee: u64, /// Maximum feerate (in satoshis per virtual byte). #[serde(rename = "maxfeerate")] - pub max_fee_rate: u64, + pub max_fee_rate: u32, /// Maximum transaction size. #[serde(rename = "maxtxsize")] pub max_tx_size: i64, @@ -73,7 +73,7 @@ pub struct GetBlockStats { pub minimum_fee: u64, /// Minimum feerate (in satoshis per virtual byte). #[serde(rename = "minfeerate")] - pub minimum_fee_rate: u64, + pub minimum_fee_rate: u32, /// Minimum transaction size. #[serde(rename = "mintxsize")] pub minimum_tx_size: i64, diff --git a/types/src/v25/generating/error.rs b/types/src/v25/generating/error.rs index 025a4fa3d..a377319d0 100644 --- a/types/src/v25/generating/error.rs +++ b/types/src/v25/generating/error.rs @@ -11,7 +11,7 @@ use crate::error::write_err; #[derive(Debug)] pub enum GenerateBlockError { /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the `hex` field failed. Hex(encode::FromHexError), } diff --git a/types/src/v25/raw_transactions/error.rs b/types/src/v25/raw_transactions/error.rs index e56120805..57a14df57 100644 --- a/types/src/v25/raw_transactions/error.rs +++ b/types/src/v25/raw_transactions/error.rs @@ -43,9 +43,9 @@ pub enum MempoolAcceptanceError { /// Conversion of a numeric field failed. Numeric(NumericError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `base` fee field failed. Base(ParseAmountError), /// Conversion of the `effective-feerate` field failed. diff --git a/types/src/v25/raw_transactions/into.rs b/types/src/v25/raw_transactions/into.rs index ae58f2d55..849c2273c 100644 --- a/types/src/v25/raw_transactions/into.rs +++ b/types/src/v25/raw_transactions/into.rs @@ -39,8 +39,7 @@ impl MempoolAcceptance { let effective_feerate = s .effective_feerate .map(|f| crate::btc_per_kb(f).map_err(E::Feerate)) - .transpose()? - .flatten(); + .transpose()?; Ok::<_, MempoolAcceptanceError>(model::MempoolAcceptanceFees { base: Amount::from_btc(s.base).map_err(E::Base)?, diff --git a/types/src/v26/blockchain/error.rs b/types/src/v26/blockchain/error.rs index b5b9f9450..09fde2335 100644 --- a/types/src/v26/blockchain/error.rs +++ b/types/src/v26/blockchain/error.rs @@ -11,9 +11,9 @@ use crate::NumericError; #[derive(Debug)] pub enum GetChainStatesError { /// Conversion of the `best_block_hash` field failed. - BestBlockHash(hex::HexToArrayError), + BestBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `snapshot_block_hash` field failed. - SnapshotBlockHash(hex::HexToArrayError), + SnapshotBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of numeric type to expected type failed. Numeric(NumericError), } @@ -51,9 +51,9 @@ pub enum DumpTxOutSetError { /// Conversion of the `coins_written` field to Amount failed. CoinsWritten(amount::ParseAmountError), /// Conversion of the `base_hash` field failed. - BaseHash(hex::HexToArrayError), + BaseHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txoutset_hash` field failed. - TxOutSetHash(hex::HexToArrayError), + TxOutSetHash(hex::DecodeFixedLengthBytesError), /// Conversion of numeric type to expected type failed. Numeric(NumericError), } @@ -93,7 +93,7 @@ pub enum GetTxOutSetInfoError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `best_block` field failed. - BestBlock(hex::HexToArrayError), + BestBlock(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `total_amount` field failed. TotalAmount(amount::ParseAmountError), /// Conversion of the `prevout_spent` field failed. @@ -175,7 +175,7 @@ pub enum LoadTxOutSetError { /// Conversion of the `coins_loaded` field to Amount failed. CoinsLoaded(amount::ParseAmountError), /// Conversion of the `tip_hash` field failed. - TipHash(hex::HexToArrayError), + TipHash(hex::DecodeFixedLengthBytesError), /// Conversion of numeric type to expected type failed. Numeric(NumericError), } diff --git a/types/src/v26/mining.rs b/types/src/v26/mining.rs index a72b10456..6c7abde84 100644 --- a/types/src/v26/mining.rs +++ b/types/src/v26/mining.rs @@ -35,7 +35,9 @@ pub struct PrioritisedTransaction { impl GetPrioritisedTransactions { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let mut map = BTreeMap::new(); for (k, v) in self.0.into_iter() { let txid = k.parse::()?; @@ -49,7 +51,7 @@ impl PrioritisedTransaction { /// Converts version specific type to a version nonspecific, more strongly typed type. pub fn into_model(self) -> model::PrioritisedTransaction { model::PrioritisedTransaction { - fee_delta: Amount::from_sat(self.fee_delta as u64), + fee_delta: Amount::from_sat(self.fee_delta as u64).expect("TODO: Handle this error"), in_mempool: self.in_mempool, modified_fee: None, } diff --git a/types/src/v26/raw_transactions/error.rs b/types/src/v26/raw_transactions/error.rs index c090bd488..ff2de9698 100644 --- a/types/src/v26/raw_transactions/error.rs +++ b/types/src/v26/raw_transactions/error.rs @@ -4,7 +4,7 @@ use core::fmt; use bitcoin::amount::ParseAmountError; use bitcoin::consensus::encode; -use bitcoin::hex::HexToArrayError; +use bitcoin::hex::DecodeFixedLengthBytesError; use bitcoin::psbt::PsbtParseError; use crate::error::write_err; @@ -42,11 +42,11 @@ impl std::error::Error for DescriptorProcessPsbtError { #[derive(Debug)] pub enum SubmitPackageError { /// Conversion of key from `tx_results` map failed. - TxResultKey(HexToArrayError), + TxResultKey(DecodeFixedLengthBytesError), /// Conversion of value from `tx_results` map failed. TxResultValue(SubmitPackageTxResultError), /// Conversion of a list item from `replaced_transactions` field failed. - ReplaceTransactions(HexToArrayError), + ReplaceTransactions(DecodeFixedLengthBytesError), } impl fmt::Display for SubmitPackageError { @@ -79,9 +79,9 @@ pub enum SubmitPackageTxResultError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `txid` field failed. - Txid(HexToArrayError), + Txid(DecodeFixedLengthBytesError), /// Conversion of the `other_wtxid` field failed. - OtherWtxid(HexToArrayError), + OtherWtxid(DecodeFixedLengthBytesError), /// Conversion of the `fees` field failed. Fees(SubmitPackageTxResultFeesError), } @@ -122,7 +122,7 @@ pub enum SubmitPackageTxResultFeesError { /// Conversion of the `effective_fee_rate` field failed. EffectiveFeeRate(ParseAmountError), /// Conversion of a list item from `effective_includes` field failed. - EffectiveIncludes(HexToArrayError), + EffectiveIncludes(DecodeFixedLengthBytesError), } impl fmt::Display for SubmitPackageTxResultFeesError { diff --git a/types/src/v26/raw_transactions/into.rs b/types/src/v26/raw_transactions/into.rs index 71c0b1564..582521fa5 100644 --- a/types/src/v26/raw_transactions/into.rs +++ b/types/src/v26/raw_transactions/into.rs @@ -72,8 +72,7 @@ impl SubmitPackageTxResultFees { let effective_fee_rate = self .effective_fee_rate .map(|f| crate::btc_per_kb(f).map_err(E::EffectiveFeeRate)) - .transpose()? - .flatten(); + .transpose()?; let effective_includes = self .effective_includes .iter() diff --git a/types/src/v26/wallet/error.rs b/types/src/v26/wallet/error.rs index 475c1ae87..1e40f53a8 100644 --- a/types/src/v26/wallet/error.rs +++ b/types/src/v26/wallet/error.rs @@ -54,19 +54,19 @@ pub enum GetTransactionError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaced_by_txid` field failed. - ReplacedByTxid(hex::HexToArrayError), + ReplacedByTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaces_txid` field failed. - ReplacesTxid(hex::HexToArrayError), + ReplacesTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `mempool_conflicts` field failed. - MempoolConflicts(hex::HexToArrayError), + MempoolConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `hex` field failed. Tx(encode::FromHexError), /// Conversion of the `details` field failed. @@ -140,7 +140,7 @@ pub enum GetWalletInfoError { /// Conversion of the `pay_tx_fee` field failed. PayTxFee(ParseAmountError), /// Conversion of the `hd_seed_id` field failed. - HdSeedId(hex::HexToArrayError), + HdSeedId(hex::DecodeFixedLengthBytesError), /// Conversion of the `last_processed_block` field failed. LastProcessedBlock(LastProcessedBlockError), } @@ -187,7 +187,7 @@ impl From for GetWalletInfoError { #[derive(Debug)] pub enum LastProcessedBlockError { /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the `height` field failed. Height(NumericError), } diff --git a/types/src/v27/mining.rs b/types/src/v27/mining.rs index 2a10c9813..d333a419e 100644 --- a/types/src/v27/mining.rs +++ b/types/src/v27/mining.rs @@ -37,7 +37,9 @@ pub struct PrioritisedTransaction { impl GetPrioritisedTransactions { /// Converts version specific type to a version nonspecific, more strongly typed type. - pub fn into_model(self) -> Result { + pub fn into_model( + self, + ) -> Result { let mut map = BTreeMap::new(); for (k, v) in self.0.into_iter() { let txid = k.parse::()?; @@ -51,9 +53,11 @@ impl PrioritisedTransaction { /// Converts version specific type to a version nonspecific, more strongly typed type. pub fn into_model(self) -> model::PrioritisedTransaction { model::PrioritisedTransaction { - fee_delta: Amount::from_sat(self.fee_delta as u64), + fee_delta: Amount::from_sat(self.fee_delta as u64).expect("TODO: Handle this error"), in_mempool: self.in_mempool, - modified_fee: self.modified_fee.map(Amount::from_sat), + modified_fee: self + .modified_fee + .map(|fee| Amount::from_sat(fee).expect("TODO: Handle this error")), } } } diff --git a/types/src/v28/blockchain/into.rs b/types/src/v28/blockchain/into.rs index cb0b3ad9e..a6ab47cb4 100644 --- a/types/src/v28/blockchain/into.rs +++ b/types/src/v28/blockchain/into.rs @@ -2,7 +2,7 @@ use alloc::collections::BTreeMap; -use bitcoin::{Amount, BlockHash, Network, ScriptBuf, Txid, Work}; +use bitcoin::{Amount, BlockHash, Network, ScriptPubKeyBuf, Txid, Work}; use super::{ GetBlockchainInfo, GetBlockchainInfoError, ScanTxOutSetError, ScanTxOutSetStart, @@ -81,7 +81,8 @@ impl ScanTxOutSetUnspent { let txid = self.txid.parse::().map_err(E::Txid)?; let amount = Amount::from_btc(self.amount).map_err(E::Amount)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let block_hash = self.block_hash.parse::().map_err(E::BlockHash)?; Ok(model::ScanTxOutSetUnspent { diff --git a/types/src/v28/raw_transactions/error.rs b/types/src/v28/raw_transactions/error.rs index 2bb683af5..42958e5b7 100644 --- a/types/src/v28/raw_transactions/error.rs +++ b/types/src/v28/raw_transactions/error.rs @@ -3,7 +3,7 @@ use core::fmt; use bitcoin::amount::ParseAmountError; -use bitcoin::hex::HexToArrayError; +use bitcoin::hex::DecodeFixedLengthBytesError; use crate::error::write_err; use crate::NumericError; @@ -12,11 +12,11 @@ use crate::NumericError; #[derive(Debug)] pub enum SubmitPackageError { /// Conversion of key from `tx_results` map failed. - TxResultKey(HexToArrayError), + TxResultKey(DecodeFixedLengthBytesError), /// Conversion of value from `tx_results` map failed. TxResultValue(SubmitPackageTxResultError), /// Conversion of a list item from `replaced_transactions` field failed. - ReplaceTransactions(HexToArrayError), + ReplaceTransactions(DecodeFixedLengthBytesError), } impl fmt::Display for SubmitPackageError { @@ -49,9 +49,9 @@ pub enum SubmitPackageTxResultError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the `txid` field failed. - Txid(HexToArrayError), + Txid(DecodeFixedLengthBytesError), /// Conversion of the `other_wtxid` field failed. - OtherWtxid(HexToArrayError), + OtherWtxid(DecodeFixedLengthBytesError), /// Conversion of the `fees` field failed. Fees(SubmitPackageTxResultFeesError), } @@ -92,7 +92,7 @@ pub enum SubmitPackageTxResultFeesError { /// Conversion of the `effective_fee_rate` field failed. EffectiveFeeRate(ParseAmountError), /// Conversion of a list item from `effective_includes` field failed. - EffectiveIncludes(HexToArrayError), + EffectiveIncludes(DecodeFixedLengthBytesError), } impl fmt::Display for SubmitPackageTxResultFeesError { diff --git a/types/src/v28/raw_transactions/into.rs b/types/src/v28/raw_transactions/into.rs index dbab987cd..8b6bc0ae8 100644 --- a/types/src/v28/raw_transactions/into.rs +++ b/types/src/v28/raw_transactions/into.rs @@ -57,8 +57,7 @@ impl SubmitPackageTxResultFees { let effective_fee_rate = self .effective_fee_rate .map(|f| crate::btc_per_kb(f).map_err(E::EffectiveFeeRate)) - .transpose()? - .flatten(); + .transpose()?; let effective_includes = self .effective_includes .unwrap_or_default() diff --git a/types/src/v28/wallet/error.rs b/types/src/v28/wallet/error.rs index 2d0434b4d..0e5917b84 100644 --- a/types/src/v28/wallet/error.rs +++ b/types/src/v28/wallet/error.rs @@ -12,9 +12,9 @@ use crate::NumericError; #[derive(Debug)] pub enum GetHdKeysError { /// Conversion of the `xpub` field failed. - Xpub(bip32::Error), + Xpub(bip32::ParseError), /// Conversion of the `xpriv` field failed. - Xpriv(bip32::Error), + Xpriv(bip32::ParseError), /// Conversion of numeric type to expected type failed. Numeric(NumericError), } @@ -52,7 +52,7 @@ pub enum ListSinceBlockError { /// Conversion of the `removed` field failed. Removed(TransactionItemError), /// Conversion of the `last_block` field failed. - LastBlock(hex::HexToArrayError), + LastBlock(hex::DecodeFixedLengthBytesError), } impl fmt::Display for ListSinceBlockError { @@ -90,17 +90,17 @@ pub enum TransactionItemError { /// Conversion of the `fee` field failed. Fee(ParseAmountError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `wallet_conflicts` field failed. - WalletConflicts(hex::HexToArrayError), + WalletConflicts(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaced_by_txid` field failed. - ReplacedByTxid(hex::HexToArrayError), + ReplacedByTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `replaces_txid` field failed. - ReplacesTxid(hex::HexToArrayError), + ReplacesTxid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TransactionItemError { diff --git a/types/src/v28/wallet/into.rs b/types/src/v28/wallet/into.rs index b74ad2b92..1d80146a5 100644 --- a/types/src/v28/wallet/into.rs +++ b/types/src/v28/wallet/into.rs @@ -2,11 +2,10 @@ use bitcoin::consensus::encode; use bitcoin::hashes::hash160; -use bitcoin::hex::FromHex; use bitcoin::key::PublicKey; use bitcoin::{ - bip32, Address, BlockHash, ScriptBuf, SignedAmount, Transaction, Txid, WitnessProgram, - WitnessVersion, + bip32, Address, BlockHash, RedeemScriptBuf, ScriptPubKeyBuf, SignedAmount, Transaction, Txid, + WitnessProgram, WitnessVersion, }; use super::{ @@ -22,7 +21,8 @@ impl GetAddressInfo { use GetAddressInfoError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -32,7 +32,7 @@ impl GetAddressInfo { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -41,8 +41,10 @@ impl GetAddressInfo { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = self .pubkeys .map(|pubkeys| { @@ -107,7 +109,8 @@ impl GetAddressInfoEmbedded { use GetAddressInfoEmbeddedError as E; let address = self.address.parse::>().map_err(E::Address)?; - let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?; + let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(&self.script_pubkey) + .map_err(E::ScriptPubKey)?; let (witness_version, witness_program) = match (self.witness_version, self.witness_program) { (Some(v), Some(hex)) => { @@ -117,7 +120,7 @@ impl GetAddressInfoEmbedded { let witness_version = WitnessVersion::try_from(v as u8).map_err(E::WitnessVersion)?; - let bytes = Vec::from_hex(&hex).map_err(E::WitnessProgramBytes)?; + let bytes = bitcoin::hex::decode_to_vec(&hex).map_err(E::WitnessProgramBytes)?; let witness_program = WitnessProgram::new(witness_version, &bytes).map_err(E::WitnessProgram)?; @@ -126,8 +129,10 @@ impl GetAddressInfoEmbedded { _ => (None, None), // TODO: Think more if catchall is ok. }; let script = self.script.map(|s| s.into_model()); - let redeem_script = - self.hex.map(|hex| ScriptBuf::from_hex(&hex).map_err(E::Hex)).transpose()?; + let redeem_script = self + .hex + .map(|hex| RedeemScriptBuf::from_hex_no_length_prefix(&hex).map_err(E::Hex)) + .transpose()?; let pubkeys = None; let sigs_required = self.sigs_required.map(|s| crate::to_u32(s, "sigs_required")).transpose()?; @@ -290,7 +295,7 @@ impl TransactionItem { .fee .map(|f| SignedAmount::from_btc(f).map_err(E::Fee)) .transpose()? // optional historically - .unwrap_or_else(|| SignedAmount::from_sat(0)); + .unwrap_or_else(|| SignedAmount::from_sat(0).expect("TODO: Handle this error")); let block_hash = self.block_hash.map(|s| s.parse::().map_err(E::BlockHash)).transpose()?; let block_height = diff --git a/types/src/v29/blockchain/error.rs b/types/src/v29/blockchain/error.rs index 814fee6be..404f6b09d 100644 --- a/types/src/v29/blockchain/error.rs +++ b/types/src/v29/blockchain/error.rs @@ -3,9 +3,9 @@ use core::fmt; use bitcoin::consensus::encode; -use bitcoin::error::UnprefixedHexError; -use bitcoin::hex::HexToBytesError; -use bitcoin::{address, amount, hex, network}; +use bitcoin::hex::DecodeVariableLengthBytesError; +use bitcoin::parse_int::UnprefixedHexError; +use bitcoin::{address, block, amount, hex, network}; use crate::error::write_err; use crate::psbt::{RawTransactionInputError, RawTransactionOutputError}; @@ -18,9 +18,9 @@ pub enum GetBlockVerboseOneError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `merkle_root` field failed. - MerkleRoot(hex::HexToArrayError), + MerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `hex` field failed. Tx(encode::FromHexError), /// Conversion of the transaction `bits` field failed. @@ -30,9 +30,9 @@ pub enum GetBlockVerboseOneError { /// Conversion of the transaction `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of the transaction `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `next_block_hash` field failed. - NextBlockHash(hex::HexToArrayError), + NextBlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetBlockVerboseOneError { @@ -82,9 +82,9 @@ pub enum GetBlockVerboseTwoError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `merkle_root` field failed. - MerkleRoot(hex::HexToArrayError), + MerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `bits` field failed. Bits(UnprefixedHexError), /// Conversion of the `target` field failed. @@ -92,9 +92,9 @@ pub enum GetBlockVerboseTwoError { /// Conversion of the transaction `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of the transaction `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `next_block_hash` field failed. - NextBlockHash(hex::HexToArrayError), + NextBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of a transaction entry failed. Transaction(GetRawTransactionVerboseError), /// Conversion of the transaction `fee` field failed. @@ -151,9 +151,9 @@ pub enum GetBlockVerboseThreeError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of the transaction `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `merkle_root` field failed. - MerkleRoot(hex::HexToArrayError), + MerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `bits` field failed. Bits(UnprefixedHexError), /// Conversion of the `target` field failed. @@ -161,15 +161,15 @@ pub enum GetBlockVerboseThreeError { /// Conversion of the transaction `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of the transaction `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `next_block_hash` field failed. - NextBlockHash(hex::HexToArrayError), + NextBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of one of the transaction inputs failed. Inputs(RawTransactionInputError), /// Conversion of one of the transaction outputs failed. Outputs(RawTransactionOutputError), /// Conversion of the transaction `block_hash` field failed. - TransactionBlockHash(hex::HexToArrayError), + TransactionBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `fee` field failed. Fee(amount::ParseAmountError), /// Conversion of a prevout height failed. @@ -251,11 +251,11 @@ pub enum GetBlockchainInfoError { /// Conversion of the `target` field failed. Target(UnprefixedHexError), /// Conversion of the `best_block_hash` field failed. - BestBlockHash(hex::HexToArrayError), + BestBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of the `script` field failed. - SignetChallenge(hex::HexToBytesError), + SignetChallenge(hex::DecodeVariableLengthBytesError), } impl fmt::Display for GetBlockchainInfoError { @@ -294,17 +294,17 @@ impl From for GetBlockchainInfoError { fn from(e: NumericError) -> Self { Self::Numeric(e) } } -impl From for GetBlockchainInfoError { - fn from(e: HexToBytesError) -> Self { Self::SignetChallenge(e) } +impl From for GetBlockchainInfoError { + fn from(e: DecodeVariableLengthBytesError) -> Self { Self::SignetChallenge(e) } } /// Error when converting a `GetBlockHeader` type into the model type. #[derive(Debug)] pub enum GetBlockHeaderError { /// Conversion of hex data to bytes failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Consensus decoding of bytes to header failed. - Header(encode::Error), + Header(encoding::DecodeError), } impl fmt::Display for GetBlockHeaderError { @@ -332,9 +332,9 @@ pub enum GetBlockHeaderVerboseError { /// Conversion of numeric type to expected type failed. Numeric(NumericError), /// Conversion of `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of `merkle_root` field failed. - MerkleRoot(hex::HexToArrayError), + MerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of `bits` field failed. Bits(UnprefixedHexError), /// Conversion of `target` field failed. @@ -342,9 +342,9 @@ pub enum GetBlockHeaderVerboseError { /// Conversion of `chain_work` field failed. ChainWork(UnprefixedHexError), /// Conversion of `previous_block_hash` field failed. - PreviousBlockHash(hex::HexToArrayError), + PreviousBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of `next_block_hash` field failed. - NextBlockHash(hex::HexToArrayError), + NextBlockHash(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetBlockHeaderVerboseError { @@ -392,13 +392,13 @@ impl From for GetBlockHeaderVerboseError { #[derive(Debug)] pub enum GetChainStatesError { /// Conversion of the `best_block_hash` field failed. - BestBlockHash(hex::HexToArrayError), + BestBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `bits` field failed. Bits(UnprefixedHexError), /// Conversion of the `target` field failed. Target(UnprefixedHexError), /// Conversion of the `snapshot_block_hash` field failed. - SnapshotBlockHash(hex::HexToArrayError), + SnapshotBlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of numeric type to expected type failed. Numeric(NumericError), } @@ -442,17 +442,17 @@ pub enum GetDescriptorActivityError { /// Conversion of numeric type (e.g., height) to expected type failed. Numeric(NumericError), /// Conversion of the `spend_txid` field failed. - SpendTxid(hex::HexToArrayError), + SpendTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `prevout_txid` field failed. - PrevoutTxid(hex::HexToArrayError), + PrevoutTxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the `block_hash` field failed. - BlockHash(hex::HexToArrayError), + BlockHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `amount` field (f64 BTC) failed. Amount(amount::ParseAmountError), /// Conversion of script hex to ScriptBuf failed. - Script(hex::HexToBytesError), + Script(hex::DecodeVariableLengthBytesError), /// Conversion of address string to Address failed. Address(address::ParseError), /// An error occurred during processing of an individual activity entry. @@ -515,16 +515,16 @@ impl From for GetDescriptorActivityError { fn from(e: NumericError) -> Self { Self::Numeric(e) } } -impl From for GetDescriptorActivityError { - fn from(e: hex::HexToArrayError) -> Self { Self::BlockHash(e) } +impl From for GetDescriptorActivityError { + fn from(e: hex::DecodeFixedLengthBytesError) -> Self { Self::BlockHash(e) } } impl From for GetDescriptorActivityError { fn from(e: amount::ParseAmountError) -> Self { Self::Amount(e) } } -impl From for GetDescriptorActivityError { - fn from(e: hex::HexToBytesError) -> Self { Self::Script(e) } +impl From for GetDescriptorActivityError { + fn from(e: hex::DecodeVariableLengthBytesError) -> Self { Self::Script(e) } } impl From for GetDescriptorActivityError { diff --git a/types/src/v29/blockchain/into.rs b/types/src/v29/blockchain/into.rs index e17805030..e9b76c1a4 100644 --- a/types/src/v29/blockchain/into.rs +++ b/types/src/v29/blockchain/into.rs @@ -3,11 +3,9 @@ use alloc::collections::BTreeMap; use core::str::FromStr; -use bitcoin::consensus::encode; -use bitcoin::hashes::hex::FromHex; use bitcoin::{ - absolute, block, hex, transaction, Amount, BlockHash, CompactTarget, Network, ScriptBuf, - Target, Transaction, TxMerkleNode, Txid, Weight, Work, + absolute, block, hex, transaction, Amount, BlockHash, CompactTarget, Network, Target, + Transaction, TxMerkleNode, Txid, Weight, WitnessScriptBuf, Work, }; // TODO: Use explicit imports? @@ -136,10 +134,10 @@ impl GetRawTransactionVerboseWithPrevout { > { use GetBlockVerboseThreeError as E; - let version = transaction::Version::non_standard(self.version); + let version = transaction::Version::maybe_non_standard(self.version); let lock_time = absolute::LockTime::from_consensus(self.lock_time); - let mut input = Vec::with_capacity(self.inputs.len()); + let mut inputs = Vec::with_capacity(self.inputs.len()); let mut prevouts = Vec::with_capacity(self.inputs.len()); for item in self.inputs { let prevout = item @@ -163,17 +161,17 @@ impl GetRawTransactionVerboseWithPrevout { prevouts.push(prevout); let txin = item.input.to_input().map_err(E::Inputs)?; - input.push(txin); + inputs.push(txin); } - let output = self + let outputs = self .outputs .into_iter() .map(|output| output.to_output()) .collect::>() .map_err(E::Outputs)?; - let transaction = Transaction { version, lock_time, input, output }; + let transaction = Transaction { version, lock_time, inputs, outputs }; let block_hash = self .block_hash .map(|s| s.parse::()) @@ -269,8 +267,11 @@ impl GetBlockchainInfo { self.prune_height.map(|h| crate::to_u32(h, "prune_height")).transpose()?; let prune_target_size = self.prune_target_size.map(|h| crate::to_u32(h, "prune_target_size")).transpose()?; - let signet_challenge = - self.signet_challenge.as_ref().map(|s| ScriptBuf::from_hex(s)).transpose()?; + let signet_challenge = self + .signet_challenge + .as_ref() + .map(|s| WitnessScriptBuf::from_hex_no_length_prefix(s)) + .transpose()?; Ok(model::GetBlockchainInfo { chain, @@ -302,8 +303,8 @@ impl GetBlockHeader { pub fn into_model(self) -> Result { use GetBlockHeaderError as E; - let v = Vec::from_hex(&self.0).map_err(E::Hex)?; - let header = encode::deserialize::(&v).map_err(E::Header)?; + let v = bitcoin::hex::decode_to_vec(&self.0).map_err(E::Hex)?; + let header = encoding::decode_from_slice::(&v).map_err(E::Header)?; Ok(model::GetBlockHeader(header)) } @@ -354,7 +355,7 @@ impl GetBlockHeaderVerbose { } /// Converts json straight to a `bitcoin::BlockHeader`. - pub fn block_header(self) -> Result { todo!() } + pub fn block_header(self) -> Result { todo!() } } impl GetChainStates { diff --git a/types/src/v29/blockchain/mod.rs b/types/src/v29/blockchain/mod.rs index 28d0b6aa3..f094e9b2e 100644 --- a/types/src/v29/blockchain/mod.rs +++ b/types/src/v29/blockchain/mod.rs @@ -220,7 +220,7 @@ pub struct GetRawTransactionVerboseWithPrevout { /// The transaction's weight (between vsize*4-3 and vsize*4). pub weight: u64, /// The version. - pub version: i32, + pub version: u32, /// The lock time. #[serde(rename = "locktime")] pub lock_time: u32, diff --git a/types/src/v29/hidden/error.rs b/types/src/v29/hidden/error.rs index 14069ddd3..7a6b104b7 100644 --- a/types/src/v29/hidden/error.rs +++ b/types/src/v29/hidden/error.rs @@ -2,8 +2,8 @@ use core::fmt; -use bitcoin::consensus::encode; use bitcoin::hex; +use bitcoin::primitives::transaction::TransactionDecoderError; use crate::error::write_err; @@ -11,7 +11,7 @@ use crate::error::write_err; #[derive(Debug)] pub enum GetOrphanTxsError { /// Conversion of the `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetOrphanTxsError { @@ -35,9 +35,9 @@ impl std::error::Error for GetOrphanTxsError { #[derive(Debug)] pub enum GetOrphanTxsVerboseOneEntryError { /// Conversion of the transaction `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), } impl fmt::Display for GetOrphanTxsVerboseOneEntryError { @@ -63,13 +63,13 @@ impl std::error::Error for GetOrphanTxsVerboseOneEntryError { #[derive(Debug)] pub enum GetOrphanTxsVerboseTwoEntryError { /// Conversion of the transaction `txid` field failed. - Txid(hex::HexToArrayError), + Txid(hex::DecodeFixedLengthBytesError), /// Conversion of the transaction `wtxid` field failed. - Wtxid(hex::HexToArrayError), + Wtxid(hex::DecodeFixedLengthBytesError), /// Conversion of the `hex` field to bytes failed. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Consensus decoding of the `hex` bytes to `transaction` failed. - Transaction(encode::Error), + Transaction(encoding::DecodeError), } impl fmt::Display for GetOrphanTxsVerboseTwoEntryError { diff --git a/types/src/v29/hidden/into.rs b/types/src/v29/hidden/into.rs index c3d2f1723..68e8f3364 100644 --- a/types/src/v29/hidden/into.rs +++ b/types/src/v29/hidden/into.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::consensus::encode; -use bitcoin::hashes::hex::FromHex; use bitcoin::{Transaction, Txid, Wtxid}; use super::{ @@ -58,8 +56,8 @@ impl GetOrphanTxsVerboseTwoEntry { let txid = self.txid.parse::().map_err(E::Txid)?; let wtxid = self.wtxid.parse::().map_err(E::Wtxid)?; - let v = Vec::from_hex(&self.hex).map_err(E::Hex)?; - let transaction = encode::deserialize::(&v).map_err(E::Transaction)?; + let v = bitcoin::hex::decode_to_vec(&self.hex).map_err(E::Hex)?; + let transaction = encoding::decode_from_slice::(&v).map_err(E::Transaction)?; Ok(model::GetOrphanTxsVerboseTwoEntry { txid, diff --git a/types/src/v29/mining/error.rs b/types/src/v29/mining/error.rs index d13b691b0..ea77359ba 100644 --- a/types/src/v29/mining/error.rs +++ b/types/src/v29/mining/error.rs @@ -2,7 +2,7 @@ use core::fmt; -use bitcoin::error::UnprefixedHexError; +use bitcoin::parse_int::UnprefixedHexError; use crate::error::write_err; diff --git a/types/src/v29/raw_transactions/into.rs b/types/src/v29/raw_transactions/into.rs index 1d35903d3..45c76a743 100644 --- a/types/src/v29/raw_transactions/into.rs +++ b/types/src/v29/raw_transactions/into.rs @@ -39,8 +39,7 @@ impl MempoolAcceptance { let effective_feerate = s .effective_feerate .map(|f| crate::btc_per_kb(f).map_err(E::Feerate)) - .transpose()? - .flatten(); + .transpose()?; Ok::<_, MempoolAcceptanceError>(model::MempoolAcceptanceFees { base: Amount::from_btc(s.base).map_err(E::Base)?, diff --git a/types/src/v30/blockchain/into.rs b/types/src/v30/blockchain/into.rs index 69fe7b3c4..f7e7ba159 100644 --- a/types/src/v30/blockchain/into.rs +++ b/types/src/v30/blockchain/into.rs @@ -24,7 +24,7 @@ impl GetMempoolInfo { max_mempool, mempool_min_fee, min_relay_tx_fee, - incremental_relay_fee, + incremental_relay_fee: Some(incremental_relay_fee), unbroadcast_count, full_rbf: Some(self.full_rbf), permit_bare_multisig: Some(self.permit_bare_multisig), diff --git a/types/src/v30/hidden/error.rs b/types/src/v30/hidden/error.rs new file mode 100644 index 000000000..a304855f2 --- /dev/null +++ b/types/src/v30/hidden/error.rs @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: CC0-1.0 + +use core::fmt; + +use bitcoin::hex; + +use crate::error::write_err; + +/// Error when converting a `GetOrphanTxsVerboseOneEntry` type into the model type. +#[derive(Debug)] +pub enum GetOrphanTxsVerboseOneEntryError { + /// Conversion of the transaction `txid` field failed. + Txid(hex::DecodeFixedLengthBytesError), + /// Conversion of the transaction `wtxid` field failed. + Wtxid(hex::DecodeFixedLengthBytesError), +} + +impl fmt::Display for GetOrphanTxsVerboseOneEntryError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Txid(ref e) => write_err!(f, "conversion of the `txid` field failed"; e), + Self::Wtxid(ref e) => write_err!(f, "conversion of the `wtxid` field failed"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for GetOrphanTxsVerboseOneEntryError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + Self::Txid(ref e) => Some(e), + Self::Wtxid(ref e) => Some(e), + } + } +} + +/// Error when converting a `GetOrphanTxsVerboseTwoEntry` type into the model type. +#[derive(Debug)] +pub enum GetOrphanTxsVerboseTwoEntryError { + /// Conversion of the transaction `txid` field failed. + Txid(hex::DecodeFixedLengthBytesError), + /// Conversion of the transaction `wtxid` field failed. + Wtxid(hex::DecodeFixedLengthBytesError), + /// Conversion of hex data to bytes failed. + Hex(hex::DecodeVariableLengthBytesError), + /// Consensus decoding of `hex` to transaction failed. + Consensus(bitcoin::primitives::transaction::TransactionDecoderError), +} + +impl fmt::Display for GetOrphanTxsVerboseTwoEntryError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Self::Txid(ref e) => write_err!(f, "conversion of the `txid` field failed"; e), + Self::Wtxid(ref e) => write_err!(f, "conversion of the `wtxid` field failed"; e), + Self::Hex(ref e) => write_err!(f, "conversion of hex data to bytes failed"; e), + Self::Consensus(ref e) => + write_err!(f, "consensus decoding of `hex` to transaction failed"; e), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for GetOrphanTxsVerboseTwoEntryError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + Self::Txid(ref e) => Some(e), + Self::Wtxid(ref e) => Some(e), + Self::Hex(ref e) => Some(e), + Self::Consensus(ref e) => Some(e), + } + } +} diff --git a/types/src/v30/hidden/into.rs b/types/src/v30/hidden/into.rs index a4580f761..e8cf58583 100644 --- a/types/src/v30/hidden/into.rs +++ b/types/src/v30/hidden/into.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: CC0-1.0 -use bitcoin::consensus::encode; -use bitcoin::hashes::hex::FromHex; use bitcoin::{Transaction, Txid, Wtxid}; use super::{ @@ -58,8 +56,8 @@ impl GetOrphanTxsVerboseTwoEntry { let txid = self.txid.parse::().map_err(E::Txid)?; let wtxid = self.wtxid.parse::().map_err(E::Wtxid)?; - let v = Vec::from_hex(&self.hex).map_err(E::Hex)?; - let transaction = encode::deserialize::(&v).map_err(E::Transaction)?; + let v = bitcoin::hex::decode_to_vec(&self.hex).map_err(E::Hex)?; + let transaction = encoding::decode_from_slice::(&v).map_err(E::Transaction)?; Ok(model::GetOrphanTxsVerboseTwoEntry { txid, diff --git a/types/src/v30/mining/error.rs b/types/src/v30/mining/error.rs index e51711e30..ff283a3c4 100644 --- a/types/src/v30/mining/error.rs +++ b/types/src/v30/mining/error.rs @@ -3,7 +3,7 @@ use core::fmt; use bitcoin::amount::ParseAmountError; -use bitcoin::error::UnprefixedHexError; +use bitcoin::parse_int::UnprefixedHexError; use super::NextBlockInfoError; use crate::error::write_err; diff --git a/types/src/v30/mining/into.rs b/types/src/v30/mining/into.rs index 2de3efac3..ece478e03 100644 --- a/types/src/v30/mining/into.rs +++ b/types/src/v30/mining/into.rs @@ -27,7 +27,7 @@ impl GetMiningInfo { target: Some(target), network_hash_ps: self.network_hash_ps, pooled_tx: self.pooled_tx, - block_min_tx_fee, + block_min_tx_fee: Some(block_min_tx_fee), chain: self.chain, signet_challenge: self.signet_challenge, next: Some(next), diff --git a/types/src/v30/mod.rs b/types/src/v30/mod.rs index 123fabda5..bf78519ca 100644 --- a/types/src/v30/mod.rs +++ b/types/src/v30/mod.rs @@ -275,9 +275,9 @@ pub use crate::{ Bip125Replaceable, Bip32DerivError, BlockTemplateTransaction, BlockTemplateTransactionError, BumpFee, BumpFeeError, ChainTips, ChainTipsError, ChainTipsStatus, CombinePsbt, CombineRawTransaction, ConvertToPsbt, CreateMultisigError, - CreatePsbt, CreateRawTransaction, DecodeRawTransaction, EncryptWallet, EstimateRawFee, - EstimateRawFeeError, EstimateSmartFee, FinalizePsbt, FinalizePsbtError, FundRawTransaction, - FundRawTransactionError, Generate, GenerateToAddress, GetAddedNodeInfo, + CreatePsbt, CreateRawTransaction, DecodeRawTransaction, DumpPrivKey, EncryptWallet, + EstimateRawFee, EstimateRawFeeError, EstimateSmartFee, FinalizePsbt, FinalizePsbtError, + FundRawTransaction, FundRawTransactionError, Generate, GenerateToAddress, GetAddedNodeInfo, GetAddressInfoEmbeddedError, GetAddressesByLabel, GetBalance, GetBestBlockHash, GetBlockCount, GetBlockHash, GetBlockStatsError, GetBlockTemplate, GetBlockTemplateError, GetBlockVerboseZero, GetChainTips, GetChainTxStatsError, GetConnectionCount, GetDifficulty, diff --git a/types/src/v30/raw_transactions/error.rs b/types/src/v30/raw_transactions/error.rs index 87e7dd333..00a95a8a5 100644 --- a/types/src/v30/raw_transactions/error.rs +++ b/types/src/v30/raw_transactions/error.rs @@ -3,8 +3,10 @@ use core::fmt; use bitcoin::amount::ParseAmountError; -use bitcoin::taproot::{IncompleteBuilderError, TaprootBuilderError, TaprootError}; -use bitcoin::{bip32, hex, secp256k1, sighash}; +use bitcoin::taproot::{ + IncompleteBuilderError, InvalidTaprootLeafVersionError, TaprootBuilderError, TaprootError, +}; +use bitcoin::{bip32, hex, key, sighash}; use super::{Bip32DerivError, PartialSignatureError, RawTransactionError, WitnessUtxoError}; use crate::error::write_err; @@ -17,9 +19,9 @@ pub enum DecodePsbtError { /// Conversion of the `global_xpubs` field failed. GlobalXpubs(GlobalXpubError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of one the map items in the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), /// Conversion of one of the PSBT inputs failed. Inputs(PsbtInputError), /// Conversion of one of the PSBT outputs failed. @@ -66,11 +68,11 @@ impl std::error::Error for DecodePsbtError { #[derive(Debug)] pub enum GlobalXpubError { /// Conversion of the `xpub` field failed. - Xpub(bip32::Error), + Xpub(bip32::ParseError), /// Conversion of the `master_fingerprint` field failed. - MasterFingerprint(hex::HexToArrayError), + MasterFingerprint(hex::DecodeFixedLengthBytesError), /// Conversion of the `path` field failed. - Path(bip32::Error), + Path(bip32::ParseChildNumberError), } impl fmt::Display for GlobalXpubError { @@ -107,31 +109,31 @@ pub enum PsbtInputError { /// Conversion of the `sighash` field failed. Sighash(sighash::SighashTypeParseError), /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `final_script_sig` field failed. - FinalScriptSig(hex::HexToBytesError), + FinalScriptSig(hex::DecodeVariableLengthBytesError), /// Conversion of the `final_script_witness` field failed. - FinalScriptWitness(hex::HexToBytesError), + FinalScriptWitness(hex::DecodeVariableLengthBytesError), /// Conversion of the `ripemd160` hash failed. - Ripemd160(hex::HexToArrayError), + Ripemd160(hex::DecodeFixedLengthBytesError), /// Conversion of the `ripemd160` preimage failed. - Ripemd160Preimage(hex::HexToBytesError), + Ripemd160Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `sha256` hash failed. - Sha256(hex::HexToArrayError), + Sha256(hex::DecodeFixedLengthBytesError), /// Conversion of the `sha256` preimage failed. - Sha256Preimage(hex::HexToBytesError), + Sha256Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `hash160` hash failed. - Hash160(hex::HexToArrayError), + Hash160(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash160` preimage failed. - Hash160Preimage(hex::HexToBytesError), + Hash160Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `hash256` hash failed. - Hash256(hex::HexToArrayError), + Hash256(hex::DecodeFixedLengthBytesError), /// Conversion of the `hash256` preimage failed. - Hash256Preimage(hex::HexToBytesError), + Hash256Preimage(hex::DecodeVariableLengthBytesError), /// Conversion of the `taproot_key_path_sig` field failed. TaprootKeyPathSig(super::taproot::Error), /// Conversion of the `taproot_script_path_sigs` field failed. @@ -141,13 +143,13 @@ pub enum PsbtInputError { /// Conversion of the `taproot_bip32_derives` field failed. TaprootBip32Derivs(TaprootBip32DerivsError), /// Conversion of the `taproot_internal_key` field failed. - TaprootInternalKey(secp256k1::Error), + TaprootInternalKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `taproot_merkle_root` field failed. - TaprootMerkleRoot(hex::HexToArrayError), + TaprootMerkleRoot(hex::DecodeFixedLengthBytesError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtInputError { @@ -238,21 +240,21 @@ impl std::error::Error for PsbtInputError { #[derive(Debug)] pub enum PsbtOutputError { /// Conversion of the `redeem_script` field failed. - RedeemScript(hex::HexToBytesError), + RedeemScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `witness_script` field failed. - WitnessScript(hex::HexToBytesError), + WitnessScript(hex::DecodeVariableLengthBytesError), /// Conversion of the `bip32_derivs` field failed. Bip32Derivs(Bip32DerivError), /// Conversion of the `taproot_internal_key` field failed. - TaprootInternalKey(secp256k1::Error), + TaprootInternalKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `taproot_tree` field failed. TaprootTree(TaprootLeafError), /// Conversion of the `taproot_bip32_derives` field failed. TaprootBip32Derivs(TaprootBip32DerivsError), /// Conversion of the `proprietary` field failed. - Proprietary(hex::HexToBytesError), + Proprietary(hex::DecodeVariableLengthBytesError), /// Conversion of the `unknown` field failed. - Unknown(hex::HexToBytesError), + Unknown(hex::DecodeVariableLengthBytesError), } impl fmt::Display for PsbtOutputError { @@ -297,9 +299,9 @@ impl std::error::Error for PsbtOutputError { #[derive(Debug)] pub enum TaprootScriptPathSigError { /// Conversion of the `pubkey` field failed. - PubKey(secp256k1::Error), + PubKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `leaf_hash` field failed. - LeafHash(hex::HexToArrayError), + LeafHash(hex::DecodeFixedLengthBytesError), /// Conversion of the `sig` field failed. Sig(super::taproot::Error), } @@ -329,9 +331,9 @@ impl std::error::Error for TaprootScriptPathSigError { #[derive(Debug)] pub enum TaprootScriptError { /// Conversion of the `script` field failed. - Script(hex::HexToBytesError), + Script(hex::DecodeVariableLengthBytesError), /// Conversion of the `leaf_ver` field failed. - LeafVer(TaprootError), + LeafVer(InvalidTaprootLeafVersionError), /// Conversion of the `control_blocks` field failed. ControlBlocks(ControlBlocksError), } @@ -366,7 +368,7 @@ pub enum ControlBlocksError { /// Multiple control blocks returned by Core for this script. Multiple(usize), /// Failed to parse control block hex string. - Parse(hex::HexToBytesError), + Parse(hex::DecodeVariableLengthBytesError), /// Failed to decode parsed bytes. Decode(TaprootError), } @@ -399,13 +401,13 @@ impl std::error::Error for ControlBlocksError { #[derive(Debug)] pub enum TaprootBip32DerivsError { /// Conversion of the `pubkey` field failed. - PubKey(secp256k1::Error), + PubKey(key::ParseXOnlyPublicKeyError), /// Conversion of the `master_fingerprint` field failed. - MasterFingerprint(hex::HexToArrayError), + MasterFingerprint(hex::DecodeFixedLengthBytesError), /// Conversion of the `path` field failed. - Path(bip32::Error), + Path(bip32::ParseChildNumberError), /// Conversion of one of the leaf hashes failed. - LeafHashes(hex::HexToArrayError), + LeafHashes(hex::DecodeFixedLengthBytesError), } impl fmt::Display for TaprootBip32DerivsError { @@ -437,9 +439,9 @@ impl std::error::Error for TaprootBip32DerivsError { #[derive(Debug)] pub enum TaprootLeafError { /// Conversion of the `leaf_ver` field failed. - LeafVer(TaprootError), + LeafVer(InvalidTaprootLeafVersionError), /// Conversion of the `script` field failed. - Script(hex::HexToBytesError), + Script(hex::DecodeVariableLengthBytesError), /// Failed to add leaf to builder. TaprootBuilder(TaprootBuilderError), /// Failed to convert builder into a tap tree. diff --git a/types/src/v30/raw_transactions/into.rs b/types/src/v30/raw_transactions/into.rs index fc3c01563..d56da10e6 100644 --- a/types/src/v30/raw_transactions/into.rs +++ b/types/src/v30/raw_transactions/into.rs @@ -4,12 +4,11 @@ use std::collections::BTreeMap; use bitcoin::bip32::{DerivationPath, Fingerprint, KeySource, Xpub}; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; -use bitcoin::hex::{self, FromHex as _}; use bitcoin::psbt::{self, raw, PsbtSighashType}; use bitcoin::taproot::{ ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder, }; -use bitcoin::{Amount, ScriptBuf, XOnlyPublicKey}; +use bitcoin::{hex, Amount, TapScriptBuf, XOnlyPublicKey}; use super::{ taproot, ControlBlocksError, DecodePsbt, DecodePsbtError, GlobalXpub, GlobalXpubError, @@ -94,18 +93,12 @@ impl Proprietary { /// Converts this proprietary list element to a map entry suitable to use in `bitcoin::Psbt`. pub fn to_key_value_pair( &self, - ) -> Result<(raw::ProprietaryKey, Vec), hex::HexToBytesError> { - // FIXME: Remove cast once rust-bitcoin 0.33 is out. - // - // This is changed to a u64 in the upcoming rust-bitcoin - // release, until then just ignore any additional bits. - let subtype = self.subtype as u8; - - let prefix = Vec::from_hex(&self.identifier)?; - let key = Vec::from_hex(&self.key)?; - let value = Vec::from_hex(&self.value)?; - - Ok((raw::ProprietaryKey { prefix, subtype, key }, value)) + ) -> Result<(raw::ProprietaryKey, Vec), hex::DecodeVariableLengthBytesError> { + let prefix = bitcoin::hex::decode_to_vec(&self.identifier)?; + let key = bitcoin::hex::decode_to_vec(&self.key)?; + let value = bitcoin::hex::decode_to_vec(&self.value)?; + + Ok((raw::ProprietaryKey { prefix, subtype: self.subtype, key }, value)) } } @@ -161,7 +154,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Ripemd160)?; - let preimage = Vec::from_hex(preimage).map_err(E::Ripemd160Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Ripemd160Preimage)?; preimages.insert(hash, preimage); } preimages @@ -173,7 +167,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Sha256)?; - let preimage = Vec::from_hex(preimage).map_err(E::Sha256Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Sha256Preimage)?; preimages.insert(hash, preimage); } preimages @@ -185,7 +180,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Hash160)?; - let preimage = Vec::from_hex(preimage).map_err(E::Hash160Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Hash160Preimage)?; preimages.insert(hash, preimage); } preimages @@ -197,7 +193,8 @@ impl PsbtInput { let mut preimages = BTreeMap::default(); for (hash, preimage) in map.iter() { let hash = hash.parse::().map_err(E::Hash256)?; - let preimage = Vec::from_hex(preimage).map_err(E::Hash256Preimage)?; + let preimage = + bitcoin::hex::decode_to_vec(preimage).map_err(E::Hash256Preimage)?; preimages.insert(hash, preimage); } preimages @@ -257,6 +254,9 @@ impl PsbtInput { .transpose() .map_err(E::TaprootMerkleRoot)?; + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + let proprietary = match self.proprietary { Some(props) => { let mut map = BTreeMap::default(); @@ -294,6 +294,7 @@ impl PsbtInput { tap_key_origins, tap_internal_key, tap_merkle_root, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -342,6 +343,9 @@ impl PsbtOutput { None => BTreeMap::default(), }; + // These field is not used in Core yet as of v30. + let musig2_participant_pubkeys = BTreeMap::default(); + let proprietary = match self.proprietary { Some(props) => { let mut map = BTreeMap::default(); @@ -366,6 +370,7 @@ impl PsbtOutput { tap_internal_key, tap_tree, tap_key_origins, + musig2_participant_pubkeys, proprietary, unknown, }) @@ -392,10 +397,10 @@ impl TaprootScript { /// Converts list element to a map entry suitable to use in `bitcoin::psbt::Input`. pub fn to_key_value_pair( &self, - ) -> Result<(ControlBlock, (ScriptBuf, LeafVersion)), TaprootScriptError> { + ) -> Result<(ControlBlock, (TapScriptBuf, LeafVersion)), TaprootScriptError> { use TaprootScriptError as E; - let script = ScriptBuf::from_hex(&self.script).map_err(E::Script)?; + let script = TapScriptBuf::from_hex_no_length_prefix(&self.script).map_err(E::Script)?; let leaf_version = self.leaf_version as u8; // FIXME: Is this cast ok? let version = LeafVersion::from_consensus(leaf_version).map_err(E::LeafVer)?; @@ -415,7 +420,7 @@ fn control_block(control_blocks: &[String]) -> Result Err(E::Missing), 1 => { - let bytes = Vec::from_hex(&control_blocks[0]).map_err(E::Parse)?; + let bytes = bitcoin::hex::decode_to_vec(&control_blocks[0]).map_err(E::Parse)?; Ok(ControlBlock::decode(&bytes).map_err(E::Decode)?) } n => Err(E::Multiple(n)), @@ -455,7 +460,7 @@ fn build_taproot_tree(leaves: Vec) -> Result Result { use Error as E; - let bytes = Vec::from_hex(sig).map_err(E::Hex)?; + let bytes = bitcoin::hex::decode_to_vec(sig).map_err(E::Hex)?; let (sighash_byte, signature) = bytes.split_last().ok_or(E::EmptySignature)?; Ok(Signature { signature: secp256k1::schnorr::Signature::from_slice(signature) @@ -281,7 +280,7 @@ pub mod taproot { #[non_exhaustive] pub enum Error { /// Hex decoding error. - Hex(hex::HexToBytesError), + Hex(hex::DecodeVariableLengthBytesError), /// Non-standard sighash type. SighashType(InvalidSighashTypeError), /// Signature was empty. diff --git a/types/src/v30/wallet/error.rs b/types/src/v30/wallet/error.rs index 1fc74a432..017ab9d57 100644 --- a/types/src/v30/wallet/error.rs +++ b/types/src/v30/wallet/error.rs @@ -50,7 +50,7 @@ impl From for GetWalletInfoError { #[derive(Debug)] pub enum LastProcessedBlockError { /// Conversion of the `hash` field failed. - Hash(hex::HexToArrayError), + Hash(hex::DecodeFixedLengthBytesError), /// Conversion of the `height` field failed. Height(NumericError), }