From 912a4b1d329853e7e1d8e938e84016a4d67a4143 Mon Sep 17 00:00:00 2001 From: michael1011 Date: Sat, 29 Jun 2024 16:40:10 +0200 Subject: [PATCH 1/2] chore: fix linter warnings --- .github/workflows/ci.yml | 3 +++ src/api/routes.rs | 14 +++++++------- src/api/server.rs | 2 +- src/chain/client.rs | 12 +++--------- src/chain/esplora.rs | 29 +++++++++++++---------------- src/chain/zmq.rs | 2 +- src/claimer/constructor.rs | 15 +++++++-------- src/claimer/mod.rs | 31 +++++++++++++++---------------- src/claimer/tree.rs | 5 +---- src/db/helpers.rs | 4 ++-- src/db/models.rs | 1 + src/main.rs | 2 +- 12 files changed, 55 insertions(+), 65 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b19838f..486079b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,5 +19,8 @@ jobs: - name: Build run: cargo build + - name: Lint + run: cargo clippy + - name: Run tests run: cargo test --verbose diff --git a/src/api/routes.rs b/src/api/routes.rs index a3b6569..0422c17 100644 --- a/src/api/routes.rs +++ b/src/api/routes.rs @@ -88,7 +88,7 @@ pub async fn post_covenant_claim( return CovenantClaimResponse::Error(ErrorResponse { error: format!( "could not parse blinding key: {}", - blinding_key.err().unwrap().to_string() + blinding_key.err().unwrap() ), }); } @@ -97,7 +97,7 @@ pub async fn post_covenant_claim( Ok(res) => res, Err(err) => { return CovenantClaimResponse::Error(ErrorResponse { - error: format!("could not parse swap tree: {}", err.to_string()), + error: format!("could not parse swap tree: {}", err), }) } }; @@ -109,7 +109,7 @@ pub async fn post_covenant_claim( Ok(res) => res, Err(err) => { return CovenantClaimResponse::Error(ErrorResponse { - error: format!("could not parse refundPublicKey: {}", err.to_string()), + error: format!("could not parse refundPublicKey: {}", err), }) } }, @@ -117,7 +117,7 @@ pub async fn post_covenant_claim( Ok(res) => res, Err(err) => { return CovenantClaimResponse::Error(ErrorResponse { - error: format!("could not parse claimPublicKey: {}", err.to_string()), + error: format!("could not parse claimPublicKey: {}", err), }) } }, @@ -126,7 +126,7 @@ pub async fn post_covenant_claim( let internal_key = Vec::from(aggregate.agg_pk().serialize()); let preimage_hash: hashes::hash160::Hash = Hash::hash(body.preimage.clone().as_ref()); - if Vec::from(preimage_hash.as_byte_array()) != covenant_details.preimage_hash { + if covenant_details.preimage_hash != *preimage_hash.as_byte_array() { return CovenantClaimResponse::Error(ErrorResponse { error: "invalid preimage".to_string(), }); @@ -145,7 +145,7 @@ pub async fn post_covenant_claim( &body .tree .clone() - .address(internal_key, &state.address_params) + .address(internal_key, state.address_params) .script_pubkey(), ), tx_id: None, @@ -170,7 +170,7 @@ fn parse_address( Ok(res) => res, Err(err) => { return Err(ErrorResponse { - error: format!("could not parse address: {}", err.to_string()), + error: format!("could not parse address: {}", err), }); } }; diff --git a/src/api/server.rs b/src/api/server.rs index 46902d7..cf0f13b 100644 --- a/src/api/server.rs +++ b/src/api/server.rs @@ -28,5 +28,5 @@ pub async fn start_server( return Err(listener.err().unwrap()); } - return Ok(axum::serve(listener.unwrap(), app.clone()).await); + Ok(axum::serve(listener.unwrap(), app.clone()).await) } diff --git a/src/chain/client.rs b/src/chain/client.rs index 36a84ea..178cc98 100644 --- a/src/chain/client.rs +++ b/src/chain/client.rs @@ -60,7 +60,7 @@ impl ChainClient { }; trace!("Using Elements endpoint: {}", client.url); - return client; + client } pub async fn connect(mut self) -> Result> { @@ -69,11 +69,7 @@ impl ChainClient { self.cookie = Some(format!("Basic {}", BASE64_STANDARD.encode(file))); let notifications = self.clone().get_zmq_notifications().await?; - - match self.zmq_client.clone().connect(notifications).await { - Err(e) => return Err(e), - _ => {} - }; + self.zmq_client.clone().connect(notifications).await?; Ok(self) } @@ -143,9 +139,7 @@ impl ChainBackend for ChainClient { } async fn get_block(&self, hash: String) -> Result> { - let mut params = Vec::::new(); - params.push(StringOrU64::Str(hash)); - params.push(StringOrU64::Num(0)); + let params = vec![StringOrU64::Str(hash), StringOrU64::Num(0)]; let block_hex = self .clone() diff --git a/src/chain/esplora.rs b/src/chain/esplora.rs index 39308d1..7e5160e 100644 --- a/src/chain/esplora.rs +++ b/src/chain/esplora.rs @@ -39,7 +39,8 @@ impl EsploraClient { max_reqs_per_second: u64, boltz_endpoint: String, ) -> Result> { - let trimmed_endpoint = match endpoint.strip_suffix("/") { + // TODO: also do in boltz + let trimmed_endpoint = match endpoint.strip_suffix('/') { Some(s) => s.to_string(), None => endpoint, }; @@ -47,32 +48,28 @@ impl EsploraClient { let (tx_sender, tx_receiver) = crossbeam_channel::bounded::(1); let (block_sender, block_receiver) = crossbeam_channel::unbounded::(); - let rate_limit: Option>; - - if max_reqs_per_second > 0 { + let rate_limit = if max_reqs_per_second > 0 { info!( "Rate limiting requests to {} requests/second", max_reqs_per_second ); - rate_limit = Some(Arc::new( + Some(Arc::new( Ratelimiter::builder(max_reqs_per_second, Duration::from_secs(1)) .max_tokens(max_reqs_per_second) .build()?, - )); + )) } else { info!("Not rate limiting"); - rate_limit = None; - } - - let boltz_client: Option; + None + }; - if !boltz_endpoint.is_empty() { + let boltz_client = if !boltz_endpoint.is_empty() { info!("Broadcasting transactions with Boltz API"); - boltz_client = Some(Client::new(boltz_endpoint)); + Some(Client::new(boltz_endpoint)) } else { info!("Broadcasting transactions with Esplora"); - boltz_client = None; - } + None + }; Ok(EsploraClient { tx_sender, @@ -280,11 +277,11 @@ impl ChainBackend for EsploraClient { } fn get_tx_receiver(&self) -> Receiver { - return self.tx_receiver.clone(); + self.tx_receiver.clone() } fn get_block_receiver(&self) -> Receiver { - return self.block_receiver.clone(); + self.block_receiver.clone() } } diff --git a/src/chain/zmq.rs b/src/chain/zmq.rs index 0c5ffb8..38e50ca 100644 --- a/src/chain/zmq.rs +++ b/src/chain/zmq.rs @@ -94,7 +94,7 @@ impl ZmqClient { handler: F, ) -> Result<(), ZmqError> where - F: Fn(ZmqMessage) -> () + Send + 'static, + F: Fn(ZmqMessage) + Send + 'static, { debug!( "Connecting to {} ZMQ at {}", diff --git a/src/claimer/constructor.rs b/src/claimer/constructor.rs index fd2231a..de88216 100644 --- a/src/claimer/constructor.rs +++ b/src/claimer/constructor.rs @@ -87,7 +87,6 @@ impl Constructor { Ok(_) => {} Err(err) => { warn!("Could not schedule covenant claim: {}", err); - return; } }; } @@ -106,7 +105,7 @@ impl Constructor { } }; - if covenants.len() == 0 { + if covenants.is_empty() { return; } @@ -192,7 +191,7 @@ impl Constructor { let is_blinded = prevout.asset.is_confidential() && prevout.value.is_confidential(); let tx_secrets = match is_blinded { true => match prevout.unblind( - &secp, + secp, match SecretKey::from_slice( match covenant.clone().blinding_key { Some(res) => res, @@ -232,7 +231,7 @@ impl Constructor { }); if is_blinded { - let mut rng = OsRng::default(); + let mut rng = OsRng; let op_return_script = Builder::new() .push_opcode(opcodes::all::OP_RETURN) @@ -241,13 +240,13 @@ impl Constructor { let out_abf = AssetBlindingFactor::new(&mut rng); let (blinded_asset, surjection_proof) = Asset::Explicit(utxo_asset).blind( &mut rng, - &secp, + secp, out_abf, &[tx_secrets.unwrap()], )?; let final_vbf = ValueBlindingFactor::last( - &secp, + secp, 1, out_abf, &[( @@ -269,9 +268,9 @@ impl Constructor { ], ); let (blinded_value, nonce, rangeproof) = Value::Explicit(1).blind( - &secp, + secp, final_vbf, - SecretKey::new(&mut rng).public_key(&secp), + SecretKey::new(&mut rng).public_key(secp), SecretKey::new(&mut rng), &op_return_script.clone(), &elements::RangeProofMessage { diff --git a/src/claimer/mod.rs b/src/claimer/mod.rs index 8ab20e1..6447eb1 100644 --- a/src/claimer/mod.rs +++ b/src/claimer/mod.rs @@ -216,22 +216,21 @@ impl Claimer { for vout in 0..tx.output.len() { let out = &tx.output[vout]; - match get_pending_covenant_for_output(self.db.clone(), out.script_pubkey.as_bytes()) { - Some(covenant) => { - info!( - "Found covenant {} to claim in {}:{}", - hex::encode(covenant.clone().output_script), - tx.txid().to_string(), - vout - ); - - self.clone() - .constructor - .schedule_broadcast(covenant, tx.clone()) - .await; - } - None => {} - }; + if let Some(covenant) = + get_pending_covenant_for_output(self.db.clone(), out.script_pubkey.as_bytes()) + { + info!( + "Found covenant {} to claim in {}:{}", + hex::encode(covenant.clone().output_script), + tx.txid().to_string(), + vout + ); + + self.clone() + .constructor + .schedule_broadcast(covenant, tx.clone()) + .await; + } } } } diff --git a/src/claimer/tree.rs b/src/claimer/tree.rs index ed11c28..4cc643a 100644 --- a/src/claimer/tree.rs +++ b/src/claimer/tree.rs @@ -102,13 +102,10 @@ impl SwapTree { ) -> Option<(TxOut, u32)> { let script_pubkey = self.address(internal_key, params).script_pubkey(); - let mut vout: u32 = 0; - for out in lockup_tx.output { + for (vout, out) in (0_u32..).zip(lockup_tx.output.into_iter()) { if out.script_pubkey.eq(&script_pubkey) { return Some((out, vout)); } - - vout += 1; } None diff --git a/src/db/helpers.rs b/src/db/helpers.rs index 6ac765c..f37202b 100644 --- a/src/db/helpers.rs +++ b/src/db/helpers.rs @@ -30,7 +30,7 @@ pub fn get_block_height(con: db::Pool) -> Option { .load(&mut con.get().unwrap()) { Ok(res) => { - if res.len() == 0 { + if res.is_empty() { return None; } @@ -89,7 +89,7 @@ pub fn get_pending_covenant_for_output(con: db::Pool, script: &[u8]) -> Option

{ - if res.len() == 0 { + if res.is_empty() { return None; } diff --git a/src/db/models.rs b/src/db/models.rs index 316100b..dd6fa20 100644 --- a/src/db/models.rs +++ b/src/db/models.rs @@ -1,6 +1,7 @@ use diesel::internal::derives::multiconnection::chrono; use diesel::prelude::*; +#[derive(Copy, Clone)] pub enum PendingCovenantStatus { Pending = 0, TransactionFound = 1, diff --git a/src/main.rs b/src/main.rs index ba0960b..af3d1a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -139,7 +139,7 @@ async fn get_chain_backend() -> Arc> { } }; - return Arc::new(client); + Arc::new(client) } fn get_address_params() -> &'static AddressParams { From 92223c2b72a6c49ccbf685e44f73b87e6661ead9 Mon Sep 17 00:00:00 2001 From: michael1011 Date: Sat, 29 Jun 2024 20:12:19 +0200 Subject: [PATCH 2/2] chore: sanitize Boltz API endpoint --- src/boltz/api.rs | 10 +++++++++- src/chain/esplora.rs | 8 +------- src/main.rs | 1 + src/utils/mod.rs | 1 + src/utils/string.rs | 6 ++++++ 5 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 src/utils/mod.rs create mode 100644 src/utils/string.rs diff --git a/src/boltz/api.rs b/src/boltz/api.rs index 8fe4d6f..4025c04 100644 --- a/src/boltz/api.rs +++ b/src/boltz/api.rs @@ -13,7 +13,9 @@ pub struct Client { impl Client { pub fn new(endpoint: String) -> Self { - Client { endpoint } + Client { + endpoint: crate::utils::string::trim_suffix(endpoint, '/'), + } } pub async fn send_raw_transaction(&self, hex: String) -> Result> { @@ -65,6 +67,12 @@ mod client_test { const ENDPOINT: &str = "https://api.testnet.boltz.exchange/v2"; + #[test] + fn test_trim_suffix() { + assert_eq!(Client::new(ENDPOINT.to_string() + "/").endpoint, ENDPOINT); + assert_eq!(Client::new(ENDPOINT.to_string()).endpoint, ENDPOINT); + } + #[tokio::test] async fn test_send_raw_transaction_error_handling() { let client = Client::new(ENDPOINT.to_string()); diff --git a/src/chain/esplora.rs b/src/chain/esplora.rs index 7e5160e..2becefb 100644 --- a/src/chain/esplora.rs +++ b/src/chain/esplora.rs @@ -39,12 +39,6 @@ impl EsploraClient { max_reqs_per_second: u64, boltz_endpoint: String, ) -> Result> { - // TODO: also do in boltz - let trimmed_endpoint = match endpoint.strip_suffix('/') { - Some(s) => s.to_string(), - None => endpoint, - }; - let (tx_sender, tx_receiver) = crossbeam_channel::bounded::(1); let (block_sender, block_receiver) = crossbeam_channel::unbounded::(); @@ -79,7 +73,7 @@ impl EsploraClient { boltz_client, poll_interval, block_receiver, - endpoint: trimmed_endpoint, + endpoint: crate::utils::string::trim_suffix(endpoint, '/'), }) } diff --git a/src/main.rs b/src/main.rs index af3d1a0..94f60ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ mod boltz; mod chain; mod claimer; mod db; +mod utils; pub mod built_info { include!(concat!(env!("OUT_DIR"), "/built.rs")); diff --git a/src/utils/mod.rs b/src/utils/mod.rs new file mode 100644 index 0000000..d245b85 --- /dev/null +++ b/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod string; diff --git a/src/utils/string.rs b/src/utils/string.rs new file mode 100644 index 0000000..4763434 --- /dev/null +++ b/src/utils/string.rs @@ -0,0 +1,6 @@ +pub fn trim_suffix(string: String, suffix: char) -> String { + match string.strip_suffix(suffix) { + Some(s) => s.to_string(), + None => string, + } +}