-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move blindbit backend to sp-client behind feature
- Loading branch information
Showing
12 changed files
with
292 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
use std::{ops::RangeInclusive, pin::Pin, sync::Arc}; | ||
|
||
use async_trait::async_trait; | ||
use bitcoin::{absolute::Height, Amount}; | ||
use futures::{stream, Stream, StreamExt}; | ||
use reqwest::Url; | ||
|
||
use anyhow::Result; | ||
|
||
use crate::{backend::blindbit::BlindbitClient, BlockData, ChainBackend, SpentIndexData, UtxoData}; | ||
|
||
const CONCURRENT_FILTER_REQUESTS: usize = 200; | ||
|
||
pub struct BlindbitBackend { | ||
client: BlindbitClient, | ||
} | ||
|
||
impl BlindbitBackend { | ||
pub fn new(blindbit_url: String) -> Result<Self> { | ||
let host_url = Url::parse(&blindbit_url)?; | ||
Ok(Self { | ||
client: BlindbitClient::new(host_url), | ||
}) | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl ChainBackend for BlindbitBackend { | ||
/// High-level function to get block data for a range of blocks. | ||
/// Block data includes all the information needed to determine if a block is relevant for scanning, | ||
/// but does not include utxos, or spent index. | ||
/// These need to be fetched separately afterwards, if it is determined this block is relevant. | ||
fn get_block_data_for_range( | ||
&self, | ||
range: RangeInclusive<u32>, | ||
dust_limit: Amount, | ||
) -> Pin<Box<dyn Stream<Item = Result<BlockData>> + Send>> { | ||
let client = Arc::new(self.client.clone()); | ||
|
||
let res = stream::iter(range) | ||
.map(move |n| { | ||
let client = client.clone(); | ||
|
||
async move { | ||
let blkheight = Height::from_consensus(n)?; | ||
let tweaks = client.tweak_index(blkheight, dust_limit).await?; | ||
let new_utxo_filter = client.filter_new_utxos(blkheight).await?; | ||
let spent_filter = client.filter_spent(blkheight).await?; | ||
let blkhash = new_utxo_filter.block_hash; | ||
Ok(BlockData { | ||
blkheight, | ||
blkhash, | ||
tweaks, | ||
new_utxo_filter: new_utxo_filter.into(), | ||
spent_filter: spent_filter.into(), | ||
}) | ||
} | ||
}) | ||
.buffered(CONCURRENT_FILTER_REQUESTS); | ||
|
||
Box::pin(res) | ||
} | ||
|
||
async fn spent_index(&self, block_height: Height) -> Result<SpentIndexData> { | ||
self.client.spent_index(block_height).await.map(Into::into) | ||
} | ||
|
||
async fn utxos(&self, block_height: Height) -> Result<Vec<UtxoData>> { | ||
Ok(self | ||
.client | ||
.utxos(block_height) | ||
.await? | ||
.into_iter() | ||
.map(Into::into) | ||
.collect()) | ||
} | ||
|
||
async fn block_height(&self) -> Result<Height> { | ||
self.client.block_height().await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
mod backend; | ||
|
||
pub use backend::BlindbitBackend; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
use std::time::Duration; | ||
|
||
use bitcoin::{absolute::Height, secp256k1::PublicKey, Amount}; | ||
use reqwest::{Client, Url}; | ||
|
||
use anyhow::Result; | ||
|
||
use super::structs::{BlockHeightResponse, FilterResponse, SpentIndexResponse, UtxoResponse}; | ||
|
||
#[derive(Clone)] | ||
pub struct BlindbitClient { | ||
client: Client, | ||
host_url: Url, | ||
} | ||
|
||
impl BlindbitClient { | ||
pub fn new(mut host_url: Url) -> Self { | ||
let client = reqwest::Client::new(); | ||
|
||
// we need a trailing slash, if not present we append it | ||
if !host_url.path().ends_with('/') { | ||
host_url.set_path(&format!("{}/", host_url.path())); | ||
} | ||
|
||
BlindbitClient { client, host_url } | ||
} | ||
pub async fn block_height(&self) -> Result<Height> { | ||
let url = self.host_url.join("block-height")?; | ||
|
||
let res = self | ||
.client | ||
.get(url) | ||
.timeout(Duration::from_secs(5)) | ||
.send() | ||
.await?; | ||
let blkheight: BlockHeightResponse = serde_json::from_str(&res.text().await?)?; | ||
Ok(blkheight.block_height) | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub async fn tweaks(&self, block_height: Height) -> Result<Vec<PublicKey>> { | ||
let url = self.host_url.join(&format!("tweaks/{}", block_height))?; | ||
|
||
let res = self.client.get(url).send().await?; | ||
Ok(serde_json::from_str(&res.text().await?)?) | ||
} | ||
|
||
pub async fn tweak_index( | ||
&self, | ||
block_height: Height, | ||
dust_limit: Amount, | ||
) -> Result<Vec<PublicKey>> { | ||
let url = self | ||
.host_url | ||
.join(&format!("tweak-index/{}", block_height))?; | ||
|
||
let res = self | ||
.client | ||
.get(url) | ||
.query(&[("dustLimit", format!("{}", dust_limit.to_sat()))]) | ||
.send() | ||
.await?; | ||
Ok(serde_json::from_str(&res.text().await?)?) | ||
} | ||
|
||
pub async fn utxos(&self, block_height: Height) -> Result<Vec<UtxoResponse>> { | ||
let url = self.host_url.join(&format!("utxos/{}", block_height))?; | ||
let res = self.client.get(url).send().await?; | ||
|
||
Ok(serde_json::from_str(&res.text().await?)?) | ||
} | ||
|
||
pub async fn spent_index(&self, block_height: Height) -> Result<SpentIndexResponse> { | ||
let url = self | ||
.host_url | ||
.join(&format!("spent-index/{}", block_height))?; | ||
let res = self.client.get(url).send().await?; | ||
|
||
Ok(serde_json::from_str(&res.text().await?)?) | ||
} | ||
|
||
pub async fn filter_new_utxos(&self, block_height: Height) -> Result<FilterResponse> { | ||
let url = self | ||
.host_url | ||
.join(&format!("filter/new-utxos/{}", block_height))?; | ||
|
||
let res = self.client.get(url).send().await?; | ||
|
||
Ok(serde_json::from_str(&res.text().await?)?) | ||
} | ||
|
||
pub async fn filter_spent(&self, block_height: Height) -> Result<FilterResponse> { | ||
let url = self | ||
.host_url | ||
.join(&format!("filter/spent/{}", block_height))?; | ||
|
||
let res = self.client.get(url).send().await?; | ||
|
||
Ok(serde_json::from_str(&res.text().await?)?) | ||
} | ||
|
||
#[allow(dead_code)] | ||
pub async fn forward_tx(&self) { | ||
// not needed | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
mod client; | ||
pub mod structs; | ||
|
||
pub use client::BlindbitClient; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
use bitcoin::{absolute::Height, Amount, BlockHash, ScriptBuf, Txid}; | ||
use serde::Deserialize; | ||
|
||
use crate::{FilterData, SpentIndexData, UtxoData}; | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct BlockHeightResponse { | ||
pub block_height: Height, | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct UtxoResponse { | ||
pub txid: Txid, | ||
pub vout: u32, | ||
pub value: Amount, | ||
pub scriptpubkey: ScriptBuf, | ||
pub block_height: Height, | ||
pub block_hash: BlockHash, | ||
pub timestamp: i32, | ||
pub spent: bool, | ||
} | ||
|
||
impl From<UtxoResponse> for UtxoData { | ||
fn from(value: UtxoResponse) -> Self { | ||
Self { | ||
txid: value.txid, | ||
vout: value.vout, | ||
value: value.value, | ||
scriptpubkey: value.scriptpubkey, | ||
spent: value.spent, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct SpentIndexResponse { | ||
pub block_hash: BlockHash, | ||
pub data: Vec<MyHex>, | ||
} | ||
|
||
impl From<SpentIndexResponse> for SpentIndexData { | ||
fn from(value: SpentIndexResponse) -> Self { | ||
Self { | ||
data: value.data.into_iter().map(|x| x.hex).collect(), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Deserialize, Debug)] | ||
#[serde(transparent)] | ||
pub struct MyHex { | ||
#[serde(with = "hex::serde")] | ||
pub hex: Vec<u8>, | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct FilterResponse { | ||
pub block_hash: BlockHash, | ||
pub block_height: Height, | ||
pub data: MyHex, | ||
pub filter_type: i32, | ||
} | ||
|
||
impl From<FilterResponse> for FilterData { | ||
fn from(value: FilterResponse) -> Self { | ||
Self { | ||
block_hash: value.block_hash, | ||
data: value.data.hex, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
mod backend; | ||
mod client; | ||
|
||
pub use backend::BlindbitBackend; | ||
pub use client::BlindbitClient; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
mod backend; | ||
#[cfg(feature = "blindbit-backend")] | ||
mod blindbit; | ||
mod structs; | ||
|
||
pub use backend::ChainBackend; | ||
pub use structs::*; | ||
|
||
#[cfg(feature = "blindbit-backend")] | ||
pub use blindbit::BlindbitBackend; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
pub mod constants; | ||
mod backend; | ||
mod client; | ||
pub mod constants; | ||
mod scanner; | ||
mod backend; | ||
mod updater; | ||
|
||
pub use bitcoin; | ||
pub use silentpayments; | ||
|
||
pub use backend::ChainBackend; | ||
pub use backend::*; | ||
pub use client::*; | ||
pub use scanner::SpScanner; | ||
pub use updater::Updater; | ||
pub use client::SpClient; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters