Correct feerate units
authorMatt Corallo <git@bluematt.me>
Sat, 26 Jun 2021 17:19:34 +0000 (17:19 +0000)
committerMatt Corallo <git@bluematt.me>
Wed, 30 Jun 2021 03:13:50 +0000 (03:13 +0000)
Lightning, unlike every other Bitcoin-related protocol or API, uses
satoshis-per-1000-weight, instead of
satoshis-per-1000-virtual-bytes. This requires a division by 4 to
calculate the correct fees when passing Bitcoin Core fees into LDK.

src/bitcoind_client.rs
src/convert.rs

index 56b7f1a97b6c53fd5db2916f12880d83917ea14a..90552d915b5702ddc600910aed7506a75082080f 100644 (file)
@@ -60,6 +60,9 @@ impl BlockSource for &BitcoindClient {
        }
 }
 
        }
 }
 
+/// The minimum feerate we are allowed to send, as specify by LDK.
+const MIN_FEERATE: u32 = 253;
+
 impl BitcoindClient {
        pub async fn new(
                host: String, port: u16, rpc_user: String, rpc_password: String,
 impl BitcoindClient {
        pub async fn new(
                host: String, port: u16, rpc_user: String, rpc_password: String,
@@ -76,7 +79,7 @@ impl BitcoindClient {
                                "Failed to make initial call to bitcoind - please check your RPC user/password and access settings")
                        })?;
                let mut fees: HashMap<Target, AtomicU32> = HashMap::new();
                                "Failed to make initial call to bitcoind - please check your RPC user/password and access settings")
                        })?;
                let mut fees: HashMap<Target, AtomicU32> = HashMap::new();
-               fees.insert(Target::Background, AtomicU32::new(253));
+               fees.insert(Target::Background, AtomicU32::new(MIN_FEERATE));
                fees.insert(Target::Normal, AtomicU32::new(2000));
                fees.insert(Target::HighPriority, AtomicU32::new(5000));
                let client = Self {
                fees.insert(Target::Normal, AtomicU32::new(2000));
                fees.insert(Target::HighPriority, AtomicU32::new(5000));
                let client = Self {
@@ -111,12 +114,11 @@ impl BitcoindClient {
                                                )
                                                .await
                                                .unwrap();
                                                )
                                                .await
                                                .unwrap();
-                                       match resp.feerate {
-                                               Some(fee) => fee,
-                                               None => 253,
+                                       match resp.feerate_sat_per_kw {
+                                               Some(feerate) => std::cmp::max(feerate, MIN_FEERATE),
+                                               None => MIN_FEERATE,
                                        }
                                };
                                        }
                                };
-                               // if background_estimate.
 
                                let normal_estimate = {
                                        let mut rpc = rpc_client.lock().await;
 
                                let normal_estimate = {
                                        let mut rpc = rpc_client.lock().await;
@@ -129,8 +131,8 @@ impl BitcoindClient {
                                                )
                                                .await
                                                .unwrap();
                                                )
                                                .await
                                                .unwrap();
-                                       match resp.feerate {
-                                               Some(fee) => fee,
+                                       match resp.feerate_sat_per_kw {
+                                               Some(feerate) => std::cmp::max(feerate, MIN_FEERATE),
                                                None => 2000,
                                        }
                                };
                                                None => 2000,
                                        }
                                };
@@ -147,8 +149,8 @@ impl BitcoindClient {
                                                .await
                                                .unwrap();
 
                                                .await
                                                .unwrap();
 
-                                       match resp.feerate {
-                                               Some(fee) => fee,
+                                       match resp.feerate_sat_per_kw {
+                                               Some(feerate) => std::cmp::max(feerate, MIN_FEERATE),
                                                None => 5000,
                                        }
                                };
                                                None => 5000,
                                        }
                                };
index a652980e3ddbd9a20e6cbf5e54092938a1ffb5ac..64039233e7d5800fc9c1c147c2e800c328ced0fd 100644 (file)
@@ -51,7 +51,7 @@ impl TryInto<NewAddress> for JsonResponse {
 }
 
 pub struct FeeResponse {
 }
 
 pub struct FeeResponse {
-       pub feerate: Option<u32>,
+       pub feerate_sat_per_kw: Option<u32>,
        pub errored: bool,
 }
 
        pub errored: bool,
 }
 
@@ -61,8 +61,13 @@ impl TryInto<FeeResponse> for JsonResponse {
                let errored = !self.0["errors"].is_null();
                Ok(FeeResponse {
                        errored,
                let errored = !self.0["errors"].is_null();
                Ok(FeeResponse {
                        errored,
-                       feerate: match self.0["feerate"].as_f64() {
-                               Some(fee) => Some((fee * 100_000_000.0).round() as u32),
+                       feerate_sat_per_kw: match self.0["feerate"].as_f64() {
+                               // Bitcoin Core gives us a feerate in BTC/KvB, which we need to convert to
+                               // satoshis/KW. Thus, we first multiply by 10^8 to get satoshis, then divide by 4
+                               // to convert virtual-bytes into weight units.
+                               Some(feerate_btc_per_kvbyte) => {
+                                       Some((feerate_btc_per_kvbyte * 100_000_000.0 / 4.0).round() as u32)
+                               }
                                None => None,
                        },
                })
                                None => None,
                        },
                })