From 41cf16791ae4467496cbd8ad38bfa28fc6c856d3 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Tue, 10 Oct 2023 18:11:43 +0200 Subject: [PATCH 1/3] backend: wip including nakamoto Signed-off-by: Vincenzo Palazzo --- Cargo.lock | 233 +++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/bitcoin/d/mod.rs | 2 + src/bitcoin/d/nakamoto/mod.rs | 118 +++++++++++++++++ 4 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 src/bitcoin/d/nakamoto/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 7d057c721..ec9805beb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,7 +97,7 @@ dependencies = [ "bitcoin_hashes 0.13.0", "hex-conservative", "hex_lit", - "secp256k1", + "secp256k1 0.27.0", "serde", ] @@ -169,6 +169,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "dirs" version = "5.0.0" @@ -202,6 +221,15 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fern" version = "0.6.2" @@ -259,6 +287,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "itoa" version = "1.0.10" @@ -291,6 +328,7 @@ dependencies = [ "libc", "log", "miniscript", + "nakamoto", "rdrand", "rusqlite", "serde", @@ -338,15 +376,40 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "microserde" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc73d64402c57ce913a4a4788ca4e0c60329a2e29782f8e88d510c1c951fac46" +dependencies = [ + "microserde-derive", +] + +[[package]] +name = "microserde-derive" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3afa8ee462bb9ed735b544476a9e4ece0f10be76864ff9b80a6a525b837232" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "miniscript" version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86a23dd3ad145a980e231185d114399f25a0a307d2cd918010ddda6334323df9" dependencies = [ +<<<<<<< HEAD "bech32", "bitcoin", "bitcoin-internals", +======= + "bitcoin 0.30.0", + "bitcoin-private", +>>>>>>> 271acd1 (backend: wip including nakamoto) "serde", ] @@ -370,6 +433,104 @@ dependencies = [ "serde_json", ] +[[package]] +name = "nakamoto" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "nakamoto-chain", + "nakamoto-client", + "nakamoto-common", + "nakamoto-net", + "nakamoto-net-poll", + "nakamoto-p2p", +] + +[[package]] +name = "nakamoto-chain" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "log", + "nakamoto-common", + "thiserror", +] + +[[package]] +name = "nakamoto-client" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "crossbeam-channel", + "fastrand", + "log", + "microserde", + "nakamoto-chain", + "nakamoto-common", + "nakamoto-net", + "nakamoto-p2p", + "thiserror", +] + +[[package]] +name = "nakamoto-common" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "bitcoin 0.29.2", + "bitcoin_hashes 0.11.0", + "fastrand", + "log", + "microserde", + "nakamoto-net", + "nonempty", + "thiserror", +] + +[[package]] +name = "nakamoto-net" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "crossbeam-channel", + "fastrand", + "log", + "thiserror", +] + +[[package]] +name = "nakamoto-net-poll" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "crossbeam-channel", + "libc", + "log", + "nakamoto-net", + "popol", + "socket2", +] + +[[package]] +name = "nakamoto-p2p" +version = "0.4.0" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +dependencies = [ + "crossbeam-channel", + "fastrand", + "log", + "microserde", + "nakamoto-common", + "nakamoto-net", + "thiserror", +] + +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + [[package]] name = "object" version = "0.31.1" @@ -397,6 +558,15 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +[[package]] +name = "popol" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953dd115cbe3b9d10340d47e6825a9700059a2fee12cee722975776caf3c531" +dependencies = [ + "libc", +] + [[package]] name = "proc-macro2" version = "1.0.74" @@ -481,18 +651,45 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "secp256k1" +<<<<<<< HEAD version = "0.28.0" +======= +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "bitcoin_hashes 0.11.0", + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +>>>>>>> 271acd1 (backend: wip including nakamoto) source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" dependencies = [ "bitcoin_hashes 0.12.0", - "secp256k1-sys", + "secp256k1-sys 0.8.1", "serde", ] [[package]] name = "secp256k1-sys" +<<<<<<< HEAD version = "0.9.1" +======= +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +>>>>>>> 271acd1 (backend: wip including nakamoto) source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" dependencies = [ @@ -536,6 +733,16 @@ version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "syn" version = "2.0.46" @@ -624,6 +831,28 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 21c21949b..e95f39949 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ nonblocking_shutdown = [] [dependencies] # For managing transactions (it re-exports the bitcoin crate) miniscript = { version = "11.0", features = ["serde", "compiler", "base64"] } +nakamoto = { git = "https://github.com/vincenzopalazzo/nakamoto.git", features = ["nakamoto-client", "nakamoto-net-poll"], commit = "e03c7dc4caf01605b050cc77718bfc663a323764" } # Coin selection algorithms for spend transaction creation. bdk_coin_select = { version = "0.1.0" } diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index a1b1317c4..f80a4277f 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -2,6 +2,8 @@ //! //! We use the RPC interface and a watchonly descriptor wallet. +// FIXME(vincenzopalazzo): move this outside of the bitcoind crate +mod nakamoto; mod utils; use crate::{ bitcoin::{Block, BlockChainTip}, diff --git a/src/bitcoin/d/nakamoto/mod.rs b/src/bitcoin/d/nakamoto/mod.rs new file mode 100644 index 000000000..390f5935f --- /dev/null +++ b/src/bitcoin/d/nakamoto/mod.rs @@ -0,0 +1,118 @@ +//! Nakamoto Backend implementation +//! +//! Author: Vincenzo Palazzo +use std::net; +use std::path::PathBuf; +use std::thread::JoinHandle; + +// FIXME: use the bitcoin exported inside the type +use nakamoto::common::bitcoin; + +use nakamoto::client; +use nakamoto::net::poll::{Waker, Reactor}; + +use crate::bitcoin::BitcoinInterface; + +/// Nakamoto client +pub struct Nakamoto { + /// Nakamoto handler used interact with the client. + handler: client::Handle, + /// Nakamoto main worked to avoid leave a pending project. + worker: JoinHandle> +} + +impl Nakamoto { + /// Create a new instance of nakamoto. + pub fn new(network: &bitcoin::Network, connect: &[net::SocketAddr], data_dir: PathBuf) -> Result { + let mut config = client::Config::new(network.clone().into()); + config.root = data_dir; + config.connect = connect.to_vec(); + config.user_agent = "Liana-Nakamoto-v1"; + let client = client::Client::>::new().unwrap(); + let handler = client.handle(); + let worker = std::thread::spawn(|| client.run(config)); + Ok(Self{ handler, worker }) + } +} + +impl BitcoinInterface for Nakamoto { + fn chain_tip(&self) -> crate::bitcoin::BlockChainTip { + unimplemented!() + } + + fn broadcast_tx(&self, tx: &miniscript::bitcoin::Transaction) -> Result<(), String> { + unimplemented!() + } + + fn common_ancestor(&self, tip: &crate::bitcoin::BlockChainTip) -> Option { + todo!() + } + + fn is_in_chain(&self, tip: &crate::bitcoin::BlockChainTip) -> bool { + unimplemented!() + } + + fn block_before_date(&self, timestamp: u32) -> Option { + unimplemented!() + } + + fn confirmed_coins( + &self, + outpoints: &[miniscript::bitcoin::OutPoint], + ) -> (Vec<(miniscript::bitcoin::OutPoint, i32, u32)>, Vec) { + unimplemented!() + } + + fn genesis_block(&self) -> crate::bitcoin::BlockChainTip { + unimplemented!() + } + + fn received_coins( + &self, + tip: &crate::bitcoin::BlockChainTip, + descs: &[crate::descriptors::SinglePathLianaDesc], + ) -> Vec { + unimplemented!() + } + + fn rescan_progress(&self) -> Option { + unimplemented!() + } + + fn spending_coins( + &self, + outpoints: &[miniscript::bitcoin::OutPoint], + ) -> Vec<(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid)> { + unimplemented!() + } + + fn spent_coins( + &self, + outpoints: &[(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid)], + ) -> Vec<(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid, crate::bitcoin::Block)> { + unimplemented!() + } + + fn start_rescan( + &self, + desc: &crate::descriptors::LianaDescriptor, + timestamp: u32, + ) -> Result<(), String> { + unimplemented!() + } + + fn sync_progress(&self) -> f64 { + unimplemented!() + } + + fn tip_time(&self) -> u32 { + unimplemented!() + } + + fn wallet_transaction( + &self, + txid: &miniscript::bitcoin::Txid, + ) -> Option<(miniscript::bitcoin::Transaction, Option)> { + unimplemented!() + } +} From ea746f90971420548128229f0f29b3bcb3f0504a Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Mon, 25 Dec 2023 17:11:10 +0100 Subject: [PATCH 2/3] wip: implement basic method with nakamoto Signed-off-by: Vincenzo Palazzo --- Cargo.lock | 19 +++---- Cargo.toml | 2 +- src/bitcoin/d/mod.rs | 1 + src/bitcoin/d/nakamoto/mod.rs | 98 ++++++++++++++++++++++++++--------- 4 files changed, 83 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec9805beb..595aa33df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -402,14 +402,9 @@ version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86a23dd3ad145a980e231185d114399f25a0a307d2cd918010ddda6334323df9" dependencies = [ -<<<<<<< HEAD "bech32", "bitcoin", "bitcoin-internals", -======= - "bitcoin 0.30.0", - "bitcoin-private", ->>>>>>> 271acd1 (backend: wip including nakamoto) "serde", ] @@ -436,7 +431,7 @@ dependencies = [ [[package]] name = "nakamoto" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "nakamoto-chain", "nakamoto-client", @@ -449,7 +444,7 @@ dependencies = [ [[package]] name = "nakamoto-chain" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "log", "nakamoto-common", @@ -459,7 +454,7 @@ dependencies = [ [[package]] name = "nakamoto-client" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "crossbeam-channel", "fastrand", @@ -475,7 +470,7 @@ dependencies = [ [[package]] name = "nakamoto-common" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "bitcoin 0.29.2", "bitcoin_hashes 0.11.0", @@ -490,7 +485,7 @@ dependencies = [ [[package]] name = "nakamoto-net" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "crossbeam-channel", "fastrand", @@ -501,7 +496,7 @@ dependencies = [ [[package]] name = "nakamoto-net-poll" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "crossbeam-channel", "libc", @@ -514,7 +509,7 @@ dependencies = [ [[package]] name = "nakamoto-p2p" version = "0.4.0" -source = "git+https://github.com/vincenzopalazzo/nakamoto.git#9b24b04675076a9584ea7c5366095467d2ee24f4" +source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" dependencies = [ "crossbeam-channel", "fastrand", diff --git a/Cargo.toml b/Cargo.toml index e95f39949..1b8b2d900 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ nonblocking_shutdown = [] [dependencies] # For managing transactions (it re-exports the bitcoin crate) miniscript = { version = "11.0", features = ["serde", "compiler", "base64"] } -nakamoto = { git = "https://github.com/vincenzopalazzo/nakamoto.git", features = ["nakamoto-client", "nakamoto-net-poll"], commit = "e03c7dc4caf01605b050cc77718bfc663a323764" } +nakamoto = { git = "https://github.com/cloudhead/nakamoto.git", features = ["nakamoto-client", "nakamoto-net-poll"] } # Coin selection algorithms for spend transaction creation. bdk_coin_select = { version = "0.1.0" } diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index f80a4277f..aa435bc0d 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -61,6 +61,7 @@ pub enum BitcoindError { NetworkMismatch(String /*config*/, String /*bitcoind*/), StartRescan, RescanPastPruneHeight, + GenericError, } impl BitcoindError { diff --git a/src/bitcoin/d/nakamoto/mod.rs b/src/bitcoin/d/nakamoto/mod.rs index 390f5935f..e5844204f 100644 --- a/src/bitcoin/d/nakamoto/mod.rs +++ b/src/bitcoin/d/nakamoto/mod.rs @@ -3,14 +3,17 @@ //! Author: Vincenzo Palazzo use std::net; use std::path::PathBuf; +use std::str::FromStr; use std::thread::JoinHandle; -// FIXME: use the bitcoin exported inside the type -use nakamoto::common::bitcoin; - +use nakamoto::client::traits::Handle; use nakamoto::client; +use nakamoto::common::bitcoin_hashes::hex::FromHex; use nakamoto::net::poll::{Waker, Reactor}; +use miniscript::bitcoin::hashes::Hash; +use miniscript::bitcoin::{self, BlockHash}; +use crate::BitcoindError; use crate::bitcoin::BitcoinInterface; /// Nakamoto client @@ -19,29 +22,53 @@ pub struct Nakamoto { handler: client::Handle, /// Nakamoto main worked to avoid leave a pending project. worker: JoinHandle> + network: client::Network, } impl Nakamoto { /// Create a new instance of nakamoto. pub fn new(network: &bitcoin::Network, connect: &[net::SocketAddr], data_dir: PathBuf) -> Result { - let mut config = client::Config::new(network.clone().into()); + let network = client::Network::from_str(&network.to_string()).map_err(|err| ())?; + let mut config = client::Config::new(network); config.root = data_dir; config.connect = connect.to_vec(); config.user_agent = "Liana-Nakamoto-v1"; let client = client::Client::>::new().unwrap(); let handler = client.handle(); let worker = std::thread::spawn(|| client.run(config)); - Ok(Self{ handler, worker }) + Ok(Self{ handler, worker, network }) + } + + /// Stop the nakamoto node + pub fn stop(&self) -> Result<(), BitcoindError> { + self.handler.shutdown(); + self.worker.join().map_err(|err| BitcoindError::GenericError)?; + Ok(()) } } impl BitcoinInterface for Nakamoto { - fn chain_tip(&self) -> crate::bitcoin::BlockChainTip { + fn mempool_spenders(&self, outpoints: &[miniscript::bitcoin::OutPoint]) -> Vec { unimplemented!() } + fn chain_tip(&self) -> crate::bitcoin::BlockChainTip { + // FIXME: we should check the error and maybe return + // it to the caller. + let (height, header, _) = self.handler.get_tip().unwrap(); + let block_hash = header.block_hash(); + let hash = bitcoin::BlockHash::from_slice(&block_hash.as_hash().to_vec()).unwrap(); + crate::bitcoin::BlockChainTip{ height: height as i32, hash } + } + fn broadcast_tx(&self, tx: &miniscript::bitcoin::Transaction) -> Result<(), String> { - unimplemented!() + use miniscript::bitcoin::consensus::serialize; + use nakamoto::common::bitcoin::consensus::deserialize; + + let tx = serialize(tx); + let tx: nakamoto::common::bitcoin::Transaction = deserialize(&tx).map_err(|err| format!("{err}"))?; + self.handler.submit_transaction(tx).map_err(|err| format!("{err}"))?; + Ok(()) } fn common_ancestor(&self, tip: &crate::bitcoin::BlockChainTip) -> Option { @@ -64,7 +91,12 @@ impl BitcoinInterface for Nakamoto { } fn genesis_block(&self) -> crate::bitcoin::BlockChainTip { - unimplemented!() + let height = 0; + let block = self.handler.get_block_by_height(height).unwrap(); + let block = block.unwrap(); + let block_hash = block.block_hash().as_hash().to_string(); + let block_hash = miniscript::bitcoin::BlockHash::from_str(&block_hash).unwrap(); + crate::bitcoin::BlockChainTip{ height: height as i32, hash: block_hash } } fn received_coins( @@ -76,7 +108,7 @@ impl BitcoinInterface for Nakamoto { } fn rescan_progress(&self) -> Option { - unimplemented!() + None } fn spending_coins( @@ -86,33 +118,51 @@ impl BitcoinInterface for Nakamoto { unimplemented!() } - fn spent_coins( - &self, - outpoints: &[(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid)], - ) -> Vec<(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid, crate::bitcoin::Block)> { - unimplemented!() - } - fn start_rescan( &self, desc: &crate::descriptors::LianaDescriptor, timestamp: u32, ) -> Result<(), String> { - unimplemented!() + // We do not care for the momenet, because we are tracking with nakamoto + // all the transactions submitted + Ok(()) } - fn sync_progress(&self) -> f64 { - unimplemented!() + fn wallet_transaction( + &self, + txid: &miniscript::bitcoin::Txid, + ) -> Option<(miniscript::bitcoin::Transaction, Option)> { + use nakamoto::common::bitcoin::consensus::serialize; + use miniscript::bitcoin::consensus::deserialize; + + let txid = txid.to_string(); + let txid = nakamoto::common::bitcoin::Txid::from_hex(&txid).unwrap(); + let Ok(Some(tx)) = self.handler.get_submitted_transaction(&txid) else { + return None; + }; + let tx = serialize(&tx); + let tx: miniscript::bitcoin::Transaction = deserialize(&tx).unwrap(); + // FIXME: we do not know what is the block that it is confirmed, we should + // keep this in our db maybe? + Some((tx, None)) } - fn tip_time(&self) -> u32 { + fn spent_coins( + &self, + outpoints: &[(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid)], + ) -> ( + Vec<(miniscript::bitcoin::OutPoint, miniscript::bitcoin::Txid, crate::bitcoin::Block)>, + Vec, + ) { unimplemented!() } - fn wallet_transaction( - &self, - txid: &miniscript::bitcoin::Txid, - ) -> Option<(miniscript::bitcoin::Transaction, Option)> { + fn sync_progress(&self) -> super::SyncProgress { unimplemented!() } + + fn tip_time(&self) -> Option { + // This is a little bit hard to track at the moment + None + } } From c2bb2b85fb31eeca75fc3294e67a067aabdfae98 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Sun, 18 Feb 2024 14:29:42 +0100 Subject: [PATCH 3/3] fixup! wip: implement basic method with nakamoto Signed-off-by: Vincenzo Palazzo --- Cargo.lock | 88 ++++++++++++++++++------------ Cargo.toml | 2 +- contrib/lianad_config_example.toml | 8 +-- src/bin/daemon.rs | 2 +- src/bitcoin/d/mod.rs | 6 +- src/bitcoin/d/nakamoto/mod.rs | 30 +++++----- src/lib.rs | 6 ++ 7 files changed, 85 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 595aa33df..140a9599d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,6 +68,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0320167c3655e83f0415d52f39618902e449186ffc7dfb090f922f79675c316" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bech32" version = "0.10.0-beta" @@ -85,6 +91,17 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "bitcoin" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" +dependencies = [ + "bech32 0.9.1", + "bitcoin_hashes 0.11.0", + "secp256k1 0.24.3", +] + [[package]] name = "bitcoin" version = "0.31.0" @@ -92,12 +109,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5973a027b341b462105675962214dfe3c938ad9afd395d84b28602608bdcec7b" dependencies = [ "base64 0.21.5", - "bech32", + "bech32 0.10.0-beta", "bitcoin-internals", "bitcoin_hashes 0.13.0", "hex-conservative", "hex_lit", - "secp256k1 0.27.0", + "secp256k1 0.28.0", "serde", ] @@ -171,22 +188,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "dirs" @@ -393,7 +406,7 @@ checksum = "6e3afa8ee462bb9ed735b544476a9e4ece0f10be76864ff9b80a6a525b837232" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -402,8 +415,8 @@ version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86a23dd3ad145a980e231185d114399f25a0a307d2cd918010ddda6334323df9" dependencies = [ - "bech32", - "bitcoin", + "bech32 0.10.0-beta", + "bitcoin 0.31.0", "bitcoin-internals", "serde", ] @@ -431,7 +444,7 @@ dependencies = [ [[package]] name = "nakamoto" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "nakamoto-chain", "nakamoto-client", @@ -444,7 +457,7 @@ dependencies = [ [[package]] name = "nakamoto-chain" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "log", "nakamoto-common", @@ -454,7 +467,7 @@ dependencies = [ [[package]] name = "nakamoto-client" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "crossbeam-channel", "fastrand", @@ -470,7 +483,7 @@ dependencies = [ [[package]] name = "nakamoto-common" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "bitcoin 0.29.2", "bitcoin_hashes 0.11.0", @@ -485,7 +498,7 @@ dependencies = [ [[package]] name = "nakamoto-net" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "crossbeam-channel", "fastrand", @@ -496,7 +509,7 @@ dependencies = [ [[package]] name = "nakamoto-net-poll" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "crossbeam-channel", "libc", @@ -509,7 +522,7 @@ dependencies = [ [[package]] name = "nakamoto-p2p" version = "0.4.0" -source = "git+https://github.com/cloudhead/nakamoto.git#9ea71ed71655e41b8b1ec7db02b4b8dea6f9f1ea" +source = "git+https://github.com/vincenzopalazzo/nakamoto.git?branch=macros/master#83a746621c08a6ac1177f086e337697f9a8f57dd" dependencies = [ "crossbeam-channel", "fastrand", @@ -646,9 +659,6 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "secp256k1" -<<<<<<< HEAD -version = "0.28.0" -======= version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" @@ -659,21 +669,17 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.27.0" ->>>>>>> 271acd1 (backend: wip including nakamoto) +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" dependencies = [ "bitcoin_hashes 0.12.0", - "secp256k1-sys 0.8.1", + "secp256k1-sys 0.9.1", "serde", ] [[package]] name = "secp256k1-sys" -<<<<<<< HEAD -version = "0.9.1" -======= version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" @@ -683,8 +689,7 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.8.1" ->>>>>>> 271acd1 (backend: wip including nakamoto) +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" dependencies = [ @@ -708,7 +713,7 @@ checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.46", ] [[package]] @@ -730,14 +735,25 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.46" @@ -766,7 +782,7 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.46", ] [[package]] @@ -931,5 +947,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.46", ] diff --git a/Cargo.toml b/Cargo.toml index 1b8b2d900..850f64c3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ nonblocking_shutdown = [] [dependencies] # For managing transactions (it re-exports the bitcoin crate) miniscript = { version = "11.0", features = ["serde", "compiler", "base64"] } -nakamoto = { git = "https://github.com/cloudhead/nakamoto.git", features = ["nakamoto-client", "nakamoto-net-poll"] } +nakamoto = { git = "https://github.com/vincenzopalazzo/nakamoto.git", branch = "macros/master", features = ["nakamoto-client", "nakamoto-net-poll"] } # Coin selection algorithms for spend transaction creation. bdk_coin_select = { version = "0.1.0" } diff --git a/contrib/lianad_config_example.toml b/contrib/lianad_config_example.toml index 462ac8ccb..262fc477b 100644 --- a/contrib/lianad_config_example.toml +++ b/contrib/lianad_config_example.toml @@ -20,7 +20,7 @@ log_level = "debug" # # YOUR DESCRIPTOR IS UNIQUE AND MUST BE BACKED UP, WITHOUT IT YOU WONT BE ABLE TO RECOVER YOUR FUNDS. # -main_descriptor = "wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/<0;1>/*),and_v(v:pkh(tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/<0;1>/*),older(2))))#uact7s3g" +#main_descriptor = "wsh(or_d(pk([92162c45]tpubD6NzVbkrYhZ4WzTf9SsD6h7AH7oQEippXK2KP8qvhMMqFoNeN5YFVi7vRyeRSDGtgd2bPyMxUNmHui8t5yCgszxPPxMafu1VVzDpg9aruYW/<0;1>/*),and_v(v:pkh(tpubD6NzVbkrYhZ4Wdgu2yfdmrce5g4fiH1ZLmKhewsnNKupbi4sxjH1ZVAorkBLWSkhsjhg8kiq8C4BrBjMy3SjAKDyDdbuvUa1ToAHbiR98js/<0;1>/*),older(2))))#uact7s3g" # This section is the configuration related to the Bitcoin backend. # On what network shall it operate? @@ -35,6 +35,6 @@ poll_interval_secs = 30 # how to authenticate, either by specifying the cookie location with "cookie_path" or otherwise # passing a colon-separated user and password with "auth". [bitcoind_config] -addr = "127.0.0.1:18332" -cookie_path = "/home/wizardsardine/.bitcoin/testnet3/.cookie" -# auth = "my_user:my_password" +addr = "192.168.178.30:18332" +#cookie_path = "/home/wizardsardine/.bitcoin/testnet3/.cookie" +auth = "vincent:vincent-home-pi" diff --git a/src/bin/daemon.rs b/src/bin/daemon.rs index 51e3c1347..3f9ed03b3 100644 --- a/src/bin/daemon.rs +++ b/src/bin/daemon.rs @@ -70,7 +70,7 @@ fn main() { process::exit(1); }); - let daemon = DaemonHandle::start_default(config).unwrap_or_else(|e| { + let daemon = DaemonHandle::start_nakamoto(config).unwrap_or_else(|e| { log::error!("Error starting Liana daemon: {}", e); process::exit(1); }); diff --git a/src/bitcoin/d/mod.rs b/src/bitcoin/d/mod.rs index aa435bc0d..43d95bdbd 100644 --- a/src/bitcoin/d/mod.rs +++ b/src/bitcoin/d/mod.rs @@ -3,8 +3,9 @@ //! We use the RPC interface and a watchonly descriptor wallet. // FIXME(vincenzopalazzo): move this outside of the bitcoind crate -mod nakamoto; +pub(crate) mod nakamoto; mod utils; + use crate::{ bitcoin::{Block, BlockChainTip}, config, @@ -154,7 +155,8 @@ impl std::fmt::Display for BitcoindError { f, "Trying to rescan the block chain past the prune block height." ) - } + }, + BitcoindError::GenericError => write!(f, "Generic error"), } } } diff --git a/src/bitcoin/d/nakamoto/mod.rs b/src/bitcoin/d/nakamoto/mod.rs index e5844204f..5638009c1 100644 --- a/src/bitcoin/d/nakamoto/mod.rs +++ b/src/bitcoin/d/nakamoto/mod.rs @@ -11,24 +11,26 @@ use nakamoto::client; use nakamoto::common::bitcoin_hashes::hex::FromHex; use nakamoto::net::poll::{Waker, Reactor}; use miniscript::bitcoin::hashes::Hash; -use miniscript::bitcoin::{self, BlockHash}; +use miniscript::bitcoin; use crate::BitcoindError; use crate::bitcoin::BitcoinInterface; +use super::SyncProgress; + /// Nakamoto client pub struct Nakamoto { /// Nakamoto handler used interact with the client. handler: client::Handle, /// Nakamoto main worked to avoid leave a pending project. - worker: JoinHandle> - network: client::Network, + _worker: JoinHandle>, + _network: client::Network, } impl Nakamoto { /// Create a new instance of nakamoto. pub fn new(network: &bitcoin::Network, connect: &[net::SocketAddr], data_dir: PathBuf) -> Result { - let network = client::Network::from_str(&network.to_string()).map_err(|err| ())?; + let network = client::Network::from_str(&network.to_string()).map_err(|_| ())?; let mut config = client::Config::new(network); config.root = data_dir; config.connect = connect.to_vec(); @@ -36,13 +38,14 @@ impl Nakamoto { let client = client::Client::>::new().unwrap(); let handler = client.handle(); let worker = std::thread::spawn(|| client.run(config)); - Ok(Self{ handler, worker, network }) + Ok(Self{ handler, _worker: worker, _network: network }) } /// Stop the nakamoto node - pub fn stop(&self) -> Result<(), BitcoindError> { - self.handler.shutdown(); - self.worker.join().map_err(|err| BitcoindError::GenericError)?; + #[allow(dead_code)] + pub fn stop(self) -> Result<(), BitcoindError> { + self.handler.shutdown().map_err(|_| BitcoindError::GenericError)?; + let _ = self._worker.join().map_err(|_| BitcoindError::GenericError)?; Ok(()) } } @@ -72,15 +75,15 @@ impl BitcoinInterface for Nakamoto { } fn common_ancestor(&self, tip: &crate::bitcoin::BlockChainTip) -> Option { - todo!() + None } fn is_in_chain(&self, tip: &crate::bitcoin::BlockChainTip) -> bool { - unimplemented!() + true } fn block_before_date(&self, timestamp: u32) -> Option { - unimplemented!() + None } fn confirmed_coins( @@ -123,7 +126,7 @@ impl BitcoinInterface for Nakamoto { desc: &crate::descriptors::LianaDescriptor, timestamp: u32, ) -> Result<(), String> { - // We do not care for the momenet, because we are tracking with nakamoto + // We do not care for the moment, because we are tracking with nakamoto // all the transactions submitted Ok(()) } @@ -158,7 +161,8 @@ impl BitcoinInterface for Nakamoto { } fn sync_progress(&self) -> super::SyncProgress { - unimplemented!() + // FIXME: call tip and try to simulate the bitcoin intergace + SyncProgress::new(100.0, 0, 0) } fn tip_time(&self) -> Option { diff --git a/src/lib.rs b/src/lib.rs index a58b6b30a..bddd4c7d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ pub mod spend; mod testutils; pub use bip39; +use bitcoin::d::nakamoto::Nakamoto; pub use miniscript; pub use crate::bitcoin::d::{BitcoinD, BitcoindError, WalletError}; @@ -373,6 +374,11 @@ impl DaemonHandle { DaemonHandle::start(config, Option::::None, Option::::None) } + pub fn start_nakamoto(config: Config) -> Result { + let nakamoto = Nakamoto::new(&config.bitcoin_config.network, &[], config.data_dir().unwrap()).unwrap(); + DaemonHandle::start(config, Some(nakamoto), Option::::None) + } + /// Start the JSONRPC server and listen for incoming commands until we die. /// Like DaemonHandle::shutdown(), this stops the Bitcoin poller at teardown. #[cfg(feature = "daemon")]