Skip to content

Commit 9023c5d

Browse files
pre-cleanup
1 parent ce9a3cf commit 9023c5d

File tree

4 files changed

+219
-101
lines changed

4 files changed

+219
-101
lines changed

src/bitcoind_client.rs

Lines changed: 156 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::convert::{BlockchainInfo, FeeResponse, FundedTx, NewAddress, RawTx, SignedTx};
22
use base64;
3-
use bitcoin::blockdata::block::{Block, BlockHeader};
3+
use bitcoin::blockdata::block::Block;
44
use bitcoin::blockdata::transaction::Transaction;
55
use bitcoin::consensus::encode;
66
use bitcoin::hash_types::BlockHash;
@@ -12,82 +12,161 @@ use lightning_block_sync::{AsyncBlockSourceResult, BlockHeaderData, BlockSource}
1212
use serde_json;
1313
use std::collections::HashMap;
1414
use std::str::FromStr;
15-
use std::sync::{Arc, Mutex};
15+
use std::sync::atomic::{AtomicU32, Ordering};
16+
use std::sync::Arc;
17+
use std::time::Duration;
18+
use tokio::sync::Mutex;
1619

1720
pub struct BitcoindClient {
18-
// bitcoind_rpc_client: RpcClient,
19-
bitcoind_rpc_client: Mutex<RpcClient>,
21+
bitcoind_rpc_client: Arc<Mutex<RpcClient>>,
2022
host: String,
2123
port: u16,
2224
rpc_user: String,
2325
rpc_password: String,
24-
fees: Arc<HashMap<String, u32>>,
26+
fees: Arc<HashMap<Target, AtomicU32>>,
27+
}
28+
29+
#[derive(Clone, Eq, Hash, PartialEq)]
30+
pub enum Target {
31+
Background,
32+
Normal,
33+
HighPriority,
2534
}
2635

2736
impl BlockSource for &BitcoindClient {
2837
fn get_header<'a>(
2938
&'a mut self, header_hash: &'a BlockHash, height_hint: Option<u32>,
3039
) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
31-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
32-
// self.bitcoind_rpc_client.get_header(header_hash, height_hint)
33-
rpc.get_header(header_hash, height_hint)
40+
Box::pin(async move {
41+
let mut rpc = self.bitcoind_rpc_client.lock().await;
42+
rpc.get_header(header_hash, height_hint).await
43+
})
3444
}
45+
3546
fn get_block<'a>(
3647
&'a mut self, header_hash: &'a BlockHash,
3748
) -> AsyncBlockSourceResult<'a, Block> {
38-
// self.bitcoind_rpc_client.get_block(header_hash)
39-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
40-
rpc.get_block(header_hash)
49+
Box::pin(async move {
50+
let mut rpc = self.bitcoind_rpc_client.lock().await;
51+
rpc.get_block(header_hash).await
52+
})
4153
}
54+
4255
fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<(BlockHash, Option<u32>)> {
43-
// self.bitcoind_rpc_client.get_best_block()
44-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
45-
rpc.get_best_block()
56+
Box::pin(async move {
57+
let mut rpc = self.bitcoind_rpc_client.lock().await;
58+
rpc.get_best_block().await
59+
})
4660
}
4761
}
4862

