1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
// Copyright (c) 2021-2024 Espresso Systems (espressosys.com)
// This file is part of the HotShot repository.
// You should have received a copy of the MIT License
// along with the HotShot repository. If not, see <https://mit-license.org/>.
use anyhow::{bail, Result};
use async_trait::async_trait;
use hotshot_types::traits::{
auction_results_provider::AuctionResultsProvider,
node_implementation::{HasUrls, NodeType},
};
use serde::{Deserialize, Serialize};
use url::Url;
/// A mock result for the auction solver. This type is just a pointer to a URL.
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Default)]
pub struct TestAuctionResult {
/// The URL of the builder to reach out to.
pub urls: Vec<Url>,
}
impl HasUrls for TestAuctionResult {
fn urls(&self) -> Vec<Url> {
self.urls.clone()
}
}
/// The test auction results type is used to mimic the results from the Solver.
#[derive(Clone, Debug, Default)]
pub struct TestAuctionResultsProvider<TYPES: NodeType> {
/// We intentionally allow for the results to be pre-cooked for the unit test to guarantee a
/// particular outcome is met.
pub solver_results: TYPES::AuctionResult,
/// A canned type to ensure that an error is thrown in absence of a true fault-injectible
/// system for logical tests. This will guarantee that `fetch_auction_result` always throws an
/// error.
pub should_return_err: bool,
/// The broadcast URL that the solver is running on. This type allows for the url to be
/// optional, where `None` means to just return whatever `solver_results` contains, and `Some`
/// means that we have a `FakeSolver` instance available to query.
pub broadcast_url: Option<Url>,
}
#[async_trait]
impl<TYPES: NodeType> AuctionResultsProvider<TYPES> for TestAuctionResultsProvider<TYPES> {
/// Mock fetching the auction results, with optional error injection to simulate failure cases
/// in the solver.
async fn fetch_auction_result(&self, view_number: TYPES::View) -> Result<TYPES::AuctionResult> {
if let Some(url) = &self.broadcast_url {
let resp =
reqwest::get(url.join(&format!("/v0/api/auction_results/{}", *view_number))?)
.await?
.json::<TYPES::AuctionResult>()
.await?;
Ok(resp)
} else {
if self.should_return_err {
bail!("Something went wrong")
}
// Otherwise, return our pre-made results
Ok(self.solver_results.clone())
}
}
}