version = "3.0.0"
dependencies = [
"assert_cmd",
- "bdk_bip322",
"bdk_bitcoind_rpc",
"bdk_electrum",
"bdk_esplora",
"bdk_redb",
"bdk_sp",
"bdk_testenv",
- "bdk_wallet 3.1.0",
+ "bdk_wallet",
"bitcoin-payment-instructions",
"clap",
"clap_complete",
"url",
]
-[[package]]
-name = "bdk_bip322"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "262ee5f0c1056400b354391cabc541cb732c10488679de6389641e37f7e6c698"
-dependencies = [
- "bdk_wallet 2.4.0",
- "bitcoin",
-]
-
[[package]]
name = "bdk_bitcoind_rpc"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346c1d502ee4613cf2201db9c3b93a2317772d8eaa372114f34bf5f374be94fd"
dependencies = [
- "bdk_wallet 3.1.0",
+ "bdk_wallet",
"bip157",
]
checksum = "69ac8b88c9594c615fcb5b763e7afa16937e94f7a7f5ca334bf59a7fee69fea1"
dependencies = [
"bdk_chain",
- "bdk_wallet 3.1.0",
+ "bdk_wallet",
"ciborium",
"redb",
"thiserror 2.0.18",
"electrsd",
]
-[[package]]
-name = "bdk_wallet"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c99821af39c7df004bd411ece2ef22d9fba5a631b4489f3d9a0ac0d19637e2d0"
-dependencies = [
- "bdk_chain",
- "bitcoin",
- "miniscript",
- "rand_core 0.6.4",
- "serde",
- "serde_json",
-]
-
[[package]]
name = "bdk_wallet"
version = "3.1.0"
payjoin = { version = "0.25.0", features = ["v1", "v2", "io", "_test-utils"], optional = true}
reqwest = { version = "0.13.2", default-features = false, features = ["rustls"], optional = true }
url = { version = "2.5.8", optional = true }
-bdk_bip322 = { version = "0.1.0", optional = true }
+# bdk_bip322 = { version = "0.1.0", optional = true }
bitcoin-payment-instructions = { version = "0.7.0", optional = true}
[features]
# Internal features
_payjoin-dependencies = ["payjoin", "reqwest", "url", "sqlite"]
-bip322 = ["bdk_bip322"]
+# bip322 = ["bdk_bip322"]
# Use this to consensus verify transactions at sync time
verify = []
//! All subcommands are defined in the below enums.
#![allow(clippy::large_enum_variant)]
-#[cfg(feature = "bip322")]
-use crate::handlers::offline::{SignMessageCommand, VerifyMessageCommand};
+// #[cfg(feature = "bip322")]
+// use crate::handlers::offline::{SignMessageCommand, VerifyMessageCommand};
use crate::handlers::{
config::{ListWalletsCommand, SaveConfigCommand},
descriptor::DescriptorCommand,
/// Combines multiple PSBTs into one.
CombinePsbt(CombinePsbtCommand),
/// Sign a message using BIP322
- #[cfg(feature = "bip322")]
- SignMessage(SignMessageCommand),
+ // #[cfg(feature = "bip322")]
+ // SignMessage(SignMessageCommand),
/// Verify a BIP322 signature
- #[cfg(feature = "bip322")]
- VerifyMessage(VerifyMessageCommand),
+ // #[cfg(feature = "bip322")]
+ // VerifyMessage(VerifyMessageCommand),
/// Lock UTXO(s) so they're excluded from coin selection.
LockUtxo(LockUtxoCommand),
/// Unlock previously locked UTXO(s).
#[cfg(feature = "payjoin")]
#[error("Payjoin database error: {0}")]
PayjoinDb(#[from] crate::handlers::payjoin::db::Error),
-
- #[cfg(feature = "bip322")]
- #[error("BIP-322 error: {0}")]
- Bip322Error(#[from] bdk_bip322::error::Error),
+ // #[cfg(feature = "bip322")]
+ // #[error("BIP-322 error: {0}")]
+ // Bip322Error(#[from] bdk_bip322::error::Error),
}
impl From<ExtractTxError> for BDKCliError {
tx_builder.set_exact_sequence(Sequence::MAX);
}
if self.offline_signer {
- tx_builder.include_output_redeem_witness_script();
+ tx_builder.add_global_xpubs();
}
if let Some(fee_rate) = self.fee_rate
&& let Some(fee_rate) = FeeRate::from_sat_per_vb(fee_rate as u64)
bdk_wallet::keys::{DescriptorPublicKey, DescriptorSecretKey, SinglePubKey},
std::collections::HashMap,
};
-#[cfg(feature = "bip322")]
-use {
- crate::utils::parse_signature_format,
- crate::utils::types::MessageResult,
- bdk_bip322::{BIP322, MessageProof},
-};
+// #[cfg(feature = "bip322")]
+// use {
+// crate::utils::parse_signature_format,
+// crate::utils::types::MessageResult,
+// bdk_bip322::{BIP322, MessageProof},
+// };
impl OfflineWalletSubCommand {
pub fn execute(&self, ctx: &mut AppContext<OfflineOperations<'_>>) -> Result<(), Error> {
Self::CombinePsbt(combine_psbt_command) => combine_psbt_command
.execute(ctx)?
.write_out(std::io::stdout()),
- #[cfg(feature = "bip322")]
- Self::SignMessage(sign_message_command) => sign_message_command
- .execute(ctx)?
- .write_out(std::io::stdout()),
- #[cfg(feature = "bip322")]
- Self::VerifyMessage(verify_message_command) => verify_message_command
- .execute(ctx)?
- .write_out(std::io::stdout()),
+ // #[cfg(feature = "bip322")]
+ // Self::SignMessage(sign_message_command) => sign_message_command
+ // .execute(ctx)?
+ // .write_out(std::io::stdout()),
+ // #[cfg(feature = "bip322")]
+ // Self::VerifyMessage(verify_message_command) => verify_message_command
+ // .execute(ctx)?
+ // .write_out(std::io::stdout()),
Self::LockUtxo(lock_utxo) => lock_utxo.execute(ctx)?.write_out(std::io::stdout()),
Self::UnlockUtxo(unlock_utxo) => unlock_utxo.execute(ctx)?.write_out(std::io::stdout()),
Self::LockedUtxos(locked_utxos) => {
}
}
+/**
#[cfg(feature = "bip322")]
#[derive(Debug, Parser, Clone, PartialEq)]
pub struct SignMessageCommand {
})
}
}
+**/
#[derive(Parser, Debug, Clone, PartialEq)]
pub struct LockUtxoCommand {
use crate::{commands::WalletOpts, config::WalletConfig, error::BDKCliError as Error};
-#[cfg(feature = "bip322")]
-use bdk_bip322::SignatureFormat;
+// #[cfg(feature = "bip322")]
+// use bdk_bip322::SignatureFormat;
#[cfg(feature = "cbf")]
use bdk_kyoto::{Info, Receiver, UnboundedReceiver, Warning};
#[cfg(feature = "silent-payments")]
feature = "cbf",
feature = "rpc"
))]
-use bdk_wallet::{bitcoin::Psbt, event::WalletEvent};
+use bdk_wallet::{WalletEvent, bitcoin::Psbt};
use crate::commands::OfflineWalletSubCommand;
use std::{
Ok((key, value))
}
-/// Function to parse the signature format from a string
-#[cfg(feature = "bip322")]
-pub(crate) fn parse_signature_format(format_str: &str) -> Result<SignatureFormat, Error> {
- match format_str.to_lowercase().as_str() {
- "legacy" => Ok(SignatureFormat::Legacy),
- "simple" => Ok(SignatureFormat::Simple),
- "full" => Ok(SignatureFormat::Full),
- "fullproofoffunds" => Ok(SignatureFormat::FullProofOfFunds),
- _ => Err(Error::Generic(
- "Invalid signature format. Use 'legacy', 'simple', 'full', or 'fullproofoffunds'"
- .to_string(),
- )),
- }
-}
+// /// Function to parse the signature format from a string
+// #[cfg(feature = "bip322")]
+// pub(crate) fn parse_signature_format(format_str: &str) -> Result<SignatureFormat, Error> {
+// match format_str.to_lowercase().as_str() {
+// "legacy" => Ok(SignatureFormat::Legacy),
+// "simple" => Ok(SignatureFormat::Simple),
+// "full" => Ok(SignatureFormat::Full),
+// "fullproofoffunds" => Ok(SignatureFormat::FullProofOfFunds),
+// _ => Err(Error::Generic(
+// "Invalid signature format. Use 'legacy', 'simple', 'full', or 'fullproofoffunds'"
+// .to_string(),
+// )),
+// }
+// }
pub fn command_requires_db(command: &OfflineWalletSubCommand) -> bool {
match command {
| OfflineWalletSubCommand::FinalizePsbt(_)
| OfflineWalletSubCommand::CombinePsbt(_) => false,
- #[cfg(feature = "bip322")]
- OfflineWalletSubCommand::SignMessage(_) => true,
+ // #[cfg(feature = "bip322")]
+ // OfflineWalletSubCommand::SignMessage(_) => true,
- #[cfg(feature = "bip322")]
- OfflineWalletSubCommand::VerifyMessage(_) => true,
+ // #[cfg(feature = "bip322")]
+ // OfflineWalletSubCommand::VerifyMessage(_) => true,
#[cfg(feature = "silent-payments")]
OfflineWalletSubCommand::CreateSpTx(_) => true,
#[cfg(feature = "dns_payment")]
pub internal: T,
}
-#[cfg(feature = "bip322")]
-#[derive(Serialize, Debug, Default)]
-pub struct MessageResult {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub proof: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub valid: Option<bool>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub proven_amount: Option<u64>,
-}
+// #[cfg(feature = "bip322")]
+// #[derive(Serialize, Debug, Default)]
+// pub struct MessageResult {
+// #[serde(skip_serializing_if = "Option::is_none")]
+// pub proof: Option<String>,
+
+// #[serde(skip_serializing_if = "Option::is_none")]
+// pub valid: Option<bool>,
+
+// #[serde(skip_serializing_if = "Option::is_none")]
+// pub proven_amount: Option<u64>,
+// }
#[derive(Serialize, Debug)]
pub struct StatusResult {
.failure()
.stderr(predicate::str::contains("Invalid"));
}
-
- #[cfg(feature = "bip322")]
- #[test]
- fn test_sign_message_and_verify_message() {
- let (cli, mut cmd_init) = setup_wallet_config();
- cmd_init.assert().success();
-
- let message = "bdk-cli integration test";
-
- // Reveal exactly one address and reuse it for both sign and verify.
- let addr_output = cli
- .wallet_cmd(&["--wallet", WALLET_NAME, "new_address"])
- .output()
- .expect("Failed to generate address");
- assert!(
- addr_output.status.success(),
- "new_address failed: {}",
- String::from_utf8_lossy(&addr_output.stderr)
- );
- let addr_json: Value = serde_json::from_slice(&addr_output.stdout).unwrap();
- let address = addr_json["address"]
- .as_str()
- .expect("missing address")
- .to_string();
- println!("DEBUG signing address: {address}");
-
- // Sign (default signature_type = "simple").
- let sign_output = cli
- .wallet_cmd(&[
+ /**
+ #[cfg(feature = "bip322")]
+ #[test]
+ fn test_sign_message_and_verify_message() {
+ let (cli, mut cmd_init) = setup_wallet_config();
+ cmd_init.assert().success();
+
+ let message = "bdk-cli integration test";
+
+ // Reveal exactly one address and reuse it for both sign and verify.
+ let addr_output = cli
+ .wallet_cmd(&["--wallet", WALLET_NAME, "new_address"])
+ .output()
+ .expect("Failed to generate address");
+ assert!(
+ addr_output.status.success(),
+ "new_address failed: {}",
+ String::from_utf8_lossy(&addr_output.stderr)
+ );
+ let addr_json: Value = serde_json::from_slice(&addr_output.stdout).unwrap();
+ let address = addr_json["address"]
+ .as_str()
+ .expect("missing address")
+ .to_string();
+ println!("DEBUG signing address: {address}");
+
+ // Sign (default signature_type = "simple").
+ let sign_output = cli
+ .wallet_cmd(&[
+ "--wallet",
+ WALLET_NAME,
+ "sign_message",
+ "--message",
+ message,
+ "--address",
+ &address,
+ ])
+ .output()
+ .expect("Failed to sign message");
+ assert!(
+ sign_output.status.success(),
+ "sign_message failed: {}",
+ String::from_utf8_lossy(&sign_output.stderr)
+ );
+ let sign_json: Value = serde_json::from_slice(&sign_output.stdout).unwrap();
+ let proof = sign_json["proof"].as_str().expect("missing proof");
+ println!("DEBUG proof: {proof}");
+ println!("DEBUG verifying same address: {address}");
+
+ // Verify with the identical address + message.
+ cli.wallet_cmd(&[
"--wallet",
WALLET_NAME,
- "sign_message",
- "--message",
- message,
+ "verify_message",
"--address",
&address,
+ "--message",
+ message,
+ "--proof",
+ proof,
])
- .output()
- .expect("Failed to sign message");
- assert!(
- sign_output.status.success(),
- "sign_message failed: {}",
- String::from_utf8_lossy(&sign_output.stderr)
- );
- let sign_json: Value = serde_json::from_slice(&sign_output.stdout).unwrap();
- let proof = sign_json["proof"].as_str().expect("missing proof");
- println!("DEBUG proof: {proof}");
- println!("DEBUG verifying same address: {address}");
-
- // Verify with the identical address + message.
- cli.wallet_cmd(&[
- "--wallet",
- WALLET_NAME,
- "verify_message",
- "--address",
- &address,
- "--message",
- message,
- "--proof",
- proof,
- ])
- .assert()
- .success()
- .stdout(predicate::str::contains("\"valid\": true"));
- }
-
- #[cfg(feature = "bip322")]
- #[test]
- fn test_verify_message_rejects_tampered_message() {
- let (cli, mut cmd_init) = setup_wallet_config();
- cmd_init.assert().success();
-
- let addr_output = cli
- .wallet_cmd(&["--wallet", WALLET_NAME, "new_address"])
- .output()
- .expect("Failed to generate address");
- let addr_json: Value = serde_json::from_slice(&addr_output.stdout).unwrap();
- let address = addr_json["address"].as_str().unwrap();
-
- let sign_output = cli
- .wallet_cmd(&[
+ .assert()
+ .success()
+ .stdout(predicate::str::contains("\"valid\": true"));
+ }
+
+ #[cfg(feature = "bip322")]
+ #[test]
+ fn test_verify_message_rejects_tampered_message() {
+ let (cli, mut cmd_init) = setup_wallet_config();
+ cmd_init.assert().success();
+
+ let addr_output = cli
+ .wallet_cmd(&["--wallet", WALLET_NAME, "new_address"])
+ .output()
+ .expect("Failed to generate address");
+ let addr_json: Value = serde_json::from_slice(&addr_output.stdout).unwrap();
+ let address = addr_json["address"].as_str().unwrap();
+
+ let sign_output = cli
+ .wallet_cmd(&[
+ "--wallet",
+ WALLET_NAME,
+ "sign_message",
+ "--message",
+ "original message",
+ "--address",
+ address,
+ ])
+ .output()
+ .expect("Failed to sign message");
+ let sign_json: Value = serde_json::from_slice(&sign_output.stdout).unwrap();
+ let proof = sign_json["proof"].as_str().unwrap();
+
+ // A tampered message should fail
+ cli.wallet_cmd(&[
"--wallet",
WALLET_NAME,
- "sign_message",
+ "verify_message",
+ "--proof",
+ proof,
"--message",
- "original message",
+ "tampered message",
"--address",
address,
])
- .output()
- .expect("Failed to sign message");
- let sign_json: Value = serde_json::from_slice(&sign_output.stdout).unwrap();
- let proof = sign_json["proof"].as_str().unwrap();
-
- // A tampered message should fail
- cli.wallet_cmd(&[
- "--wallet",
- WALLET_NAME,
- "verify_message",
- "--proof",
- proof,
- "--message",
- "tampered message",
- "--address",
- address,
- ])
- .assert()
- .success()
- .stdout(predicate::str::contains("\"valid\": false"));
- }
-
+ .assert()
+ .success()
+ .stdout(predicate::str::contains("\"valid\": false"));
+ }
+ **/
#[test]
fn test_create_tx_send_all_rejects_multiple_recipients() {
let (cli, mut cmd_init) = setup_wallet_config();
);
}
}
+ /**
+ #[cfg(feature = "bip322")]
+ #[test]
+ fn test_verify_message_proof_of_funds_uses_persisted_utxos() {
+ let env = TestEnv::new().expect("Failed to start bdk_testenv");
+ let server_url = env.electrsd.electrum_url.as_str();
+ let temp_dir = TempDir::new().unwrap();
+ let cli = BdkCli::new("regtest", Some(temp_dir.path().to_path_buf()));
- #[cfg(feature = "bip322")]
- #[test]
- fn test_verify_message_proof_of_funds_uses_persisted_utxos() {
- let env = TestEnv::new().expect("Failed to start bdk_testenv");
- let server_url = env.electrsd.electrum_url.as_str();
- let temp_dir = TempDir::new().unwrap();
- let cli = BdkCli::new("regtest", Some(temp_dir.path().to_path_buf()));
-
- // A wpkh wallet
- let desc = cli.cmd("descriptor", &["--type", "wpkh"]).output().unwrap();
- let desc_val: Value = serde_json::from_slice(&desc.stdout).unwrap();
- let ext_desc = desc_val["private_descriptors"]["external"]
- .as_str()
- .unwrap();
- let int_desc = desc_val["private_descriptors"]["internal"]
- .as_str()
- .unwrap();
- cli.build_base_cmd()
- .arg("wallet")
- .arg("--wallet")
- .arg(WALLET_NAME)
- .arg("config")
- .arg("--ext-descriptor")
- .arg(ext_desc)
- .arg("--int-descriptor")
- .arg(int_desc)
- .arg("--client-type")
- .arg("electrum")
- .arg("--database-type")
- .arg("sqlite")
- .arg("--url")
- .arg(server_url)
- .assert()
- .success();
-
- // Fund a single small UTXO
- let address = cli_new_address(&cli);
- let node_addr = env
- .rpc_client()
- .get_new_address(None, None)
- .unwrap()
- .assume_checked();
- env.mine_blocks(101, Some(node_addr)).unwrap();
- env.wait_until_electrum_sees_block(Duration::from_secs(10))
- .unwrap();
- let txid = env.send(&address, Amount::from_sat(5_000)).unwrap();
- env.wait_until_electrum_sees_txid(txid, Duration::from_secs(10))
- .unwrap();
- env.mine_blocks(3, None).unwrap();
- env.wait_until_electrum_sees_block(Duration::from_secs(10))
- .unwrap();
- cli_full_scan(&cli);
-
- // The funded outpoint to prove control of.
- let unspent = run_wallet_json(&cli, &["unspent"]);
- let outpoint = unspent["items"][0]["outpoint"]
- .as_str()
- .expect("funded wallet should have one UTXO")
- .to_string();
- let addr = address.to_string();
+ // A wpkh wallet
+ let desc = cli.cmd("descriptor", &["--type", "wpkh"]).output().unwrap();
+ let desc_val: Value = serde_json::from_slice(&desc.stdout).unwrap();
+ let ext_desc = desc_val["private_descriptors"]["external"]
+ .as_str()
+ .unwrap();
+ let int_desc = desc_val["private_descriptors"]["internal"]
+ .as_str()
+ .unwrap();
+ cli.build_base_cmd()
+ .arg("wallet")
+ .arg("--wallet")
+ .arg(WALLET_NAME)
+ .arg("config")
+ .arg("--ext-descriptor")
+ .arg(ext_desc)
+ .arg("--int-descriptor")
+ .arg(int_desc)
+ .arg("--client-type")
+ .arg("electrum")
+ .arg("--database-type")
+ .arg("sqlite")
+ .arg("--url")
+ .arg(server_url)
+ .assert()
+ .success();
- // Produce a proof-of-funds over that UTXO.
- let proof = run_wallet_json(
- &cli,
- &[
- "sign_message",
- "--message",
- "proof-of-funds",
- "--address",
- &addr,
- "--signature-type",
- "fullproofoffunds",
- "--utxos",
- &outpoint,
- ],
- )["proof"]
- .as_str()
- .expect("sign_message should return a proof")
- .to_string();
+ // Fund a single small UTXO
+ let address = cli_new_address(&cli);
+ let node_addr = env
+ .rpc_client()
+ .get_new_address(None, None)
+ .unwrap()
+ .assume_checked();
+ env.mine_blocks(101, Some(node_addr)).unwrap();
+ env.wait_until_electrum_sees_block(Duration::from_secs(10))
+ .unwrap();
+ let txid = env.send(&address, Amount::from_sat(5_000)).unwrap();
+ env.wait_until_electrum_sees_txid(txid, Duration::from_secs(10))
+ .unwrap();
+ env.mine_blocks(3, None).unwrap();
+ env.wait_until_electrum_sees_block(Duration::from_secs(10))
+ .unwrap();
+ cli_full_scan(&cli);
- let result = run_wallet_json(
- &cli,
- &[
- "verify_message",
- "--proof",
- &proof,
- "--message",
- "proof-of-funds",
- "--address",
- &addr,
- ],
- );
- assert_eq!(
- result["valid"].as_bool(),
- Some(true),
- "proof-of-funds should verify against the persisted wallet: {result}"
- );
- assert_eq!(
- result["proven_amount"].as_u64(),
- Some(5_000),
- "proven_amount should equal the funded UTXO value: {result}"
- );
- }
+ // The funded outpoint to prove control of.
+ let unspent = run_wallet_json(&cli, &["unspent"]);
+ let outpoint = unspent["items"][0]["outpoint"]
+ .as_str()
+ .expect("funded wallet should have one UTXO")
+ .to_string();
+ let addr = address.to_string();
+
+ // Produce a proof-of-funds over that UTXO.
+ let proof = run_wallet_json(
+ &cli,
+ &[
+ "sign_message",
+ "--message",
+ "proof-of-funds",
+ "--address",
+ &addr,
+ "--signature-type",
+ "fullproofoffunds",
+ "--utxos",
+ &outpoint,
+ ],
+ )["proof"]
+ .as_str()
+ .expect("sign_message should return a proof")
+ .to_string();
+ let result = run_wallet_json(
+ &cli,
+ &[
+ "verify_message",
+ "--proof",
+ &proof,
+ "--message",
+ "proof-of-funds",
+ "--address",
+ &addr,
+ ],
+ );
+ assert_eq!(
+ result["valid"].as_bool(),
+ Some(true),
+ "proof-of-funds should verify against the persisted wallet: {result}"
+ );
+ assert_eq!(
+ result["proven_amount"].as_u64(),
+ Some(5_000),
+ "proven_amount should equal the funded UTXO value: {result}"
+ );
+ }
+ */
// `create_dns_tx` with a plain `--to` recipient
#[cfg(feature = "dns_payment")]
#[test]