From 5a264a798ffedd428b758f6be226c3f73c243d23 Mon Sep 17 00:00:00 2001 From: Conor Okus Date: Mon, 10 Jan 2022 17:15:21 +0000 Subject: [PATCH 1/5] Adds bitcoin-rpc-client example Update edition value Add missing dependency Downgrade Tokio version Trigger build Create seperate workspace for examples Updates Cargo.toml Build examples in ci Fix yml formatting Remove test script Update tokio version Make dependencies same as sample Add missing dependency Update script for windows Update bash script Updates shell script Adds comment Fix linting errors Trigger Build --- .github/workflows/build.yml | 15 +++ .gitignore | 2 + Cargo.toml | 2 + examples/bitcoind-rpc-client/Cargo.toml | 25 ++++ examples/bitcoind-rpc-client/README.md | 37 ++++++ .../src/bitcoind_client.rs | 118 ++++++++++++++++++ examples/bitcoind-rpc-client/src/convert.rs | 81 ++++++++++++ examples/bitcoind-rpc-client/src/main.rs | 53 ++++++++ lightning-block-sync/src/rpc.rs | 6 +- 9 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 examples/bitcoind-rpc-client/Cargo.toml create mode 100644 examples/bitcoind-rpc-client/README.md create mode 100644 examples/bitcoind-rpc-client/src/bitcoind_client.rs create mode 100644 examples/bitcoind-rpc-client/src/convert.rs create mode 100644 examples/bitcoind-rpc-client/src/main.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fef042beee6..afe6e73e7e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,25 +22,31 @@ jobs: - toolchain: stable build-net-tokio: true build-no-std: true + build-examples: true - toolchain: stable platform: macos-latest build-net-tokio: true build-no-std: true + build-examples: true - toolchain: beta platform: macos-latest build-net-tokio: true build-no-std: true + build-examples: true - toolchain: stable platform: windows-latest build-net-tokio: true build-no-std: true + build-examples: true - toolchain: beta platform: windows-latest build-net-tokio: true build-no-std: true + build-examples: true - toolchain: beta build-net-tokio: true build-no-std: true + build-examples: true - toolchain: 1.36.0 build-no-std: false test-log-variants: true @@ -195,6 +201,15 @@ jobs: # Maybe if codecov wasn't broken we wouldn't need to do this... token: f421b687-4dc2-4387-ac3d-dc3b2528af57 fail_ci_if_error: true + - name: Build examples + if: matrix.build-examples + shell: bash + run: | + cd examples + for FILE in */; do + cd $FILE + cargo build --verbose --color always + done benchmark: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index a108267c2fd..42d6c54426a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ lightning-c-bindings/a.out Cargo.lock .idea lightning/target +/examples/Cargo.lock +/examples/target diff --git a/Cargo.toml b/Cargo.toml index df32ac5d9cf..a0474162e8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,8 @@ members = [ "lightning-net-tokio", "lightning-persister", "lightning-background-processor", + + "examples/*" ] # Our tests do actual crypo and lots of work, the tradeoff for -O1 is well worth it. diff --git a/examples/bitcoind-rpc-client/Cargo.toml b/examples/bitcoind-rpc-client/Cargo.toml new file mode 100644 index 00000000000..6dd9fd6976e --- /dev/null +++ b/examples/bitcoind-rpc-client/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "bitcoind-rpc-client" +version = "0.1.0" +authors = ["Conor Okus "] +edition = "2018" +license = "MIT OR Apache-2.0" + +[dependencies] +lightning = { path = "../../lightning" } +lightning-block-sync = { path = "../../lightning-block-sync", features = ["rpc-client"]} +lightning-net-tokio = { path = "../../lightning-net-tokio" } + +base64 = "0.13.0" +bitcoin = "0.27" +bitcoin-bech32 = "0.12" +bech32 = "0.8" +hex = "0.3" +serde_json = { version = "1.0" } +tokio = { version = "1.5", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] } + +[profile.release] +panic = "abort" + +[profile.dev] +panic = "abort" \ No newline at end of file diff --git a/examples/bitcoind-rpc-client/README.md b/examples/bitcoind-rpc-client/README.md new file mode 100644 index 00000000000..c8ac4daf187 --- /dev/null +++ b/examples/bitcoind-rpc-client/README.md @@ -0,0 +1,37 @@ +# Creates a basic bitcoind client + +This is example shows how you could create a client that directly communicates with bitcoind from LDK. The API is flexible and allows for different ways to implement the interface. + +It implements some basic RPC methods that allow you to create a core wallet and print it's balance to stdout. + +To run with this example you need to have a bitcoin core node running in regtest mode. Get the bitcoin core binary either from the [bitcoin core repo](https://bitcoincore.org/bin/bitcoin-core-0.22.0/) or [build from source](https://github.com/bitcoin/bitcoin/blob/v0.21.1/doc/build-unix.md). + +Then configure the node with the following `bitcoin.conf` + +``` +regtest=1 +fallbackfee=0.0001 +server=1 +txindex=1 +rpcuser=admin +rpcpassword=password +``` + +## How to use + +``` +Cargo run +``` + +## Notes + +`RpcClient` is a simple RPC client for calling methods using HTTP POST. It is implemented in [rust-lightning/lightning-block-sync/rpc.rs](https://github.com/lightningdevkit/rust-lightning/blob/61341df39e90de9d650851a624c0644f5c9dd055/lightning-block-sync/src/rpc.rs) + +The purpose of `RpcClient` is to create a new RPC client connected to the given endpoint with the provided credentials. The credentials should be a base64 encoding of a user name and password joined by a colon, as is required for HTTP basic access authentication. + +It implements [BlockSource](https://github.com/rust-bitcoin/rust-lightning/blob/61341df39e90de9d650851a624c0644f5c9dd055/lightning-block-sync/src/lib.rs#L55) against a Bitcoin Core RPC. It is an asynchronous interface for retrieving block headers and data. + +Check out our [LDK sample node](https://github.com/lightningdevkit/ldk-sample) for an integrated example. + + + diff --git a/examples/bitcoind-rpc-client/src/bitcoind_client.rs b/examples/bitcoind-rpc-client/src/bitcoind_client.rs new file mode 100644 index 00000000000..dd6623429a8 --- /dev/null +++ b/examples/bitcoind-rpc-client/src/bitcoind_client.rs @@ -0,0 +1,118 @@ +use std::{sync::{Arc}}; + +use bitcoin::{BlockHash, Block}; +use lightning_block_sync::{rpc::RpcClient, http::{HttpEndpoint}, BlockSource, AsyncBlockSourceResult, BlockHeaderData}; +use tokio::sync::Mutex; + +use crate::convert::{CreateWalletResponse, BlockchainInfoResponse, NewAddressResponse, GetBalanceResponse, GenerateToAddressResponse}; + + +pub struct BitcoindClient { + bitcoind_rpc_client: Arc>, + host: String, + port: u16, + rpc_user: String, + rpc_password: String, +} + +impl BlockSource for &BitcoindClient { + fn get_header<'a>( + &'a mut self, header_hash: &'a BlockHash, height_hint: Option, + ) -> AsyncBlockSourceResult<'a, BlockHeaderData> { + Box::pin(async move { + let mut rpc = self.bitcoind_rpc_client.lock().await; + rpc.get_header(header_hash, height_hint).await + }) + } + + fn get_block<'a>( + &'a mut self, header_hash: &'a BlockHash, + ) -> AsyncBlockSourceResult<'a, Block> { + Box::pin(async move { + let mut rpc = self.bitcoind_rpc_client.lock().await; + rpc.get_block(header_hash).await + }) + } + + fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<(BlockHash, Option)> { + Box::pin(async move { + let mut rpc = self.bitcoind_rpc_client.lock().await; + rpc.get_best_block().await + }) + } +} + +impl BitcoindClient { + pub async fn new(host: String, port: u16, rpc_user: String, rpc_password: String) -> std::io::Result { + let http_endpoint = HttpEndpoint::for_host(host.clone()).with_port(port); + let rpc_creditials = + base64::encode(format!("{}:{}", rpc_user.clone(), rpc_password.clone())); + let mut bitcoind_rpc_client = RpcClient::new(&rpc_creditials, http_endpoint)?; + let _dummy = bitcoind_rpc_client + .call_method::("getblockchaininfo", &vec![]) + .await + .map_err(|_| { + std::io::Error::new(std::io::ErrorKind::PermissionDenied, + "Failed to make initial call to bitcoind - please check your RPC user/password and access settings") + })?; + + let client = Self { + bitcoind_rpc_client: Arc::new(Mutex::new(bitcoind_rpc_client)), + host, + port, + rpc_user, + rpc_password, + }; + + Ok(client) + } + + pub fn get_new_rpc_client(&self) -> std::io::Result { + let http_endpoint = HttpEndpoint::for_host(self.host.clone()).with_port(self.port); + let rpc_credentials = + base64::encode(format!("{}:{}", self.rpc_user.clone(), self.rpc_password.clone())); + RpcClient::new(&rpc_credentials, http_endpoint) + } + + pub async fn get_blockchain_info(&self) -> BlockchainInfoResponse { + let mut rpc = self.bitcoind_rpc_client.lock().await; + rpc.call_method::("getblockchaininfo", &vec![]).await.unwrap() + } + + pub async fn create_wallet(&self) -> CreateWalletResponse { + let mut rpc = self.bitcoind_rpc_client.lock().await; + let create_wallet_args = vec![serde_json::json!("test-wallet")]; + + rpc.call_method::("createwallet", &create_wallet_args).await.unwrap() + } + + pub async fn get_new_address(&self) -> String { + let mut rpc = self.bitcoind_rpc_client.lock().await; + + let addr_args = vec![serde_json::json!("LDK output address")]; + let addr = rpc.call_method::("getnewaddress", &addr_args).await.unwrap(); + addr.0.to_string() + } + + pub async fn get_balance(&self) -> GetBalanceResponse { + let mut rpc = self.bitcoind_rpc_client.lock().await; + + rpc.call_method::("getbalance", &vec![]).await.unwrap() + } + + pub async fn generate_to_address(&self, block_num: u64, address: &str) -> GenerateToAddressResponse { + let mut rpc = self.bitcoind_rpc_client.lock().await; + + let generate_to_address_args = vec![serde_json::json!(block_num), serde_json::json!(address)]; + + + rpc.call_method::("generatetoaddress", &generate_to_address_args).await.unwrap() + } +} + + + + + + + diff --git a/examples/bitcoind-rpc-client/src/convert.rs b/examples/bitcoind-rpc-client/src/convert.rs new file mode 100644 index 00000000000..e37d55b20b3 --- /dev/null +++ b/examples/bitcoind-rpc-client/src/convert.rs @@ -0,0 +1,81 @@ +use std::convert::TryInto; + +use bitcoin::{BlockHash, hashes::hex::FromHex}; +use lightning_block_sync::http::JsonResponse; + +// TryInto implementation specifies the conversion logic from json response to BlockchainInfo object. +pub struct BlockchainInfoResponse { + pub latest_height: usize, + pub latest_blockhash: BlockHash, + pub chain: String, +} + +impl TryInto for JsonResponse { + type Error = std::io::Error; + fn try_into(self) -> std::io::Result { + Ok(BlockchainInfoResponse { + latest_height: self.0["blocks"].as_u64().unwrap() as usize, + latest_blockhash: BlockHash::from_hex(self.0["bestblockhash"].as_str().unwrap()) + .unwrap(), + chain: self.0["chain"].as_str().unwrap().to_string(), + }) + } +} + +pub struct CreateWalletResponse { + pub name: String, + pub warning: String, +} + +impl TryInto for JsonResponse { + type Error = std::io::Error; + fn try_into(self) -> std::io::Result { + Ok(CreateWalletResponse { + name: self.0["name"].as_str().unwrap().to_string(), + warning: self.0["warning"].as_str().unwrap().to_string(), + }) + } +} +pub struct GetBalanceResponse(pub usize); + +impl TryInto for JsonResponse { + type Error = std::io::Error; + fn try_into(self) -> std::io::Result { + Ok(GetBalanceResponse(self.0.as_f64().unwrap() as usize)) + } +} + +pub struct GenerateToAddressResponse(pub Vec); + +impl TryInto for JsonResponse { + type Error = std::io::Error; + fn try_into(self) -> std::io::Result { + let mut x: Vec = Vec::new(); + + for item in self.0.as_array().unwrap() { + x.push(BlockHash::from_hex(item.as_str().unwrap()) + .unwrap()); + } + + Ok(GenerateToAddressResponse(x)) + } +} + + +pub struct NewAddressResponse(pub String); + +impl TryInto for JsonResponse { + type Error = std::io::Error; + fn try_into(self) -> std::io::Result { + Ok(NewAddressResponse(self.0.as_str().unwrap().to_string())) + } +} + + + + + + + + + diff --git a/examples/bitcoind-rpc-client/src/main.rs b/examples/bitcoind-rpc-client/src/main.rs new file mode 100644 index 00000000000..a6ff786a00c --- /dev/null +++ b/examples/bitcoind-rpc-client/src/main.rs @@ -0,0 +1,53 @@ +pub mod bitcoind_client; + +use std::{sync::Arc}; + +use crate::bitcoind_client::BitcoindClient; + +mod convert; + +#[tokio::main] +pub async fn main() { + start_ldk().await; +} + +async fn start_ldk() { + // Initialize our bitcoind client + let bitcoind_client = match BitcoindClient::new( + String::from("127.0.0.1"), + 18443, + String::from("admin"), + String::from("password") + ) + .await + { + Ok(client) => { + println!("Successfully connected to bitcoind client"); + Arc::new(client) + }, + Err(e) => { + println!("Failed to connect to bitcoind client: {}", e); + return; + } + }; + + // Check we connected to the expected network + let bitcoind_blockchain_info = bitcoind_client.get_blockchain_info().await; + println!("Chain network: {}", bitcoind_blockchain_info.chain); + println!("Latest block height: {}", bitcoind_blockchain_info.latest_height); + + // Create a named bitcoin core wallet + let bitcoind_wallet = bitcoind_client.create_wallet().await; + println!("Successfully created wallet with name: {}", bitcoind_wallet.name); + + // Generate a new address + let bitcoind_new_address = bitcoind_client.get_new_address().await; + println!("Address: {}", bitcoind_new_address); + + // Generate 101 blocks and use the above address as coinbase + bitcoind_client.generate_to_address(101, &bitcoind_new_address).await; + + // Show balance + let balance = bitcoind_client.get_balance().await; + println!("Balance: {}", balance.0); +} diff --git a/lightning-block-sync/src/rpc.rs b/lightning-block-sync/src/rpc.rs index 88199688aef..15a58461642 100644 --- a/lightning-block-sync/src/rpc.rs +++ b/lightning-block-sync/src/rpc.rs @@ -53,12 +53,12 @@ impl RpcClient { match e.get_ref().unwrap().downcast_ref::() { Some(http_error) => match JsonResponse::try_from(http_error.contents.clone()) { Ok(JsonResponse(response)) => response, - Err(_) => Err(e)?, + Err(_) => return Err(e), }, - None => Err(e)?, + None => return Err(e), } }, - Err(e) => Err(e)?, + Err(e) => return Err(e), }; if !response.is_object() { From 560b9740b338772692c1de26b4fc40b896487261 Mon Sep 17 00:00:00 2001 From: Conor Okus Date: Thu, 20 Jan 2022 11:38:25 +0000 Subject: [PATCH 2/5] Improve readability --- .../bitcoind-rpc-client/src/bitcoind_client.rs | 18 ++++++------------ examples/bitcoind-rpc-client/src/convert.rs | 15 +++------------ examples/bitcoind-rpc-client/src/main.rs | 2 +- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/examples/bitcoind-rpc-client/src/bitcoind_client.rs b/examples/bitcoind-rpc-client/src/bitcoind_client.rs index dd6623429a8..1e5b9d80a42 100644 --- a/examples/bitcoind-rpc-client/src/bitcoind_client.rs +++ b/examples/bitcoind-rpc-client/src/bitcoind_client.rs @@ -2,6 +2,7 @@ use std::{sync::{Arc}}; use bitcoin::{BlockHash, Block}; use lightning_block_sync::{rpc::RpcClient, http::{HttpEndpoint}, BlockSource, AsyncBlockSourceResult, BlockHeaderData}; +use serde_json::json; use tokio::sync::Mutex; use crate::convert::{CreateWalletResponse, BlockchainInfoResponse, NewAddressResponse, GetBalanceResponse, GenerateToAddressResponse}; @@ -48,7 +49,7 @@ impl BitcoindClient { let rpc_creditials = base64::encode(format!("{}:{}", rpc_user.clone(), rpc_password.clone())); let mut bitcoind_rpc_client = RpcClient::new(&rpc_creditials, http_endpoint)?; - let _dummy = bitcoind_rpc_client + bitcoind_rpc_client .call_method::("getblockchaininfo", &vec![]) .await .map_err(|_| { @@ -81,7 +82,7 @@ impl BitcoindClient { pub async fn create_wallet(&self) -> CreateWalletResponse { let mut rpc = self.bitcoind_rpc_client.lock().await; - let create_wallet_args = vec![serde_json::json!("test-wallet")]; + let create_wallet_args = vec![json!("test-wallet")]; rpc.call_method::("createwallet", &create_wallet_args).await.unwrap() } @@ -89,7 +90,7 @@ impl BitcoindClient { pub async fn get_new_address(&self) -> String { let mut rpc = self.bitcoind_rpc_client.lock().await; - let addr_args = vec![serde_json::json!("LDK output address")]; + let addr_args = vec![json!("LDK output address")]; let addr = rpc.call_method::("getnewaddress", &addr_args).await.unwrap(); addr.0.to_string() } @@ -103,16 +104,9 @@ impl BitcoindClient { pub async fn generate_to_address(&self, block_num: u64, address: &str) -> GenerateToAddressResponse { let mut rpc = self.bitcoind_rpc_client.lock().await; - let generate_to_address_args = vec![serde_json::json!(block_num), serde_json::json!(address)]; + let generate_to_address_args = vec![json!(block_num), json!(address)]; rpc.call_method::("generatetoaddress", &generate_to_address_args).await.unwrap() } -} - - - - - - - +} \ No newline at end of file diff --git a/examples/bitcoind-rpc-client/src/convert.rs b/examples/bitcoind-rpc-client/src/convert.rs index e37d55b20b3..4d1d905c729 100644 --- a/examples/bitcoind-rpc-client/src/convert.rs +++ b/examples/bitcoind-rpc-client/src/convert.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use bitcoin::{BlockHash, hashes::hex::FromHex}; use lightning_block_sync::http::JsonResponse; -// TryInto implementation specifies the conversion logic from json response to BlockchainInfo object. +/// TryInto implementation specifies the conversion logic from json response to BlockchainInfo object. pub struct BlockchainInfoResponse { pub latest_height: usize, pub latest_blockhash: BlockHash, @@ -54,7 +54,7 @@ impl TryInto for JsonResponse { for item in self.0.as_array().unwrap() { x.push(BlockHash::from_hex(item.as_str().unwrap()) - .unwrap()); + .unwrap()); } Ok(GenerateToAddressResponse(x)) @@ -69,13 +69,4 @@ impl TryInto for JsonResponse { fn try_into(self) -> std::io::Result { Ok(NewAddressResponse(self.0.as_str().unwrap().to_string())) } -} - - - - - - - - - +} \ No newline at end of file diff --git a/examples/bitcoind-rpc-client/src/main.rs b/examples/bitcoind-rpc-client/src/main.rs index a6ff786a00c..f203d89b169 100644 --- a/examples/bitcoind-rpc-client/src/main.rs +++ b/examples/bitcoind-rpc-client/src/main.rs @@ -50,4 +50,4 @@ async fn start_ldk() { // Show balance let balance = bitcoind_client.get_balance().await; println!("Balance: {}", balance.0); -} +} \ No newline at end of file From c1e28bfbc84747870e79ed6c607e80df1c85c79b Mon Sep 17 00:00:00 2001 From: Conor Okus Date: Thu, 20 Jan 2022 11:37:19 +0000 Subject: [PATCH 3/5] Import io directly Co-authored-by: Ram Shandilya --- examples/bitcoind-rpc-client/src/bitcoind_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/bitcoind-rpc-client/src/bitcoind_client.rs b/examples/bitcoind-rpc-client/src/bitcoind_client.rs index 1e5b9d80a42..0734ad3643d 100644 --- a/examples/bitcoind-rpc-client/src/bitcoind_client.rs +++ b/examples/bitcoind-rpc-client/src/bitcoind_client.rs @@ -1,4 +1,4 @@ -use std::{sync::{Arc}}; +use std::{sync::{Arc}, io::{Result, Error, ErrorKind}}; use bitcoin::{BlockHash, Block}; use lightning_block_sync::{rpc::RpcClient, http::{HttpEndpoint}, BlockSource, AsyncBlockSourceResult, BlockHeaderData}; From 0e5751d6ec740b0ebc659b788bb207a484e53286 Mon Sep 17 00:00:00 2001 From: Conor Okus Date: Thu, 20 Jan 2022 17:28:51 +0000 Subject: [PATCH 4/5] Use Amount type for balance --- examples/bitcoind-rpc-client/src/bitcoind_client.rs | 8 ++++---- examples/bitcoind-rpc-client/src/convert.rs | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/bitcoind-rpc-client/src/bitcoind_client.rs b/examples/bitcoind-rpc-client/src/bitcoind_client.rs index 0734ad3643d..a2883096695 100644 --- a/examples/bitcoind-rpc-client/src/bitcoind_client.rs +++ b/examples/bitcoind-rpc-client/src/bitcoind_client.rs @@ -1,4 +1,4 @@ -use std::{sync::{Arc}, io::{Result, Error, ErrorKind}}; +use std::{sync::{Arc}, io}; use bitcoin::{BlockHash, Block}; use lightning_block_sync::{rpc::RpcClient, http::{HttpEndpoint}, BlockSource, AsyncBlockSourceResult, BlockHeaderData}; @@ -44,7 +44,7 @@ impl BlockSource for &BitcoindClient { } impl BitcoindClient { - pub async fn new(host: String, port: u16, rpc_user: String, rpc_password: String) -> std::io::Result { + pub async fn new(host: String, port: u16, rpc_user: String, rpc_password: String) -> io::Result { let http_endpoint = HttpEndpoint::for_host(host.clone()).with_port(port); let rpc_creditials = base64::encode(format!("{}:{}", rpc_user.clone(), rpc_password.clone())); @@ -53,7 +53,7 @@ impl BitcoindClient { .call_method::("getblockchaininfo", &vec![]) .await .map_err(|_| { - std::io::Error::new(std::io::ErrorKind::PermissionDenied, + io::Error::new(io::ErrorKind::PermissionDenied, "Failed to make initial call to bitcoind - please check your RPC user/password and access settings") })?; @@ -68,7 +68,7 @@ impl BitcoindClient { Ok(client) } - pub fn get_new_rpc_client(&self) -> std::io::Result { + pub fn get_new_rpc_client(&self) -> io::Result { let http_endpoint = HttpEndpoint::for_host(self.host.clone()).with_port(self.port); let rpc_credentials = base64::encode(format!("{}:{}", self.rpc_user.clone(), self.rpc_password.clone())); diff --git a/examples/bitcoind-rpc-client/src/convert.rs b/examples/bitcoind-rpc-client/src/convert.rs index 4d1d905c729..a2192dd75fe 100644 --- a/examples/bitcoind-rpc-client/src/convert.rs +++ b/examples/bitcoind-rpc-client/src/convert.rs @@ -1,6 +1,6 @@ use std::convert::TryInto; -use bitcoin::{BlockHash, hashes::hex::FromHex}; +use bitcoin::{Amount, BlockHash, hashes::hex::FromHex}; use lightning_block_sync::http::JsonResponse; /// TryInto implementation specifies the conversion logic from json response to BlockchainInfo object. @@ -36,12 +36,13 @@ impl TryInto for JsonResponse { }) } } -pub struct GetBalanceResponse(pub usize); +pub struct GetBalanceResponse(pub Amount); impl TryInto for JsonResponse { type Error = std::io::Error; fn try_into(self) -> std::io::Result { - Ok(GetBalanceResponse(self.0.as_f64().unwrap() as usize)) + let balance = Amount::from_btc(self.0.as_f64().unwrap()).unwrap(); + Ok(GetBalanceResponse(balance)) } } From 8ce40d5479295d83bbb41a2d8591e23f7e1e821b Mon Sep 17 00:00:00 2001 From: Conor Okus Date: Wed, 26 Jan 2022 17:39:22 +0000 Subject: [PATCH 5/5] Remove reference to BlockSource --- examples/bitcoind-rpc-client/README.md | 8 ++--- .../src/bitcoind_client.rs | 30 +------------------ 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/examples/bitcoind-rpc-client/README.md b/examples/bitcoind-rpc-client/README.md index c8ac4daf187..9ab0777b847 100644 --- a/examples/bitcoind-rpc-client/README.md +++ b/examples/bitcoind-rpc-client/README.md @@ -1,8 +1,8 @@ -# Creates a basic bitcoind client +# Wallet actions with an RPC client This is example shows how you could create a client that directly communicates with bitcoind from LDK. The API is flexible and allows for different ways to implement the interface. -It implements some basic RPC methods that allow you to create a core wallet and print it's balance to stdout. +It implements some basic RPC methods that allow you to create a wallet and print it's balance to stdout. To run with this example you need to have a bitcoin core node running in regtest mode. Get the bitcoin core binary either from the [bitcoin core repo](https://bitcoincore.org/bin/bitcoin-core-0.22.0/) or [build from source](https://github.com/bitcoin/bitcoin/blob/v0.21.1/doc/build-unix.md). @@ -29,9 +29,5 @@ Cargo run The purpose of `RpcClient` is to create a new RPC client connected to the given endpoint with the provided credentials. The credentials should be a base64 encoding of a user name and password joined by a colon, as is required for HTTP basic access authentication. -It implements [BlockSource](https://github.com/rust-bitcoin/rust-lightning/blob/61341df39e90de9d650851a624c0644f5c9dd055/lightning-block-sync/src/lib.rs#L55) against a Bitcoin Core RPC. It is an asynchronous interface for retrieving block headers and data. - -Check out our [LDK sample node](https://github.com/lightningdevkit/ldk-sample) for an integrated example. - diff --git a/examples/bitcoind-rpc-client/src/bitcoind_client.rs b/examples/bitcoind-rpc-client/src/bitcoind_client.rs index a2883096695..74abbb499e6 100644 --- a/examples/bitcoind-rpc-client/src/bitcoind_client.rs +++ b/examples/bitcoind-rpc-client/src/bitcoind_client.rs @@ -1,7 +1,6 @@ use std::{sync::{Arc}, io}; -use bitcoin::{BlockHash, Block}; -use lightning_block_sync::{rpc::RpcClient, http::{HttpEndpoint}, BlockSource, AsyncBlockSourceResult, BlockHeaderData}; +use lightning_block_sync::{rpc::RpcClient, http::{HttpEndpoint}}; use serde_json::json; use tokio::sync::Mutex; @@ -16,33 +15,6 @@ pub struct BitcoindClient { rpc_password: String, } -impl BlockSource for &BitcoindClient { - fn get_header<'a>( - &'a mut self, header_hash: &'a BlockHash, height_hint: Option, - ) -> AsyncBlockSourceResult<'a, BlockHeaderData> { - Box::pin(async move { - let mut rpc = self.bitcoind_rpc_client.lock().await; - rpc.get_header(header_hash, height_hint).await - }) - } - - fn get_block<'a>( - &'a mut self, header_hash: &'a BlockHash, - ) -> AsyncBlockSourceResult<'a, Block> { - Box::pin(async move { - let mut rpc = self.bitcoind_rpc_client.lock().await; - rpc.get_block(header_hash).await - }) - } - - fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<(BlockHash, Option)> { - Box::pin(async move { - let mut rpc = self.bitcoind_rpc_client.lock().await; - rpc.get_best_block().await - }) - } -} - impl BitcoindClient { pub async fn new(host: String, port: u16, rpc_user: String, rpc_password: String) -> io::Result { let http_endpoint = HttpEndpoint::for_host(host.clone()).with_port(port);