Skip to content

Commit

Permalink
Move in the stacks client into the signer context
Browse files Browse the repository at this point in the history
  • Loading branch information
djordon committed Oct 1, 2024
1 parent 7bd06a4 commit d8192b8
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 14 deletions.
4 changes: 4 additions & 0 deletions signer/src/block_observer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ mod tests {
Settings::new_from_default_config().unwrap(),
storage.clone(),
test_harness.clone(),
test_harness.clone(),
);
// There must be at least one signal receiver alive when the block observer
// later tries to send a signal, hence this line.
Expand Down Expand Up @@ -495,6 +496,7 @@ mod tests {
Settings::new_from_default_config().unwrap(),
storage.clone(),
test_harness.clone(),
test_harness.clone(),
);

let mut block_observer = BlockObserver {
Expand Down Expand Up @@ -572,6 +574,7 @@ mod tests {
Settings::new_from_default_config().unwrap(),
storage.clone(),
test_harness.clone(),
test_harness.clone(),
);

let mut block_observer = BlockObserver {
Expand Down Expand Up @@ -640,6 +643,7 @@ mod tests {
Settings::new_from_default_config().unwrap(),
storage.clone(),
test_harness.clone(),
test_harness.clone(),
);

// Now let's create two transactions, one spending to the signers
Expand Down
29 changes: 21 additions & 8 deletions signer/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use url::Url;
use crate::bitcoin::BitcoinInteract;
use crate::config::Settings;
use crate::error::Error;
use crate::stacks::api::StacksInteract;
use crate::storage::DbRead;
use crate::storage::DbWrite;
pub use messaging::*;
Expand All @@ -33,12 +34,14 @@ pub trait Context: Clone + Sync + Send {
fn get_storage_mut(&self) -> impl DbRead + DbWrite + Clone + Sync + Send;
/// Get a handle to a Bitcoin client.
fn get_bitcoin_client(&self) -> impl BitcoinInteract + Clone;
/// Get a handler to the Stacks client.
fn get_stacks_client(&self) -> impl StacksInteract + Clone;
}

/// Signer context which is passed to different components within the
/// signer binary.
#[derive(Debug, Clone)]
pub struct SignerContext<S, BC> {
pub struct SignerContext<S, BC, ST> {
config: Settings,
// Handle to the app signalling channel. This keeps the channel alive
// for the duration of the program and is used both to send messages
Expand All @@ -55,36 +58,40 @@ pub struct SignerContext<S, BC> {
// TODO: Additional clients to be added in future PRs. We may want
// to break the clients out into a separate struct to keep the field
// count down.
// /// Handle to a Stacks-RPC fallback-client.
//stacks_client: ApiFallbackClient<ST>,
/// Handle to a Stacks-RPC fallback-client.
stacks_client: ST,
// /// Handle to a Emily-API fallback-client.
//emily_client: ApiFallbackClient<EM>,
// /// Handle to a Blocklist-API fallback-client.
//blocklist_client: ApiFallbackClient<BL>,
}

impl<S, BC> SignerContext<S, BC>
impl<S, BC, ST> SignerContext<S, BC, ST>
where
S: DbRead + DbWrite + Clone + Sync + Send,
BC: for<'a> TryFrom<&'a [Url]> + BitcoinInteract + Clone + Sync + Send + 'static,
ST: for<'a> TryFrom<&'a Settings> + StacksInteract + Clone + Sync + Send + 'static,
Error: for<'a> From<<BC as TryFrom<&'a [Url]>>::Error>,
Error: for<'a> From<<ST as TryFrom<&'a Settings>>::Error>,
{
/// Initializes a new [`SignerContext`], automatically creating clients
/// based on the provided types.
pub fn init(config: Settings, db: S) -> Result<Self, Error> {
let bc = BC::try_from(&config.bitcoin.rpc_endpoints)?;
let st = ST::try_from(&config)?;

Ok(Self::new(config, db, bc))
Ok(Self::new(config, db, bc, st))
}
}

impl<S, BC> SignerContext<S, BC>
impl<S, BC, ST> SignerContext<S, BC, ST>
where
S: DbRead + DbWrite + Clone + Sync + Send,
BC: BitcoinInteract + Clone + Sync + Send,
ST: StacksInteract + Clone + Sync + Send,
{
/// Create a new signer context.
pub fn new(config: Settings, db: S, bitcoin_client: BC) -> Self {
pub fn new(config: Settings, db: S, bitcoin_client: BC, stacks_client: ST) -> Self {
// TODO: Decide on the channel capacity and how we should handle slow consumers.
// NOTE: Ideally consumers which require processing time should pull the relevent
// messages into a local VecDequeue and process them in their own time.
Expand All @@ -97,14 +104,16 @@ where
term_tx,
storage: db,
bitcoin_client,
stacks_client,
}
}
}

impl<S, BC> Context for SignerContext<S, BC>
impl<S, BC, ST> Context for SignerContext<S, BC, ST>
where
S: DbRead + DbWrite + Clone + Sync + Send,
BC: BitcoinInteract + Clone + Sync + Send,
ST: StacksInteract + Clone + Sync + Send,
{
fn config(&self) -> &Settings {
&self.config
Expand Down Expand Up @@ -147,6 +156,10 @@ where
fn get_bitcoin_client(&self) -> impl BitcoinInteract + Clone {
self.bitcoin_client.clone()
}

fn get_stacks_client(&self) -> impl StacksInteract + Clone {
self.stacks_client.clone()
}
}

#[cfg(test)]
Expand Down
6 changes: 5 additions & 1 deletion signer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}

// Initialize the signer context.
let context = SignerContext::<_, ApiFallbackClient<BitcoinCoreClient>>::init(settings, db)?;
let context = SignerContext::<
_,
ApiFallbackClient<BitcoinCoreClient>,
ApiFallbackClient<StacksClient>,
>::init(settings, db)?;

// Run the application components concurrently. We're `join!`ing them
// here so that every component can shut itself down gracefully when
Expand Down
8 changes: 8 additions & 0 deletions signer/src/testing/api_clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::bitcoin::rpc::GetTxResponse;
use crate::bitcoin::BitcoinInteract;
use crate::bitcoin::MockBitcoinInteract;
use crate::blocklist_client::BlocklistChecker;
use crate::config::Settings;
use crate::emily_client::EmilyInteract;
use crate::error::Error;
use crate::stacks::api::StacksInteract;
Expand All @@ -23,6 +24,13 @@ impl TryFrom<&[Url]> for NoopApiClient {
}
}

impl TryFrom<&Settings> for NoopApiClient {
type Error = Error;
fn try_from(_value: &Settings) -> Result<Self, Self::Error> {
Ok(NoopApiClient)
}
}

/// Noop implementation of the BitcoinInteract trait.
impl BitcoinInteract for NoopApiClient {
async fn get_tx(&self, _: &bitcoin::Txid) -> Result<Option<GetTxResponse>, Error> {
Expand Down
11 changes: 9 additions & 2 deletions signer/src/testing/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ use crate::{
config::Settings,
context::{Context, SignerContext},
error::Error,
stacks::api::StacksInteract,
storage::in_memory::{SharedStore, Store},
};

use super::api_clients::NoopApiClient;

/// A [`Context`] which can be used for testing.
///
/// This context is opinionated and uses a shared in-memory store and mocked
Expand All @@ -24,7 +27,7 @@ use crate::{
#[derive(Clone)]
pub struct TestContext<BC> {
/// The inner [`SignerContext`] which this context wraps.
pub inner: SignerContext<SharedStore, BC>,
pub inner: SignerContext<SharedStore, BC, NoopApiClient>,

/// The mocked bitcoin client.
pub bitcoin_client: BC,
Expand All @@ -39,7 +42,7 @@ where
let settings = Settings::new_from_default_config().unwrap();
let store = Store::new_shared();

let context = SignerContext::new(settings, store, bitcoin_client.clone());
let context = SignerContext::new(settings, store, bitcoin_client.clone(), NoopApiClient);

Self { inner: context, bitcoin_client }
}
Expand Down Expand Up @@ -102,6 +105,10 @@ where
fn get_bitcoin_client(&self) -> impl BitcoinInteract + Clone {
self.inner.get_bitcoin_client()
}

fn get_stacks_client(&self) -> impl StacksInteract + Clone {
NoopApiClient
}
}

/// A wrapper around a mock which can be cloned and shared between threads.
Expand Down
6 changes: 3 additions & 3 deletions signer/src/testing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::storage::postgres::PgStore;
pub const DEFAULT_CONFIG_PATH: Option<&str> = Some("./src/config/default");

/// A [`SignerContext`] which uses [`NoopApiClient`]s.
pub type NoopSignerContext<S> = SignerContext<S, NoopApiClient>;
pub type NoopSignerContext<S> = SignerContext<S, NoopApiClient, NoopApiClient>;

impl Settings {
/// Create a new `Settings` instance from the default configuration file.
Expand All @@ -42,7 +42,7 @@ impl Settings {
/// A client that can be used for integration tests. The settings are
/// loaded from the default config toml, and the PgStore is assumed to
/// point to a test database.
pub type TestSignerContext = SignerContext<PgStore, BitcoinCoreClient>;
pub type TestSignerContext = SignerContext<PgStore, BitcoinCoreClient, NoopApiClient>;

impl TestSignerContext {
/// Create a new one from the given database connection pool with the
Expand All @@ -52,7 +52,7 @@ impl TestSignerContext {

let url = config.bitcoin.rpc_endpoints.first().unwrap();
let bitcoin_client = BitcoinCoreClient::try_from(url).unwrap();
Self::new(config, db, bitcoin_client)
Self::new(config, db, bitcoin_client, NoopApiClient)
}
}

Expand Down

0 comments on commit d8192b8

Please sign in to comment.