diff --git a/Cargo.lock b/Cargo.lock index 54436c0..63dc326 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,6 +293,33 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "aws-lc-rs" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7d844e282b4b56750b2d4e893b2205581ded8709fddd2b6aa5418c150ca877" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a2c29203f6bf296d01141cc8bb9dbd5ecd4c27843f2ee0767bcd5985a927da" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "backtrace" version = "0.3.73" @@ -364,7 +391,7 @@ dependencies = [ "bdk-macros", "bip39", "bitcoin 0.30.2", - "electrum-client", + "electrum-client 0.18.0", "getrandom 0.2.15", "js-sys", "log", @@ -490,6 +517,29 @@ dependencies = [ "serde", ] +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.5.0", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.67", + "which", +] + [[package]] name = "bip39" version = "2.0.0" @@ -679,6 +729,20 @@ name = "cc" version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +dependencies = [ + "jobserver", + "libc", + "once_cell", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" @@ -726,6 +790,17 @@ dependencies = [ "half", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.2.25" @@ -787,6 +862,15 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.1" @@ -1108,6 +1192,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "dyn-clone" version = "1.0.17" @@ -1160,7 +1250,7 @@ dependencies = [ "byteorder", "libc", "log", - "rustls", + "rustls 0.21.12", "serde", "serde_json", "webpki", @@ -1168,6 +1258,23 @@ dependencies = [ "winapi", ] +[[package]] +name = "electrum-client" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7b1f8783238bb18e6e137875b0a66f3dffe6c7ea84066e05d033cf180b150f" +dependencies = [ + "bitcoin 0.32.2", + "byteorder", + "libc", + "log", + "rustls 0.23.10", + "serde", + "serde_json", + "webpki-roots 0.25.4", + "winapi", +] + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -1415,6 +1522,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.30" @@ -1700,6 +1813,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "http" version = "0.2.12" @@ -1874,6 +1996,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -1901,12 +2032,28 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libloading" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + [[package]] name = "libm" version = "0.2.8" @@ -1968,6 +2115,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniscript" version = "10.0.0" @@ -2008,8 +2161,8 @@ dependencies = [ "base64 0.12.3", "log", "once_cell", - "rustls", - "rustls-webpki", + "rustls 0.21.12", + "rustls-webpki 0.101.7", "serde", "serde_json", "webpki-roots 0.25.4", @@ -2026,6 +2179,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "native-tls" version = "0.2.12" @@ -2043,6 +2202,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2395,6 +2564,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.67", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -2718,6 +2897,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -2748,10 +2933,25 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -2761,6 +2961,12 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2771,6 +2977,18 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.18" @@ -3109,6 +3327,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "side-node" version = "0.1.0" @@ -3124,9 +3348,11 @@ dependencies = [ "bitcoin 0.32.2", "clap 4.5.7", "dirs", + "electrum-client 0.20.0", "ezsockets", "fastcrypto", "indexmap 2.2.6", + "reqwest", "serde", "serde_json", "sha256", @@ -3906,6 +4132,18 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/side-node/Cargo.toml b/side-node/Cargo.toml index dd89008..8f0254a 100644 --- a/side-node/Cargo.toml +++ b/side-node/Cargo.toml @@ -17,9 +17,11 @@ bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" } bitcoin = { version = "0.32.2", features = ["rand"] } clap = { version = "4.5.4", features = ["derive"] } dirs = "5.0.1" +electrum-client = "0.20" ezsockets = { version = "*", features = ["client"] } fastcrypto = "0.1.8" indexmap = { version = "2.2.6", features = ["serde"] } +reqwest = { version = "*", features = ["blocking"] } # serde_cbor = "0.11.2" # move to this once we need to pack things in CBOR serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.117" diff --git a/side-node/src/clients/btc_other_rpc.rs b/side-node/src/clients/btc_other_rpc.rs index 04ae0ab..9390ac0 100644 --- a/side-node/src/clients/btc_other_rpc.rs +++ b/side-node/src/clients/btc_other_rpc.rs @@ -1,37 +1,71 @@ use crate::{keys, utils}; + +use bdk::bitcoin::base64; +use bdk::bitcoin::psbt::PartiallySignedTransaction; +use bdk::blockchain::Progress; +use bdk::database::MemoryDatabase; +use bdk::wallet::AddressIndex::{self, New}; use bdk::{blockchain::ElectrumBlockchain, electrum_client, SyncOptions}; +use bdk::{FeeRate, SignOptions, TransactionDetails, Wallet}; + +#[derive(Debug)] +pub struct CustomProgress; + +impl Progress for CustomProgress { + fn update(&self, progress: f32, message: Option) -> Result<(), bdk::Error> { + println!("Progress: {} - {:?}", progress, message); + Ok(()) + } +} pub async fn run() -> Result<(), anyhow::Error> { let dave = utils::home(&"dave".to_string()); - let sammy = utils::home(&"sammy".to_string()); - - // Load mnemonics from disk let dave_wallet = keys::bitcoin::load_from_file(&dave).unwrap(); - let sammy_wallet = keys::bitcoin::load_from_file(&sammy).unwrap(); - // let dave_address = dave_wallet.get_address(bdk::wallet::AddressIndex::New)?; - // println!("Dave address: {:?}", dave_address); - - // let sammy_address = sammy_wallet.get_address(bdk::wallet::AddressIndex::New)?; - // println!("Sammy address: {:?}", sammy_address); + // Verify explicitly that the address is derived as expected + let expected_address = "tb1q88e45m4akrg2y00n4077vn90q8qw0svz7dss6k"; + let derived_address = dave_wallet.get_address(AddressIndex::Peek(0))?.to_string(); + assert_eq!(expected_address, derived_address); let blockchain = ElectrumBlockchain::from(electrum_client::Client::new( "ssl://electrum.blockstream.info:60002", )?); - // let dave_balance = dave_wallet.get_balance()?; - // println!("Wallet balance before syncing: {} sats", dave_balance); - - // let sammy_balance = sammy_wallet.get_balance()?; - // println!("Wallet balance before syncing: {} sats", sammy_balance); - println!("Syncing..."); dave_wallet.sync(&blockchain, SyncOptions::default())?; + println!( - "Wallet balance for {} after syncing: {:?} sats", - dave_wallet.get_address(bdk::wallet::AddressIndex::LastUnused)?, - dave_wallet.get_balance()? + "Wallet balance for {} after syncing: {:?} sats on network {}", + dave_wallet.get_address(bdk::wallet::AddressIndex::Peek(0))?, + dave_wallet.get_balance()?, + dave_wallet.network() ); + let transactions = dave_wallet.list_transactions(false)?; + println!("Transaction History: {:?}", transactions); + + let (mut psbt, details) = build_sending_tx(&dave_wallet).expect("psbt fukked"); + + println!("Transaction details: {:#?}", details); + println!("Unsigned PSBT: {}", base64::encode(psbt.serialize())); + // let mut psbt = Psbt::deserialize(&base64::decode(psbt).unwrap())?; + let _finalized = dave_wallet.sign(&mut psbt, SignOptions::default())?; + + println!("Finalized: {}", _finalized); + Ok(()) } + +fn build_sending_tx( + wallet: &Wallet, +) -> anyhow::Result<(PartiallySignedTransaction, TransactionDetails), anyhow::Error> { + let send_to = wallet.get_address(New)?; + + let mut builder = wallet.build_tx(); + builder + .add_recipient(send_to.script_pubkey(), 500) + .enable_rbf() + .do_not_spend_change() + .fee_rate(FeeRate::from_sat_per_vb(5.0)); + Ok(builder.finish()?) +} diff --git a/side-node/src/clients/mod.rs b/side-node/src/clients/mod.rs index c2f3427..e5cc7ba 100644 --- a/side-node/src/clients/mod.rs +++ b/side-node/src/clients/mod.rs @@ -1,3 +1,4 @@ pub mod btc_other_rpc; pub mod btc_rpc; +pub mod test; pub mod websocket; diff --git a/side-node/src/clients/test.rs b/side-node/src/clients/test.rs new file mode 100644 index 0000000..3f46762 --- /dev/null +++ b/side-node/src/clients/test.rs @@ -0,0 +1,19 @@ +use anyhow::Result; +use reqwest::blocking::Client; + +pub async fn run() -> Result<(), Box> { + // Set up the Esplora client + let esplora_url = "https://blockstream.info/signet/api"; + let client = Client::new(); + + // Address to check + let address = "tb1q88e45m4akrg2y00n4077vn90q8qw0svz7dss6k"; + + // Query balance + let url = format!("{}/address/{}/utxo", esplora_url, address); + let response = client.get(&url).send()?.text()?; + + println!("UTXO for address: {}", response); + + Ok(()) +} diff --git a/side-node/src/keys/bitcoin.rs b/side-node/src/keys/bitcoin.rs index 0ea9878..e5b9ee2 100644 --- a/side-node/src/keys/bitcoin.rs +++ b/side-node/src/keys/bitcoin.rs @@ -45,7 +45,7 @@ pub fn create_wallet(mnemonic_words: String) -> anyhow::Result