Skip to content

Commit

Permalink
refactor stacks client and config to use the fallback client
Browse files Browse the repository at this point in the history
  • Loading branch information
cylewitruk committed Sep 25, 2024
1 parent 36a75c8 commit a0328de
Show file tree
Hide file tree
Showing 8 changed files with 363 additions and 304 deletions.
4 changes: 2 additions & 2 deletions signer/src/bitcoin/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl BitcoinInteract for ApiFallbackClient<BitcoinCoreClient> {
&self,
block_hash: &bitcoin::BlockHash,
) -> Result<Option<bitcoin::Block>, Error> {
self.exec(|client| async {
self.exec(|client, _| async {
match client.inner_client().get_block(block_hash) {
Ok(block) => Ok(Some(block)),
Err(bitcoincore_rpc::Error::JsonRpc(bitcoincore_rpc::jsonrpc::Error::Rpc(
Expand Down Expand Up @@ -79,7 +79,7 @@ impl BitcoinInteract for ApiFallbackClient<BitcoinCoreClient> {
}

async fn broadcast_transaction(&self, tx: &bitcoin::Transaction) -> Result<(), Error> {
self.exec(|client| async {
self.exec(|client, _| async {
client
.inner_client()
.send_raw_transaction(tx)
Expand Down
17 changes: 7 additions & 10 deletions signer/src/block_observer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ where
async fn process_bitcoin_block(&mut self, block: bitcoin::Block) -> Result<(), Error> {
let info = self.stacks_client.get_tenure_info().await?;
let stacks_blocks = crate::stacks::api::fetch_unknown_ancestors(
&mut self.stacks_client,
&self.stacks_client,
&self.storage,
info.tip_block_id,
)
Expand Down Expand Up @@ -812,23 +812,23 @@ mod tests {

impl StacksInteract for TestHarness {
async fn get_current_signer_set(
&mut self,
&self,
_contract_principal: &StacksAddress,
) -> Result<Vec<PublicKey>, Error> {
// issue #118
todo!()
}
async fn get_account(&mut self, _address: &StacksAddress) -> Result<AccountInfo, Error> {
async fn get_account(&self, _address: &StacksAddress) -> Result<AccountInfo, Error> {
// issue #118
todo!()
}

async fn submit_tx(&mut self, _tx: &StacksTransaction) -> Result<SubmitTxResponse, Error> {
async fn submit_tx(&self, _tx: &StacksTransaction) -> Result<SubmitTxResponse, Error> {
// issue #118
todo!()
}

async fn get_block(&mut self, block_id: StacksBlockId) -> Result<NakamotoBlock, Error> {
async fn get_block(&self, block_id: StacksBlockId) -> Result<NakamotoBlock, Error> {
self.stacks_blocks
.iter()
.skip_while(|(id, _, _)| &block_id != id)
Expand All @@ -837,10 +837,7 @@ mod tests {
.cloned()
.ok_or(Error::MissingBlock)
}
async fn get_tenure(
&mut self,
block_id: StacksBlockId,
) -> Result<Vec<NakamotoBlock>, Error> {
async fn get_tenure(&self, block_id: StacksBlockId) -> Result<Vec<NakamotoBlock>, Error> {
let (stx_block_id, stx_block, btc_block_id) = self
.stacks_blocks
.iter()
Expand All @@ -860,7 +857,7 @@ mod tests {

Ok(blocks)
}
async fn get_tenure_info(&mut self) -> Result<RPCGetTenureInfo, Error> {
async fn get_tenure_info(&self) -> Result<RPCGetTenureInfo, Error> {
let (_, _, btc_block_id) = self.stacks_blocks.last().unwrap();

Ok(RPCGetTenureInfo {
Expand Down
2 changes: 1 addition & 1 deletion signer/src/config/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ subscribe_interval = 10
# !! ==============================================================================
# !! Stacks Node Configuration
# !! ==============================================================================
[stacks.node]
[stacks]
# The RPC URL(s) of the Stacks node(s) to connect to. At least one must be
# provided. If multiple nodes are provided they will be tried in order when
# making requests.
Expand Down
100 changes: 41 additions & 59 deletions signer/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use stacks_common::types::chainstate::StacksAddress;
use std::path::Path;
use url::Url;

use crate::error::Error;
use crate::keys::PrivateKey;
use error::SignerConfigError;
use serialization::{
Expand Down Expand Up @@ -74,6 +73,8 @@ pub struct Settings {
pub signer: SignerConfig,
/// Bitcoin core configuration
pub bitcoin: BitcoinConfig,
/// Stacks configuration
pub stacks: StacksConfig,
}

/// Configuration used for the [`BitcoinCoreClient`](sbtc::rpc::BitcoinCoreClient).
Expand Down Expand Up @@ -255,6 +256,7 @@ impl Settings {
.with_list_parse_key("signer.p2p.listen_on")
.with_list_parse_key("signer.p2p.public_endpoints")
.with_list_parse_key("bitcoin.endpoints")
.with_list_parse_key("stacks.endpoints")
.prefix_separator("_");

let mut cfg_builder = Config::builder();
Expand Down Expand Up @@ -282,20 +284,9 @@ impl Settings {
}
}

/// A struct for the entries in the signers Config.toml (which is currently
/// located in src/config/default.toml)
#[derive(Debug, Clone, serde::Deserialize)]
pub struct StacksSettings {
/// The configuration entries related to the Stacks node
pub node: StacksNodeSettings,
}

/// Settings associated with the stacks node that this signer uses for information
#[derive(Debug, Clone, serde::Deserialize)]
pub struct StacksNodeSettings {
/// TODO(225): We'll want to support specifying multiple Stacks Nodes
/// endpoints.
///
pub struct StacksConfig {
/// The endpoint to use when making requests to a stacks node.
#[serde(deserialize_with = "url_deserializer_vec")]
pub endpoints: Vec<url::Url>,
Expand All @@ -304,37 +295,21 @@ pub struct StacksNodeSettings {
pub nakamoto_start_height: u64,
}

impl StacksSettings {
/// Create a new StacksSettings object by reading the relevant entries
/// in the signer's config.toml. The values there can be overridden by
/// environment variables.
///
/// # Notes
///
/// The relevant environment variables and the config entries that are
/// overridden are:
///
/// * SIGNER_STACKS_API_ENDPOINT <-> stacks.api.endpoint
/// * SIGNER_STACKS_NODE_ENDPOINTS <-> stacks.node.endpoints
///
/// Each of these overrides an entry in the signer's `config.toml`
pub fn new_from_config() -> Result<Self, Error> {
let source = File::with_name("./src/config/default");
let env = Environment::with_prefix("SIGNER")
.prefix_separator("_")
.list_separator(",")
.try_parsing(true)
.with_list_parse_key("stacks.node.endpoints")
.separator("_");
impl Validatable for StacksConfig {
fn validate(&self, _: &Settings) -> Result<(), ConfigError> {
if self.endpoints.is_empty() {
return Err(ConfigError::Message(
"[stacks] Endpoints cannot be empty".to_string(),
));
}

let conf = Config::builder()
.add_source(source)
.add_source(env)
.build()
.map_err(Error::SignerConfig)?;
if self.nakamoto_start_height == 0 {
return Err(ConfigError::Message(
"[stacks] Nakamoto start height must be greater than zero".to_string(),
));
}

conf.get::<StacksSettings>("stacks")
.map_err(Error::StacksApiConfig)
Ok(())
}
}

Expand All @@ -344,6 +319,7 @@ mod tests {

use serialization::try_parse_p2p_multiaddr;

use crate::error::Error;
use crate::testing::clear_env;

use super::*;
Expand Down Expand Up @@ -497,37 +473,43 @@ mod tests {

// The default toml used here specifies http://localhost:20443
// as the stacks node endpoint.
let settings = StacksSettings::new_from_config().unwrap();
let host = settings.node.endpoints[0].host();
let settings = Settings::new_from_default_config().unwrap();
let host = settings.stacks.endpoints[0].host();
assert_eq!(host, Some(url::Host::Domain("localhost")));
assert_eq!(settings.node.endpoints[0].port(), Some(20443));
assert_eq!(settings.stacks.endpoints[0].port(), Some(20443));

std::env::set_var(
"SIGNER_STACKS_NODE_ENDPOINTS",
"SIGNER_STACKS__ENDPOINTS",
"http://whatever:1234,http://whateva:4321",
);

let settings = StacksSettings::new_from_config().unwrap();
let host = settings.node.endpoints[0].host();
let settings = Settings::new_from_default_config().unwrap();
let host = settings.stacks.endpoints[0].host();
assert_eq!(host, Some(url::Host::Domain("whatever")));
assert_eq!(settings.node.endpoints[0].port(), Some(1234));
let host = settings.node.endpoints[1].host();
assert_eq!(settings.stacks.endpoints[0].port(), Some(1234));
let host = settings.stacks.endpoints[1].host();
assert_eq!(host, Some(url::Host::Domain("whateva")));
assert_eq!(settings.node.endpoints[1].port(), Some(4321));
assert_eq!(settings.stacks.endpoints[1].port(), Some(4321));

std::env::set_var("SIGNER_STACKS_NODE_ENDPOINTS", "http://127.0.0.1:5678");
std::env::set_var("SIGNER_STACKS__ENDPOINTS", "http://127.0.0.1:5678");

let settings = StacksSettings::new_from_config().unwrap();
let settings = Settings::new_from_default_config().unwrap();
let ip: std::net::Ipv4Addr = "127.0.0.1".parse().unwrap();
assert_eq!(settings.node.endpoints[0].host(), Some(url::Host::Ipv4(ip)));
assert_eq!(settings.node.endpoints[0].port(), Some(5678));
assert_eq!(
settings.stacks.endpoints[0].host(),
Some(url::Host::Ipv4(ip))
);
assert_eq!(settings.stacks.endpoints[0].port(), Some(5678));

std::env::set_var("SIGNER_STACKS_NODE_ENDPOINTS", "http://[::1]:9101");
std::env::set_var("SIGNER_STACKS__ENDPOINTS", "http://[::1]:9101");

let settings = StacksSettings::new_from_config().unwrap();
let settings = Settings::new_from_default_config().unwrap();
let ip: std::net::Ipv6Addr = "::1".parse().unwrap();
assert_eq!(settings.node.endpoints[0].host(), Some(url::Host::Ipv6(ip)));
assert_eq!(settings.node.endpoints[0].port(), Some(9101));
assert_eq!(
settings.stacks.endpoints[0].host(),
Some(url::Host::Ipv6(ip))
);
assert_eq!(settings.stacks.endpoints[0].port(), Some(9101));
}

#[test]
Expand Down
Loading

0 comments on commit a0328de

Please sign in to comment.