4963
impl BitcoindClient {
50-
pub fn new(
64+
pub async fn new(
5165
host: String, port: u16, rpc_user: String, rpc_password: String,
5266
) -> std::io::Result<Self> {
5367
let http_endpoint = HttpEndpoint::for_host(host.clone()).with_port(port);
5468
let rpc_credentials =
5569
base64::encode(format!("{}:{}", rpc_user.clone(), rpc_password.clone()));
5670
let bitcoind_rpc_client = RpcClient::new(&rpc_credentials, http_endpoint)?;
71+
let mut fees: HashMap<Target, AtomicU32> = HashMap::new();
72+
fees.insert(Target::Background, AtomicU32::new(253));
73+
fees.insert(Target::Normal, AtomicU32::new(2000));
74+
fees.insert(Target::HighPriority, AtomicU32::new(5000));
5775
let client = Self {
58-
// bitcoind_rpc_client,
59-
bitcoind_rpc_client: Mutex::new(bitcoind_rpc_client),
76+
bitcoind_rpc_client: Arc::new(Mutex::new(bitcoind_rpc_client)),
6077
host,
6178
port,
6279
rpc_user,
6380
rpc_password,
64-
fees: Arc::new(HashMap::new()),
81+
fees: Arc::new(fees),
6582
};
66-
client.poll_for_fee_estimates();
83+
BitcoindClient::poll_for_fee_estimates(
84+
client.fees.clone(),
85+
client.bitcoind_rpc_client.clone(),
86+
)
87+
.await;
6788
Ok(client)
6889
}
6990

70-
fn poll_for_fee_estimates(&self) {
71-
let bitcoind_rpc_client = self.get_new_rpc_client().unwrap();
72-
let mut rpc = self.get_new_rpc_client().unwrap();
73-
let mut fees = self.fees.clone();
74-
tokio::spawn(async {
91+
async fn poll_for_fee_estimates(
92+
fees: Arc<HashMap<Target, AtomicU32>>, rpc_client: Arc<Mutex<RpcClient>>,
93+
) {
94+
tokio::spawn(async move {
7595
loop {
76-
let background_conf_target = serde_json::json!(144);
77-
let background_estimate_mode = serde_json::json!("ECONOMICAL");
78-
79-
let background_estimate = bitcoind_rpc_client
80-
.call_method::<FeeResponse>(
81-
"estimatesmartfee",
82-
&vec![background_conf_target, background_estimate_mode],
83-
)
84-
.await
85-
.unwrap();
86-
match background_estimate.feerate {
87-
Some(fee) => fees.insert("background".to_string(), fee),
88-
None => fees.insert("background".to_string(), 253),
96+
let background_estimate = {
97+
let mut rpc = rpc_client.lock().await;
98+
let background_conf_target = serde_json::json!(144);
99+
let background_estimate_mode = serde_json::json!("ECONOMICAL");
100+
let resp = rpc
101+
.call_method::<FeeResponse>(
102+
"estimatesmartfee",
103+
&vec![background_conf_target, background_estimate_mode],
104+
)
105+
.await
106+
.unwrap();
107+
match resp.feerate {
108+
Some(fee) => fee,
109+
None => 253,
110+
}
111+
};
112+
// if background_estimate.
113+
114+
let normal_estimate = {
115+
let mut rpc = rpc_client.lock().await;
116+
let normal_conf_target = serde_json::json!(18);
117+
let normal_estimate_mode = serde_json::json!("ECONOMICAL");
118+
let resp = rpc
119+
.call_method::<FeeResponse>(
120+
"estimatesmartfee",
121+
&vec![normal_conf_target, normal_estimate_mode],
122+
)
123+
.await
124+
.unwrap();
125+
match resp.feerate {
126+
Some(fee) => fee,
127+
None => 2000,
128+
}
89129
};
90-
// fees.insert("background".to_string(), background_estimate);
130+
131+
let high_prio_estimate = {
132+
let mut rpc = rpc_client.lock().await;
133+
let high_prio_conf_target = serde_json::json!(6);
134+
let high_prio_estimate_mode = serde_json::json!("CONSERVATIVE");
135+
let resp = rpc
136+
.call_method::<FeeResponse>(
137+
"estimatesmartfee",
138+
&vec![high_prio_conf_target, high_prio_estimate_mode],
139+
)
140+
.await
141+
.unwrap();
142+
143+
match resp.feerate {
144+
Some(fee) => fee,
145+
None => 5000,
146+
}
147+
};
148+
149+
fees.get(&Target::Background)
150+
.unwrap()
151+
.store(background_estimate, Ordering::Release);
152+
fees.get(&Target::Normal).unwrap().store(normal_estimate, Ordering::Release);
153+
fees.get(&Target::HighPriority)
154+
.unwrap()
155+
.store(high_prio_estimate, Ordering::Release);
156+
// match fees.get(Target::Background) {
157+
// Some(fee) => fee.store(background_estimate, Ordering::Release),
158+
// None =>
159+
// }
160+
// if let Some(fee) = background_estimate.feerate {
161+
// fees.get("background").unwrap().store(fee, Ordering::Release);
162+
// }
163+
// if let Some(fee) = normal_estimate.feerate {
164+
// fees.get("normal").unwrap().store(fee, Ordering::Release);
165+
// }
166+
// if let Some(fee) = high_prio_estimate.feerate {
167+
// fees.get("high_prio").unwrap().store(fee, Ordering::Release);
168+
// }
169+
tokio::time::sleep(Duration::from_secs(60)).await;
91170
}
92171
});
93172
}
@@ -99,58 +178,68 @@ impl BitcoindClient {
99178
RpcClient::new(&rpc_credentials, http_endpoint)
100179
}
101180

102-
// pub async fn create_raw_transaction(&mut self, outputs: Vec<HashMap<String, f64>>) -> RawTx {
103181
pub async fn create_raw_transaction(&self, outputs: Vec<HashMap<String, f64>>) -> RawTx {
104-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
182+
let mut rpc = self.bitcoind_rpc_client.lock().await;
105183

106184
let outputs_json = serde_json::json!(outputs);
107-
// self.bitcoind_rpc_client
108185
rpc.call_method::<RawTx>("createrawtransaction", &vec![serde_json::json!([]), outputs_json])
109186
.await
110187
.unwrap()
111188
}
112189

113-
// pub async fn fund_raw_transaction(&mut self, raw_tx: RawTx) -> FundedTx {
114190
pub async fn fund_raw_transaction(&self, raw_tx: RawTx) -> FundedTx {
115-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
191+
let mut rpc = self.bitcoind_rpc_client.lock().await;
116192

117193
let raw_tx_json = serde_json::json!(raw_tx.0);
118-
// self.bitcoind_rpc_client.call_method("fundrawtransaction", &[raw_tx_json]).await.unwrap()
119194
rpc.call_method("fundrawtransaction", &[raw_tx_json]).await.unwrap()
120195
}
121196

122-
// pub async fn sign_raw_transaction_with_wallet(&mut self, tx_hex: String) -> SignedTx {
197+
pub async fn send_raw_transaction(&self, raw_tx: RawTx) {
198+
let mut rpc = self.bitcoind_rpc_client.lock().await;
199+
200+
let raw_tx_json = serde_json::json!(raw_tx.0);
201+
rpc.call_method::<RawTx>("sendrawtransaction", &[raw_tx_json]).await.unwrap();
202+
}
203+
123204
pub async fn sign_raw_transaction_with_wallet(&self, tx_hex: String) -> SignedTx {
124-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
205+
let mut rpc = self.bitcoind_rpc_client.lock().await;
125206

126207
let tx_hex_json = serde_json::json!(tx_hex);
127-
// self.bitcoind_rpc_client
128208
rpc.call_method("signrawtransactionwithwallet", &vec![tx_hex_json]).await.unwrap()
129209
}
130210

131-
// pub async fn get_new_address(&mut self) -> Address {
132211
pub async fn get_new_address(&self) -> Address {
133-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
212+
let mut rpc = self.bitcoind_rpc_client.lock().await;
134213

135214
let addr_args = vec![serde_json::json!("LDK output address")];
136-
// let addr = self
137-
// .bitcoind_rpc_client
138215
let addr = rpc.call_method::<NewAddress>("getnewaddress", &addr_args).await.unwrap();
139216
Address::from_str(addr.0.as_str()).unwrap()
140217
}
141218

142-
// pub async fn get_blockchain_info(&mut self) -> BlockchainInfo {
143219
pub async fn get_blockchain_info(&self) -> BlockchainInfo {
144-
let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
145-
146-
// self.bitcoind_rpc_client
220+
let mut rpc = self.bitcoind_rpc_client.lock().await;
147221
rpc.call_method::<BlockchainInfo>("getblockchaininfo", &vec![]).await.unwrap()
148222
}
149223
}
150224

151225
impl FeeEstimator for BitcoindClient {
152226
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
153-
253
227+
match confirmation_target {
228+
ConfirmationTarget::Background => {
229+
self.fees.get(&Target::Background).unwrap().load(Ordering::Acquire)
230+
}
231+
ConfirmationTarget::Normal => {
232+
self.fees.get(&Target::Normal).unwrap().load(Ordering::Acquire)
233+
}
234+
ConfirmationTarget::HighPriority => {
235+
self.fees.get(&Target::HighPriority).unwrap().load(Ordering::Acquire)
236+
}
237+
}
238+
// self.fees.g
239+
// 253
240+
// match confirmation_target {
241+
// ConfirmationTarget::Background =>
242+
// }
154243
// let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
155244

156245
// let (conf_target, estimate_mode, default) = match confirmation_target {
@@ -188,6 +277,17 @@ impl FeeEstimator for BitcoindClient {
188277

189278
impl BroadcasterInterface for BitcoindClient {
190279
fn broadcast_transaction(&self, tx: &Transaction) {
280+
let bitcoind_rpc_client = self.bitcoind_rpc_client.clone();
281+
let tx_serialized = serde_json::json!(encode::serialize_hex(tx));
282+
tokio::spawn(async move {
283+
let mut rpc = bitcoind_rpc_client.lock().await;
284+
rpc.call_method::<RawTx>("sendrawtransaction", &vec![tx_serialized]).await.unwrap();
285+
});
286+
// let bitcoind_rpc_client = self.bitcoind_rpc_client.clone();
287+
// tokio::spawn(async move {
288+
// let rpc = bitcoind_rpc_client.lock().await;
289+
// rpc.call_method::<R>
290+
// });
191291
// let mut rpc = self.bitcoind_rpc_client.lock().unwrap();
192292
// let runtime = self.runtime.lock().unwrap();
193293

src/cli.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use std::path::Path;
2626
use std::str::FromStr;
2727
use std::sync::Arc;
2828
use std::time::Duration;
29-
use tokio::runtime::Handle;
3029
use tokio::sync::mpsc;
3130

3231
pub(crate) struct LdkUserInfo {

src/convert.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ impl TryInto<NewAddress> for JsonResponse {
5252

5353
pub struct FeeResponse {
5454
pub feerate: Option<u32>,
55+
// pub errors: Array<String>,
5556
pub errored: bool,
5657
}
5758

@@ -61,11 +62,13 @@ impl TryInto<FeeResponse> for JsonResponse {
6162
let errored = !self.0["errors"].is_null();
6263
Ok(FeeResponse {
6364
errored,
64-
feerate: match errored {
65-
true => None,
66-
// The feerate from bitcoind is in BTC/kb, and we want satoshis/kb.
67-
false => Some((self.0["feerate"].as_f64().unwrap() * 100_000_000.0).round() as u32),
68-
},
65+
feerate: match self.0["feerate"].as_f64() {
66+
Some(fee) => Some((fee * 100_000_000.0).round() as u32),
67+
None => None
68+
}
69+
// true => None,
70+
// // The feerate from bitcoind is in BTC/kb, and we want satoshis/kb.
71+
// false => Some((self.0["feerate"].as_f64().unwrap() * 100_000_000.0).round() as u32),
6972
})
7073
}
7174
}

0 commit comments

Comments
 (0)