Skip to content

Commit 7eee05e

Browse files
authored
small perf improvements and mempool link (#390)
* small perf improvements * add mempool link
1 parent b6fabff commit 7eee05e

File tree

8 files changed

+101
-38
lines changed

8 files changed

+101
-38
lines changed

src/blockchain/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ pub enum Error {
2626
#[error("Blockchain is invalid")]
2727
BlockchainInvalid,
2828

29+
/// If there is an error deserializing and decrypting blocks
30+
#[error("Could not parse and decrypt blockchain")]
31+
BlockchainParse,
32+
2933
/// If certain block is not valid and can't be added
3034
#[error("Block is invalid")]
3135
BlockInvalid,

src/external/bitcoin.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ pub trait BitcoinClientApi: Send + Sync {
5656
pkey: &bitcoin::PrivateKey,
5757
pkey_to_combine: &bitcoin::PrivateKey,
5858
) -> Result<String>;
59+
60+
fn get_mempool_link_for_address(&self, address: &str) -> String;
5961
}
6062

6163
#[derive(Clone)]
@@ -76,6 +78,17 @@ impl BitcoinClient {
7678
}
7779
}
7880
}
81+
82+
pub fn link_url(&self, path: &str) -> String {
83+
match CONFIG.bitcoin_network() {
84+
Network::Bitcoin => {
85+
format!("https://blockstream.info{path}")
86+
}
87+
_ => {
88+
format!("https://blockstream.info/testnet{path}")
89+
}
90+
}
91+
}
7992
}
8093

8194
#[async_trait]
@@ -169,6 +182,10 @@ impl BitcoinClientApi for BitcoinClient {
169182
.map_err(Error::from)?;
170183
Ok(bitcoin::PrivateKey::new(private_key_bill, CONFIG.bitcoin_network()).to_string())
171184
}
185+
186+
fn get_mempool_link_for_address(&self, address: &str) -> String {
187+
self.link_url(&format!("/address/{address}"))
188+
}
172189
}
173190

174191
/// Fields documented at https://github.com/Blockstream/esplora/blob/master/API.md#addresses

