diff --git a/bitcoin_client_rs/Cargo.toml b/bitcoin_client_rs/Cargo.toml index 78658c072..d68b72bd3 100644 --- a/bitcoin_client_rs/Cargo.toml +++ b/bitcoin_client_rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ledger_bitcoin_client" -version = "0.3.2" +version = "0.4.0" authors = ["Edouard Paris "] edition = "2018" description = "Ledger Bitcoin application client" @@ -21,8 +21,8 @@ paranoid_client = ["miniscript"] [dependencies] async-trait = { version = "0.1", optional = true } -bitcoin = { version = "0.30", default-features = false, features = ["no-std"] } -miniscript = { version = "10.0", optional = true, default-features = false, features = ["no-std"] } +bitcoin = { version = "0.31", default-features = false, features = ["no-std"] } +miniscript = { version = "11.0", optional = true, default-features = false, features = ["no-std"] } [workspace] members = ["examples/ledger_hwi"] diff --git a/bitcoin_client_rs/examples/ledger_hwi/Cargo.toml b/bitcoin_client_rs/examples/ledger_hwi/Cargo.toml index 1fe45aa0f..2931fed6f 100644 --- a/bitcoin_client_rs/examples/ledger_hwi/Cargo.toml +++ b/bitcoin_client_rs/examples/ledger_hwi/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" clap = { version = "4.0.18", features = ["derive"] } ledger_bitcoin_client = { path = "../.." } async-trait = { version = "0.1"} -bitcoin = { version = "0.30", default-features = false, features = ["no-std"] } +bitcoin = { version = "0.31", default-features = false, features = ["no-std"] } hex = "0.4" base64 = "0.13.0" ledger-apdu = "0.10" diff --git a/bitcoin_client_rs/src/async_client.rs b/bitcoin_client_rs/src/async_client.rs index 0f90ff3ed..f2086f477 100644 --- a/bitcoin_client_rs/src/async_client.rs +++ b/bitcoin_client_rs/src/async_client.rs @@ -5,10 +5,10 @@ use async_trait::async_trait; use bitcoin::{ address, - bip32::{DerivationPath, ExtendedPubKey, Fingerprint}, + bip32::{DerivationPath, Fingerprint, Xpub}, consensus::encode::{deserialize_partial, VarInt}, - psbt::PartiallySignedTransaction as Psbt, secp256k1::ecdsa::Signature, + Psbt, }; #[cfg(feature = "paranoid_client")] @@ -91,7 +91,7 @@ impl BitcoinClient { BitcoinClientError::ClientError("Failed to derive descriptor".to_string()) })? .script_pubkey() - != expected_address.payload.script_pubkey() + != expected_address.payload().script_pubkey() { return Err(BitcoinClientError::InvalidResponse("Invalid address. Please update your Bitcoin app. If the problem persists, report a bug at https://github.com/LedgerHQ/app-bitcoin-new".to_string())); } @@ -161,10 +161,10 @@ impl BitcoinClient { &self, path: &DerivationPath, display: bool, - ) -> Result> { + ) -> Result> { let cmd = command::get_extended_pubkey(path, display); self.make_request(&cmd, None).await.and_then(|data| { - ExtendedPubKey::from_str(&String::from_utf8_lossy(&data)).map_err(|_| { + Xpub::from_str(&String::from_utf8_lossy(&data)).map_err(|_| { BitcoinClientError::UnexpectedResult { command: cmd.ins, data, diff --git a/bitcoin_client_rs/src/client.rs b/bitcoin_client_rs/src/client.rs index eb41f1328..a721e4bc1 100644 --- a/bitcoin_client_rs/src/client.rs +++ b/bitcoin_client_rs/src/client.rs @@ -3,9 +3,9 @@ use core::str::FromStr; use bitcoin::{ address, - bip32::{DerivationPath, ExtendedPubKey, Fingerprint}, + bip32::{DerivationPath, Fingerprint, Xpub}, consensus::encode::{deserialize_partial, VarInt}, - psbt::PartiallySignedTransaction as Psbt, + psbt::Psbt, secp256k1::ecdsa, }; @@ -86,7 +86,7 @@ impl BitcoinClient { BitcoinClientError::ClientError("Failed to derive descriptor".to_string()) })? .script_pubkey() - != expected_address.payload.script_pubkey() + != expected_address.payload().script_pubkey() { return Err(BitcoinClientError::InvalidResponse("Invalid address. Please update your Bitcoin app. If the problem persists, report a bug at https://github.com/LedgerHQ/app-bitcoin-new".to_string())); } @@ -152,10 +152,10 @@ impl BitcoinClient { &self, path: &DerivationPath, display: bool, - ) -> Result> { + ) -> Result> { let cmd = command::get_extended_pubkey(path, display); self.make_request(&cmd, None).and_then(|data| { - ExtendedPubKey::from_str(&String::from_utf8_lossy(&data)).map_err(|_| { + Xpub::from_str(&String::from_utf8_lossy(&data)).map_err(|_| { BitcoinClientError::UnexpectedResult { command: cmd.ins, data, diff --git a/bitcoin_client_rs/src/psbt.rs b/bitcoin_client_rs/src/psbt.rs index eb82fe97d..fabfb250a 100644 --- a/bitcoin_client_rs/src/psbt.rs +++ b/bitcoin_client_rs/src/psbt.rs @@ -110,7 +110,7 @@ pub fn get_v2_global_pairs(psbt: &Psbt) -> Vec { type_value: PSBT_GLOBAL_TX_VERSION, key: vec![], }, - value: (psbt.unsigned_tx.version as u32).to_le_bytes().to_vec(), + value: psbt.unsigned_tx.version.0.to_le_bytes().to_vec(), }); rv.push(raw::Pair { @@ -343,7 +343,7 @@ pub fn get_v2_output_pairs(output: &Output, txout: &TxOut) -> Vec { type_value: PSBT_OUT_AMOUNT, key: vec![], }, - value: txout.value.to_le_bytes().to_vec(), + value: txout.value.to_sat().to_le_bytes().to_vec(), }); rv.push(raw::Pair { @@ -435,8 +435,8 @@ pub enum PartialSignatureError { XOnlyPubKey(secp256k1::Error), PubKey(KeyError), EcdsaSig(ecdsa::Error), - TaprootSig(taproot::Error), - TapLeaf(bitcoin::hashes::Error), + TaprootSig(taproot::SigFromSliceError), + TapLeaf(bitcoin::hashes::FromSliceError), } mod serialize { @@ -623,9 +623,9 @@ mod serialize { // would use check the signature assuming sighash_u32 as `0x01`. ecdsa::Signature::from_slice(bytes).map_err(|e| match e { ecdsa::Error::EmptySignature => Error::InvalidEcdsaSignature(e), - ecdsa::Error::NonStandardSighashType(flag) => Error::NonStandardSighashType(flag), + ecdsa::Error::SighashType(flag) => Error::NonStandardSighashType(flag.0), ecdsa::Error::Secp256k1(..) => Error::InvalidEcdsaSignature(e), - ecdsa::Error::HexEncoding(..) => { + ecdsa::Error::Hex(..) => { unreachable!("Decoding from slice, not hex") } _ => Error::InvalidEcdsaSignature(e), @@ -812,7 +812,7 @@ mod serialize { let capacity = self .script_leaves() .map(|l| { - l.script().len() + VarInt(l.script().len() as u64).len() // script version + l.script().len() + VarInt(l.script().len() as u64).size() // script version + 1 // merkle branch + 1 // leaf version }) diff --git a/bitcoin_client_rs/src/wallet.rs b/bitcoin_client_rs/src/wallet.rs index 6d51fecc5..d7994b890 100644 --- a/bitcoin_client_rs/src/wallet.rs +++ b/bitcoin_client_rs/src/wallet.rs @@ -3,7 +3,7 @@ use core::iter::IntoIterator; use core::str::FromStr; use bitcoin::{ - bip32::{DerivationPath, Error, ExtendedPubKey, Fingerprint, KeySource}, + bip32::{DerivationPath, Error, Fingerprint, KeySource, Xpub}, consensus::encode::{self, VarInt}, hashes::{sha256, Hash, HashEngine}, }; @@ -181,7 +181,7 @@ pub enum WalletError { #[derive(PartialEq, Eq)] pub struct WalletPubKey { - pub inner: ExtendedPubKey, + pub inner: Xpub, pub source: Option, /// Used by Version V1 @@ -189,8 +189,8 @@ pub struct WalletPubKey { pub multipath: Option, } -impl From for WalletPubKey { - fn from(inner: ExtendedPubKey) -> Self { +impl From for WalletPubKey { + fn from(inner: Xpub) -> Self { Self { inner, source: None, @@ -199,8 +199,8 @@ impl From for WalletPubKey { } } -impl From<(KeySource, ExtendedPubKey)> for WalletPubKey { - fn from(source_xpub: (KeySource, ExtendedPubKey)) -> Self { +impl From<(KeySource, Xpub)> for WalletPubKey { + fn from(source_xpub: (KeySource, Xpub)) -> Self { Self { inner: source_xpub.1, source: Some(source_xpub.0), @@ -209,8 +209,8 @@ impl From<(KeySource, ExtendedPubKey)> for WalletPubKey { } } -impl From<(KeySource, ExtendedPubKey, String)> for WalletPubKey { - fn from(source_xpub: (KeySource, ExtendedPubKey, String)) -> Self { +impl From<(KeySource, Xpub, String)> for WalletPubKey { + fn from(source_xpub: (KeySource, Xpub, String)) -> Self { Self { inner: source_xpub.1, source: Some(source_xpub.0), @@ -223,7 +223,7 @@ impl FromStr for WalletPubKey { type Err = Error; fn from_str(s: &str) -> Result { - if let Ok(key) = ExtendedPubKey::from_str(s) { + if let Ok(key) = Xpub::from_str(s) { Ok(WalletPubKey { inner: key, source: None, @@ -248,7 +248,7 @@ impl FromStr for WalletPubKey { (xpub_str, None) }; Ok(WalletPubKey { - inner: ExtendedPubKey::from_str(xpub_str)?, + inner: Xpub::from_str(xpub_str)?, source: Some((fingerprint, derivation_path)), multipath, }) @@ -296,7 +296,7 @@ mod tests { Fingerprint::from_str("5c9e228d").unwrap() ); assert_eq!(key.source.as_ref().unwrap().1, DerivationPath::master()); - assert_eq!(key.inner, ExtendedPubKey::from_str("tpubDEGquuorgFNb8bjh5kNZQMPtABJzoWwNm78FUmeoPkfRtoPF7JLrtoZeT3J3ybq1HmC3Rn1Q8wFQ8J5usanzups5rj7PJoQLNyvq8QbJruW").unwrap()); + assert_eq!(key.inner, Xpub::from_str("tpubDEGquuorgFNb8bjh5kNZQMPtABJzoWwNm78FUmeoPkfRtoPF7JLrtoZeT3J3ybq1HmC3Rn1Q8wFQ8J5usanzups5rj7PJoQLNyvq8QbJruW").unwrap()); assert_eq!(key.multipath, Some("/**".to_string())); } @@ -311,7 +311,7 @@ mod tests { key.source.as_ref().unwrap().1, DerivationPath::from_str("m/48'/1'/0'/0'").unwrap() ); - assert_eq!(key.inner, ExtendedPubKey::from_str("tpubDEGquuorgFNb8bjh5kNZQMPtABJzoWwNm78FUmeoPkfRtoPF7JLrtoZeT3J3ybq1HmC3Rn1Q8wFQ8J5usanzups5rj7PJoQLNyvq8QbJruW").unwrap()); + assert_eq!(key.inner, Xpub::from_str("tpubDEGquuorgFNb8bjh5kNZQMPtABJzoWwNm78FUmeoPkfRtoPF7JLrtoZeT3J3ybq1HmC3Rn1Q8wFQ8J5usanzups5rj7PJoQLNyvq8QbJruW").unwrap()); assert_eq!(key.multipath, Some("/**".to_string())); }