cargo clippy

This commit is contained in:
f321x
2024-07-21 14:28:38 +02:00
parent efaa843a1a
commit c8bc01e856
11 changed files with 124 additions and 134 deletions

View File

@ -0,0 +1,46 @@
use super::*;
pub fn validate_timestamp(offer_duration_ts: u64) -> Result<(), ValidationError> {
// Get the current time
let now = SystemTime::now();
// Convert the current time to a UNIX timestamp
let unix_timestamp = now
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
if offer_duration_ts < unix_timestamp + 10800 {
return Err(ValidationError::new("Offer duration too short"));
}
if offer_duration_ts > unix_timestamp + 604800 {
return Err(ValidationError::new("Offer duration too long"));
}
Ok(())
}
// ANYHOW ERROR HANDLING
// --------------
// Make our own error that wraps `anyhow::Error`.
#[derive(Debug)]
pub struct AppError(anyhow::Error);
// Tell axum how to convert `AppError` into a response.
impl IntoResponse for AppError {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", self.0),
)
.into_response()
}
}
// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into
// `Result<_, AppError>`. That way you don't need to do that manually.
impl<E> From<E> for AppError
where
E: Into<anyhow::Error>,
{
fn from(err: E) -> Self {
Self(err.into())
}
}

View File

@ -8,18 +8,18 @@ pub enum BondError {
#[derive(Debug)]
pub enum FetchOffersError {
NoOffersAvailable,
DatabaseError(String),
Database(String),
}
#[derive(Debug)]
pub enum FetchEscrowConfirmationError {
NotFoundError,
DatabaseError(String),
NotFound,
Database(String),
}
#[derive(Debug)]
pub enum RequestError {
DatabaseError(String),
NotConfirmedError,
NotFoundError,
Database(String),
NotConfirmed,
NotFound,
}

View File

@ -1,8 +1,8 @@
pub mod api;
pub mod communication_utils;
pub mod handler_errors;
mod utils;
use self::utils::*;
use self::communication_utils::*;
use super::*;
use axum::{
http::StatusCode,
@ -23,10 +23,10 @@ async fn receive_order(
Json(offer): Json<OfferRequest>,
) -> Result<Response, AppError> {
if let Err(_) = offer.validate() {
return Ok(StatusCode::BAD_REQUEST.into_response());
Ok(StatusCode::BAD_REQUEST.into_response())
} else {
let bond_requirements = process_order(coordinator, &offer).await?;
return Ok(Json(bond_requirements).into_response());
Ok(Json(bond_requirements).into_response())
}
}
@ -41,15 +41,15 @@ async fn submit_maker_bond(
Ok(offer_activated_response) => Ok(Json(offer_activated_response).into_response()),
Err(BondError::BondNotFound) => {
info!("Bond requirements not found in database");
return Ok(StatusCode::NOT_FOUND.into_response());
Ok(StatusCode::NOT_FOUND.into_response())
}
Err(BondError::InvalidBond(e)) => {
warn!("Invalid bond submission: {e}");
return Ok(StatusCode::NOT_ACCEPTABLE.into_response());
Ok(StatusCode::NOT_ACCEPTABLE.into_response())
}
Err(BondError::CoordinatorError(e)) => {
error!("Coordinator error on bond submission: {e}");
return Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response());
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
}
}
@ -64,7 +64,7 @@ async fn fetch_available_offers(
match get_public_offers(&payload, coordinator).await {
Ok(offers) => Ok(Json(offers).into_response()),
Err(FetchOffersError::NoOffersAvailable) => Ok(StatusCode::NO_CONTENT.into_response()),
Err(FetchOffersError::DatabaseError(e)) => {
Err(FetchOffersError::Database(e)) => {
error!("Database error fetching offers: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
@ -83,15 +83,15 @@ async fn submit_taker_bond(
Ok(offer_taken_response) => Ok(Json(offer_taken_response).into_response()),
Err(BondError::BondNotFound) => {
info!("Bond requirements not found in database");
return Ok(StatusCode::NOT_FOUND.into_response());
Ok(StatusCode::NOT_FOUND.into_response())
}
Err(BondError::InvalidBond(e)) => {
warn!("Invalid bond submission: {e}");
return Ok(StatusCode::NOT_ACCEPTABLE.into_response());
Ok(StatusCode::NOT_ACCEPTABLE.into_response())
}
Err(BondError::CoordinatorError(e)) => {
error!("Coordinator error on bond submission: {e}");
return Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response());
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
}
}
@ -106,7 +106,7 @@ async fn request_offer_status_maker(
match get_offer_status_maker(&payload, coordinator).await {
Ok(offer_taken_response) => Ok(Json(offer_taken_response).into_response()),
Err(FetchOffersError::NoOffersAvailable) => Ok(StatusCode::NO_CONTENT.into_response()),
Err(FetchOffersError::DatabaseError(e)) => {
Err(FetchOffersError::Database(e)) => {
error!("Database error fetching offers: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
@ -139,11 +139,11 @@ async fn poll_escrow_confirmation(
match fetch_escrow_confirmation_status(&payload, coordinator).await {
Ok(true) => Ok(StatusCode::OK.into_response()),
Ok(false) => Ok(StatusCode::ACCEPTED.into_response()),
Err(FetchEscrowConfirmationError::NotFoundError) => {
Err(FetchEscrowConfirmationError::NotFound) => {
info!("Escrow confirmation check transaction not found");
Ok(StatusCode::NOT_FOUND.into_response())
}
Err(FetchEscrowConfirmationError::DatabaseError(e)) => {
Err(FetchEscrowConfirmationError::Database(e)) => {
error!("Database error fetching escrow confirmation: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
@ -156,15 +156,15 @@ async fn submit_obligation_confirmation(
) -> Result<Response, AppError> {
match handle_obligation_confirmation(&payload, coordinator).await {
Ok(_) => Ok(StatusCode::OK.into_response()),
Err(RequestError::NotFoundError) => {
Err(RequestError::NotFound) => {
info!("Offer for obligation confirmation not found");
Ok(StatusCode::NOT_FOUND.into_response())
}
Err(RequestError::NotConfirmedError) => {
Err(RequestError::NotConfirmed) => {
info!("Offer for obligation confirmation not confirmed");
Ok(StatusCode::NOT_ACCEPTABLE.into_response())
}
Err(RequestError::DatabaseError(e)) => {
Err(RequestError::Database(e)) => {
error!("Database error fetching obligation confirmation: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
@ -181,15 +181,15 @@ async fn request_escrow(
) -> Result<Response, AppError> {
match initiate_escrow(&payload, coordinator).await {
Ok(_) => Ok(StatusCode::OK.into_response()),
Err(RequestError::NotConfirmedError) => {
Err(RequestError::NotConfirmed) => {
info!("Offer tx for escrow initiation not confirmed");
Ok(StatusCode::NOT_ACCEPTABLE.into_response())
}
Err(RequestError::NotFoundError) => {
Err(RequestError::NotFound) => {
info!("Offer for escrow initiation not found");
Ok(StatusCode::NOT_FOUND.into_response())
}
Err(RequestError::DatabaseError(e)) => {
Err(RequestError::Database(e)) => {
error!("Database error fetching obligation confirmation: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
@ -209,15 +209,15 @@ async fn poll_final_payout(
Ok(PayoutProcessingResult::LostEscrow) => Ok(StatusCode::GONE.into_response()),
Ok(PayoutProcessingResult::ReadyPSBT(psbt)) => Ok(psbt.into_response()),
Ok(PayoutProcessingResult::DecidingEscrow) => Ok(StatusCode::PROCESSING.into_response()),
Err(RequestError::NotConfirmedError) => {
Err(RequestError::NotConfirmed) => {
info!("Offer tx for final payout not confirmed");
Ok(StatusCode::NOT_ACCEPTABLE.into_response())
}
Err(RequestError::NotFoundError) => {
Err(RequestError::NotFound) => {
info!("Offer for final payout not found");
Ok(StatusCode::NOT_FOUND.into_response())
}
Err(RequestError::DatabaseError(e)) => {
Err(RequestError::Database(e)) => {
error!("Database error fetching final payout: {e}");
Ok(StatusCode::INTERNAL_SERVER_ERROR.into_response())
}
@ -257,31 +257,3 @@ pub async fn api_server(coordinator: Arc<Coordinator>) -> Result<()> {
Ok(())
}
// ANYHOW ERROR HANDLING
// --------------
// Make our own error that wraps `anyhow::Error`.
#[derive(Debug)]
pub struct AppError(anyhow::Error);
// Tell axum how to convert `AppError` into a response.
impl IntoResponse for AppError {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", self.0),
)
.into_response()
}
}
// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into
// `Result<_, AppError>`. That way you don't need to do that manually.
impl<E> From<E> for AppError
where
E: Into<anyhow::Error>,
{
fn from(err: E) -> Self {
Self(err.into())
}
}

View File

@ -1,18 +0,0 @@
use super::*;
pub fn validate_timestamp(offer_duration_ts: u64) -> Result<(), ValidationError> {
// Get the current time
let now = SystemTime::now();
// Convert the current time to a UNIX timestamp
let unix_timestamp = now
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
if offer_duration_ts < unix_timestamp + 10800 {
return Err(ValidationError::new("Offer duration too short"));
}
if offer_duration_ts > unix_timestamp + 604800 {
return Err(ValidationError::new("Offer duration too long"));
}
Ok(())
}

View File

@ -1,5 +1,13 @@
use super::*;
#[derive(Debug)]
pub enum PayoutProcessingResult {
ReadyPSBT(String),
NotReady,
LostEscrow,
DecidingEscrow,
}
pub fn generate_random_order_id(len: usize) -> String {
// Generate `len` random bytes
let bytes: Vec<u8> = rand::thread_rng()
@ -8,8 +16,7 @@ pub fn generate_random_order_id(len: usize) -> String {
.collect();
// Convert bytes to hex string
let hex_string = hex::encode(bytes);
hex_string
hex::encode(bytes)
}
pub async fn check_offer_and_confirmation(
@ -22,9 +29,9 @@ pub async fn check_offer_and_confirmation(
.is_valid_robohash_in_table(robohash_hex, offer_id_hex)
.await
{
Ok(false) => return Err(RequestError::NotFoundError),
Ok(false) => return Err(RequestError::NotFound),
Ok(true) => (),
Err(e) => return Err(RequestError::DatabaseError(e.to_string())),
Err(e) => return Err(RequestError::Database(e.to_string())),
};
// sanity check if the escrow tx is confirmed
@ -32,8 +39,8 @@ pub async fn check_offer_and_confirmation(
.fetch_escrow_tx_confirmation_status(offer_id_hex)
.await
{
Ok(false) => return Err(RequestError::NotConfirmedError),
Ok(false) => Err(RequestError::NotConfirmed),
Ok(true) => Ok(()),
Err(e) => return Err(RequestError::DatabaseError(e.to_string())),
Err(e) => Err(RequestError::Database(e.to_string())),
}
}

View File

@ -50,7 +50,7 @@ fn run_mempool(mempool: Arc<Mempool>) {
let tx = match mempool
.json_rpc_client
.deref()
.get_raw_transaction(&txid, None)
.get_raw_transaction(txid, None)
{
std::result::Result::Ok(tx) => tx,
Err(e) => {

View File

@ -1,19 +1,12 @@
pub mod coordinator_utils;
pub mod create_taproot;
pub mod mempool_monitoring;
pub mod monitoring;
pub mod tx_confirmation_monitoring;
pub mod utils;
use self::utils::*;
use self::coordinator_utils::*;
use super::*;
pub enum PayoutProcessingResult {
ReadyPSBT(String),
NotReady,
LostEscrow,
DecidingEscrow,
}
pub async fn process_order(
coordinator: Arc<Coordinator>,
offer: &OfferRequest,
@ -77,7 +70,7 @@ pub async fn handle_maker_bond(
};
// insert bond into sql database and move offer to different table
let bond_locked_until_timestamp = match database
.move_offer_to_active(&payload, &offer_id_hex, new_taker_bond_address)
.move_offer_to_active(payload, &offer_id_hex, new_taker_bond_address)
.await
{
Ok(timestamp) => timestamp,
@ -104,7 +97,7 @@ pub async fn get_public_offers(
let offers = match database.fetch_suitable_offers(request).await {
Ok(offers) => offers,
Err(e) => {
return Err(FetchOffersError::DatabaseError(e.to_string()));
return Err(FetchOffersError::Database(e.to_string()));
}
};
if offers.is_none() {
@ -147,7 +140,7 @@ pub async fn handle_taker_bond(
if let Err(e) = database
.add_taker_info_and_move_table(
&payload,
payload,
&trade_contract_psbt_maker,
&trade_contract_psbt_taker,
escrow_tx_txid,
@ -174,7 +167,7 @@ pub async fn get_offer_status_maker(
{
Ok(offer) => offer,
Err(e) => {
return Err(FetchOffersError::DatabaseError(e.to_string()));
return Err(FetchOffersError::Database(e.to_string()));
}
};
match offer {
@ -195,9 +188,9 @@ pub async fn fetch_escrow_confirmation_status(
.is_valid_robohash_in_table(&payload.robohash_hex, &payload.offer_id_hex)
.await
{
Ok(false) => return Err(FetchEscrowConfirmationError::NotFoundError),
Ok(false) => return Err(FetchEscrowConfirmationError::NotFound),
Ok(true) => (),
Err(e) => return Err(FetchEscrowConfirmationError::DatabaseError(e.to_string())),
Err(e) => return Err(FetchEscrowConfirmationError::Database(e.to_string())),
}
if match database
@ -205,12 +198,12 @@ pub async fn fetch_escrow_confirmation_status(
.await
{
Ok(status) => status,
Err(e) => return Err(FetchEscrowConfirmationError::DatabaseError(e.to_string())),
Err(e) => return Err(FetchEscrowConfirmationError::Database(e.to_string())),
} {
// rust smh
Ok(true)
} else {
Err(FetchEscrowConfirmationError::NotFoundError)
Err(FetchEscrowConfirmationError::NotFound)
}
}
@ -220,16 +213,12 @@ pub async fn handle_obligation_confirmation(
) -> Result<(), RequestError> {
let database = &coordinator.coordinator_db;
if let Err(e) =
check_offer_and_confirmation(&payload.offer_id_hex, &payload.robohash_hex, database).await
{
return Err(e);
}
check_offer_and_confirmation(&payload.offer_id_hex, &payload.robohash_hex, database).await?;
if let Err(e) = database
.set_trader_happy_field(&payload.offer_id_hex, &payload.robohash_hex, true)
.await
{
return Err(RequestError::DatabaseError(e.to_string()));
return Err(RequestError::Database(e.to_string()));
}
Ok(())
}
@ -240,17 +229,13 @@ pub async fn initiate_escrow(
) -> Result<(), RequestError> {
let database = &coordinator.coordinator_db;
if let Err(e) =
check_offer_and_confirmation(&payload.offer_id_hex, &payload.robohash_hex, database).await
{
return Err(e);
}
check_offer_and_confirmation(&payload.offer_id_hex, &payload.robohash_hex, database).await?;
if let Err(e) = database
.set_trader_happy_field(&payload.offer_id_hex, &payload.robohash_hex, false)
.await
{
return Err(RequestError::DatabaseError(e.to_string()));
return Err(RequestError::Database(e.to_string()));
}
Ok(())
@ -262,19 +247,15 @@ pub async fn handle_final_payout(
) -> Result<PayoutProcessingResult, RequestError> {
let database = &coordinator.coordinator_db;
if let Err(e) =
check_offer_and_confirmation(&payload.offer_id_hex, &payload.robohash_hex, database).await
{
return Err(e);
}
check_offer_and_confirmation(&payload.offer_id_hex, &payload.robohash_hex, database).await?;
let trader_happiness = match database.fetch_trader_happiness(&payload.offer_id_hex).await {
Ok(happiness) => happiness,
Err(e) => return Err(RequestError::DatabaseError(e.to_string())),
Err(e) => return Err(RequestError::Database(e.to_string())),
};
if trader_happiness.maker_happy.is_some_and(|x| x == true)
&& trader_happiness.taker_happy.is_some_and(|x| x == true)
if trader_happiness.maker_happy.is_some_and(|x| x)
&& trader_happiness.taker_happy.is_some_and(|x| x)
{
panic!("Implement wallet.assemble_keyspend_payout_psbt()");
// let payout_keyspend_psbt_hex = wallet
@ -295,7 +276,7 @@ pub async fn handle_final_payout(
// endpoint for the admin UI frontend in the future
let potential_escrow_winner = match database.fetch_escrow_result(&payload.offer_id_hex).await {
Ok(escrow_winner) => escrow_winner,
Err(e) => return Err(RequestError::DatabaseError(e.to_string())),
Err(e) => return Err(RequestError::Database(e.to_string())),
};
if let Some(escrow_winner) = potential_escrow_winner {
@ -308,10 +289,10 @@ pub async fn handle_final_payout(
// return Ok(PayoutProcessingResult::ReadyPSBT(script_payout_psbt_hex));
} else {
// this will be returned to the losing trader
return Ok(PayoutProcessingResult::LostEscrow);
Ok(PayoutProcessingResult::LostEscrow)
}
} else {
// this will be returned if the coordinator hasn't decided yet
return Ok(PayoutProcessingResult::DecidingEscrow);
Ok(PayoutProcessingResult::DecidingEscrow)
}
}

View File

@ -4,7 +4,6 @@
// Also needs to implement punishment logic in case a fraud is detected.
use super::*;
use anyhow::Context;
use mempool_monitoring::MempoolHandler;
use sha2::{Digest, Sha256};
#[derive(Debug, Clone, PartialEq)]

View File

@ -380,8 +380,8 @@ impl CoordinatorDB {
.bind(public_offer.musig_pubkey_hex_maker)
.bind(trade_and_taker_info.trade_data.musig_pub_nonce_hex.clone())
.bind(trade_and_taker_info.trade_data.musig_pubkey_hex.clone())
.bind(trade_contract_psbt_maker.clone())
.bind(trade_contract_psbt_taker.clone())
.bind(trade_contract_psbt_maker)
.bind(trade_contract_psbt_taker)
.bind(trade_tx_txid)
.bind(0)
.bind(0)

View File

@ -5,15 +5,20 @@ mod wallet;
use anyhow::{anyhow, Result};
use bdk::sled;
use communication::{api::*, api_server, handler_errors::*, *};
use coordinator::tx_confirmation_monitoring::update_transaction_confirmations;
use coordinator::{monitoring::*, *};
use communication::{api::*, api_server, communication_utils::*, handler_errors::*};
use coordinator::{
coordinator_utils::*, monitoring::*,
tx_confirmation_monitoring::update_transaction_confirmations, *,
};
use database::CoordinatorDB;
use dotenv::dotenv;
use log::{debug, error, info, trace, warn};
use rand::Rng;
use std::time::{SystemTime, UNIX_EPOCH};
use std::{env, sync::Arc};
use std::{
env,
sync::Arc,
time::{SystemTime, UNIX_EPOCH},
};
use tokio::sync::Mutex;
use validator::{Validate, ValidationError};
use wallet::*;

View File

@ -80,7 +80,7 @@ pub async fn init_coordinator_wallet() -> Result<CoordinatorWallet<sled::Tree>>
Ok(CoordinatorWallet {
wallet: Arc::new(Mutex::new(wallet)),
backend: Arc::new(backend),
json_rpc_client: json_rpc_client,
json_rpc_client,
mempool: Arc::new(mempool),
})
}
@ -128,8 +128,6 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
{
let wallet = self.wallet.lock().await;
for bond in bonds.as_ref().iter() {
let input_sum: u64;
let tx: Transaction = deserialize(&hex::decode(&bond.bond_tx_hex)?)?;
debug!("Validating bond in validate_bonds()");
// we need to test this with signed and invalid/unsigned transactions
@ -140,7 +138,7 @@ impl<D: bdk::database::BatchDatabase> CoordinatorWallet<D> {
}
// check if the tx has the correct input amounts (have to be >= trading amount)
input_sum = match tx.input_sum(blockchain, &*wallet.database()) {
let input_sum: u64 = match tx.input_sum(blockchain, &*wallet.database()) {
Ok(amount) => {
if amount < bond.requirements.min_input_sum_sat {
invalid_bonds.insert(