src/external/time.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub struct TimeApi {
1010

1111
impl TimeApi {
1212
pub async fn get_atomic_time() -> Self {
13-
match reqwest::get("https://api.timezonedb.com/v2.1/get-time-zone?key=RQ6ZFDOXPVLR&format=json&by=zone&zone=Europe/Vienna")
13+
match reqwest::get("https://vip.timezonedb.com/v2.1/get-time-zone?key=AY3Q7V1JPPNX&format=json&fields=timestamp&by=zone&zone=UTC")
1414
.await
1515
{
1616
Err(e) => {

src/persistence/db/notification.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,10 @@ mod tests {
314314
.await
315315
.expect("could not create notification");
316316

317-
let mut filter = NotificationFilter::default();
318-
filter.active = Some(true);
317+
let filter = NotificationFilter {
318+
active: Some(true),
319+
..Default::default()
320+
};
319321
let all = store
320322
.list(filter.clone())
321323
.await

src/service/bill_service.rs

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use crate::{error, CONFIG};
4141
use async_trait::async_trait;
4242
use borsh::to_vec;
4343
use borsh_derive::{BorshDeserialize, BorshSerialize};
44+
use futures::future::try_join_all;
4445
use log::info;
4546
#[cfg(test)]
4647
use mockall::automock;
@@ -934,13 +935,30 @@ impl BillService {
934935
.await?;
935936
let first_version_bill = chain.get_first_version_bill(&bill_keys)?;
936937
let time_of_drawing = first_version_bill.signing_timestamp;
937-
let bill_participants = chain.get_all_nodes_from_bill(&bill_keys)?;
938-
let endorsements_count = chain.get_endorsements_count();
939938

939+
// handle expensive deserialization and decryption logic in parallel on a blocking thread
940+
// pool as not to block the task queue
941+
let chain_clone = chain.clone();
942+
let keys_clone = bill_keys.clone();
943+
let bill_participants_handle =
944+
tokio::task::spawn_blocking(move || chain_clone.get_all_nodes_from_bill(&keys_clone));
945+
let chain_clone = chain.clone();
946+
let keys_clone = bill_keys.clone();
947+
let chain_to_return_handle = tokio::task::spawn_blocking(move || {
948+
BillBlockchainToReturn::new(chain_clone, &keys_clone)
949+
});
950+
let (bill_participants_res, chain_to_return_res) =
951+
tokio::try_join!(bill_participants_handle, chain_to_return_handle).map_err(|e| {
952+
error!("couldn't get data from bill chain blocks {bill_id}: {e}");
953+
Error::Blockchain(blockchain::Error::BlockchainParse)
954+
})?;
955+
let bill_participants = bill_participants_res?;
956+
let chain_to_return = chain_to_return_res?;
957+
958+
let endorsements_count = chain.get_endorsements_count();
940959
let mut in_recourse = false;
941960
let mut link_to_pay_recourse = "".to_string();
942961
let mut link_for_buy = "".to_string();
943-
let chain_to_return = BillBlockchainToReturn::new(chain.clone(), &bill_keys)?;
944962
let endorsed = chain.block_with_operation_code_exists(BillOpCode::Endorse);
945963
let accepted = chain.block_with_operation_code_exists(BillOpCode::Accept);
946964
let last_offer_to_sell_block_waiting_for_payment =
@@ -1038,6 +1056,9 @@ impl BillService {
10381056
let address_to_pay = self
10391057
.bitcoin_client
10401058
.get_address_to_pay(&bill_keys.public_key, holder_public_key)?;
1059+
let mempool_link_for_address_to_pay = self
1060+
.bitcoin_client
1061+
.get_mempool_link_for_address(&address_to_pay);
10411062
let mut paid = false;
10421063
if requested_to_pay {
10431064
paid = self.store.is_paid(&bill.id).await?;
@@ -1083,6 +1104,7 @@ impl BillService {
10831104
recoursee,
10841105
link_to_pay_recourse,
10851106
address_to_pay,
1107+
mempool_link_for_address_to_pay,
10861108
chain_of_blocks: chain_to_return,
10871109
files: bill.files,
10881110
active_notification,
@@ -1838,50 +1860,57 @@ impl BillServiceApi for BillService {
18381860
}
18391861

18401862
async fn get_bills_from_all_identities(&self) -> Result<Vec<BitcreditBillToReturn>> {
1841-
let mut res = vec![];
18421863
let bill_ids = self.store.get_ids().await?;
18431864
let identity = self.identity_store.get().await?;
1844-
let current_timestamp = external::time::TimeApi::get_atomic_time().await.timestamp;
1845-
1846-
for bill_id in bill_ids {
1847-
let bill = self
1848-
.get_full_bill(&bill_id, &identity, &identity.node_id, current_timestamp)
1849-
.await?;
1850-
res.push(bill)
1851-
}
1865+
let current_timestamp = util::date::now().timestamp() as u64;
1866+
1867+
let tasks = bill_ids.iter().map(|id| {
1868+
let identity_clone = identity.clone();
1869+
async move {
1870+
self.get_full_bill(
1871+
id,
1872+
&identity_clone,
1873+
&identity_clone.node_id,
1874+
current_timestamp,
1875+
)
1876+
.await
1877+
}
1878+
});
1879+
let bills = try_join_all(tasks).await?;
18521880

1853-
Ok(res)
1881+
Ok(bills)
18541882
}
18551883

18561884
async fn get_bills(
18571885
&self,
18581886
current_identity_node_id: &str,
18591887
) -> Result<Vec<BitcreditBillToReturn>> {
1860-
let mut res = vec![];
18611888
let bill_ids = self.store.get_ids().await?;
18621889
let identity = self.identity_store.get().await?;
1863-
let current_timestamp = external::time::TimeApi::get_atomic_time().await.timestamp;
1864-
1865-
for bill_id in bill_ids {
1866-
let bill = self
1867-
.get_full_bill(
1868-
&bill_id,
1869-
&identity,
1890+
let current_timestamp = util::date::now().timestamp() as u64;
1891+
1892+
let tasks = bill_ids.iter().map(|id| {
1893+
let identity_clone = identity.clone();
1894+
async move {
1895+
self.get_full_bill(
1896+
id,
1897+
&identity_clone,
18701898
current_identity_node_id,
18711899
current_timestamp,
18721900
)
1873-
.await?;
1874-
// filter for currently active identity
1875-
if bill
1876-
.bill_participants
1877-
.iter()
1878-
.any(|p| p == current_identity_node_id)
1879-
{
1880-
res.push(bill);
1901+
.await
18811902
}
1882-
}
1883-
1884-
Ok(res)
1903+
});
1904+
let bills = try_join_all(tasks).await?;
1905+
1906+
Ok(bills
1907+
.into_iter()
1908+
.filter(|b| {
1909+
b.bill_participants
1910+
.iter()
1911+
.any(|p| p == current_identity_node_id)
1912+
})
1913+
.collect())
18851914
}
18861915

18871916
async fn get_combined_bitcoin_key_for_bill(
@@ -3233,6 +3262,7 @@ pub struct BitcreditBillToReturn {
32333262
pub link_to_pay: String,
32343263
pub link_to_pay_recourse: String,
32353264
pub address_to_pay: String,
3265+
pub mempool_link_for_address_to_pay: String,
32363266
pub chain_of_blocks: BillBlockchainToReturn,
32373267
pub files: Vec<File>,
32383268
/// The currently active notification for this bill if any
@@ -3479,6 +3509,13 @@ pub mod tests {
34793509
bitcoin_client
34803510
.expect_get_address_to_pay()
34813511
.returning(|_, _| Ok(String::from("1Jfn2nZcJ4T7bhE8FdMRz8T3P3YV4LsWn2")));
3512+
bitcoin_client
3513+
.expect_get_mempool_link_for_address()
3514+
.returning(|_| {
3515+
String::from(
3516+
"http://blockstream.info/testnet/address/1Jfn2nZcJ4T7bhE8FdMRz8T3P3YV4LsWn2",
3517+
)
3518+
});
34823519
bitcoin_client.expect_generate_link_to_pay().returning(|_,_,_| String::from("bitcoin:1Jfn2nZcJ4T7bhE8FdMRz8T3P3YV4LsWn2?amount=0.01&message=Payment in relation to bill some bill"));
34833520
BillService::new(
34843521
Client::new(

src/service/contact_service.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub trait ContactServiceApi: Send + Sync {
6363
) -> Result<Contact>;
6464

6565
/// Returns whether a given npub (as hex) is in our contact list.
66+
#[allow(dead_code)]
6667
async fn is_known_npub(&self, npub: &str) -> Result<bool>;
6768

6869
/// opens and decrypts the attached file from the given contact

src/service/notification_service/default_service.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -782,8 +782,10 @@ mod tests {
782782
let mut mock_store = MockNotificationStoreApi::new();
783783
let result = Notification::new_bill_notification("bill_id", "node_id", "desc", None);
784784
let returning = result.clone();
785-
let mut filter = NotificationFilter::default();
786-
filter.active = Some(true);
785+
let filter = NotificationFilter {
786+
active: Some(true),
787+
..Default::default()
788+
};
787789
mock_store
788790
.expect_list()
789791
.with(eq(filter.clone()))

src/web/handlers/bill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ pub async fn bill_detail(
310310
state: &State<ServiceContext>,
311311
id: &str,
312312
) -> Result<Json<BitcreditBillToReturn>> {
313-
let current_timestamp = external::time::TimeApi::get_atomic_time().await.timestamp;
313+
let current_timestamp = util::date::now().timestamp() as u64;
314314
let identity = state.identity_service.get_identity().await?;
315315
let bill_detail = state
316316
.bill_service

0 commit comments

Comments
 (0)