Replace Config::blockchain() with chain-specific methods in preparation for multi-chain deployments

This commit is contained in:
silverpill 2023-04-08 21:08:11 +00:00
parent 0906fd8ae3
commit bd371189a0
9 changed files with 56 additions and 77 deletions

View file

@ -567,8 +567,7 @@ impl CreateMoneroWallet {
&self,
config: &Config,
) -> Result<(), Error> {
let monero_config = config.blockchain()
.and_then(|conf| conf.monero_config())
let monero_config = config.monero_config()
.ok_or(anyhow!("monero configuration not found"))?;
create_monero_wallet(
monero_config,
@ -592,8 +591,7 @@ impl CheckExpiredInvoice {
config: &Config,
db_client: &impl DatabaseClient,
) -> Result<(), Error> {
let monero_config = config.blockchain()
.and_then(|conf| conf.monero_config())
let monero_config = config.monero_config()
.ok_or(anyhow!("monero configuration not found"))?;
check_expired_invoice(
monero_config,

View file

@ -71,21 +71,3 @@ pub enum BlockchainConfig {
Ethereum(EthereumConfig),
Monero(MoneroConfig),
}
impl BlockchainConfig {
pub fn ethereum_config(&self) -> Option<&EthereumConfig> {
if let Self::Ethereum(ethereum_config) = self {
Some(ethereum_config)
} else {
None
}
}
pub fn monero_config(&self) -> Option<&MoneroConfig> {
if let Self::Monero(monero_config) = self {
Some(monero_config)
} else {
None
}
}
}

View file

@ -7,7 +7,11 @@ use url::Url;
use mitra_utils::urls::normalize_url;
use super::blockchain::BlockchainConfig;
use super::blockchain::{
BlockchainConfig,
EthereumConfig,
MoneroConfig,
};
use super::environment::Environment;
use super::federation::FederationConfig;
use super::limits::Limits;
@ -117,16 +121,31 @@ impl Config {
self.storage_dir.join("media")
}
pub fn blockchain(&self) -> Option<&BlockchainConfig> {
pub fn blockchains(&self) -> &[BlockchainConfig] {
if let Some(ref _blockchain_config) = self._blockchain {
panic!("'blockchain' setting is not supported anymore, use 'blockchains' instead");
} else {
match &self.blockchains[..] {
[blockchain_config] => Some(blockchain_config),
[] => None,
_ => panic!("multichain deployments are not supported"),
if self.blockchains.len() > 1 {
panic!("multichain deployments are not supported");
};
&self.blockchains
}
}
pub fn ethereum_config(&self) -> Option<&EthereumConfig> {
self.blockchains().iter()
.find_map(|item| match item {
BlockchainConfig::Ethereum(config) => Some(config),
_ => None,
})
}
pub fn monero_config(&self) -> Option<&MoneroConfig> {
self.blockchains().iter()
.find_map(|item| match item {
BlockchainConfig::Monero(config) => Some(config),
_ => None,
})
}
}

View file

@ -102,14 +102,12 @@ pub fn parse_config() -> (Config, Vec<&'static str>) {
};
check_directory_owner(&config.storage_dir);
config.try_instance_url().expect("invalid instance URI");
if let Some(blockchain_config) = config.blockchain() {
if let Some(ethereum_config) = blockchain_config.ethereum_config() {
if let Some(ethereum_config) = config.ethereum_config() {
ethereum_config.try_ethereum_chain_id().unwrap();
if !ethereum_config.contract_dir.exists() {
panic!("contract directory does not exist");
};
};
};
if config.ipfs_api_url.is_some() != config.ipfs_gateway_url.is_some() {
panic!("both ipfs_api_url and ipfs_gateway_url must be set");
};

View file

@ -93,9 +93,7 @@ pub async fn monero_payment_monitor(
config: &Config,
db_pool: &DbPool,
) -> Result<(), Error> {
let maybe_monero_config = config.blockchain()
.and_then(|conf| conf.monero_config());
let monero_config = match maybe_monero_config {
let monero_config = match config.monero_config() {
Some(monero_config) => monero_config,
None => return Ok(()), // not configured
};

View file

@ -61,16 +61,12 @@ async fn main() -> std::io::Result<()> {
.expect("failed to create media directory");
};
let maybe_ethereum_blockchain = if let Some(blockchain_config) = config.blockchain() {
if let Some(ethereum_config) = blockchain_config.ethereum_config() {
let maybe_ethereum_blockchain = if let Some(ethereum_config) = config.ethereum_config() {
// Create blockchain interface
get_contracts(&**db_client, ethereum_config, &config.storage_dir).await
.map(Some).unwrap()
} else {
None
}
} else {
None
};
let maybe_ethereum_contracts = maybe_ethereum_blockchain.clone()
.map(|blockchain| blockchain.contract_set);
@ -188,15 +184,13 @@ async fn main() -> std::io::Result<()> {
web::resource("/.well-known/{path}")
.to(HttpResponse::NotFound)
);
if let Some(blockchain_config) = config.blockchain() {
if let Some(ethereum_config) = blockchain_config.ethereum_config() {
if let Some(ethereum_config) = config.ethereum_config() {
// Serve artifacts if available
app = app.service(actix_files::Files::new(
"/contracts",
&ethereum_config.contract_dir,
));
};
};
if let Some(ref web_client_dir) = config.web_client_dir {
app = app.service(web_client::static_service(web_client_dir));
};

View file

@ -91,9 +91,8 @@ impl InstanceInfo {
post_count: i64,
peer_count: i64,
) -> Self {
let mut blockchains = vec![];
match config.blockchain() {
Some(BlockchainConfig::Ethereum(ethereum_config)) => {
let blockchains = config.blockchains().iter().map(|item| match item {
BlockchainConfig::Ethereum(ethereum_config) => {
let features = if let Some(contract_set) = maybe_ethereum_contracts {
BlockchainFeatures {
gate: contract_set.gate.is_some(),
@ -110,29 +109,28 @@ impl InstanceInfo {
let maybe_chain_metadata = ethereum_config
.chain_metadata.as_ref()
.and_then(|metadata| to_value(metadata).ok());
blockchains.push(BlockchainInfo {
BlockchainInfo {
chain_id: ethereum_config.chain_id.to_string(),
chain_metadata: maybe_chain_metadata,
contract_address:
Some(ethereum_config.contract_address.clone()),
features: features,
});
}
},
Some(BlockchainConfig::Monero(monero_config)) => {
BlockchainConfig::Monero(monero_config) => {
let features = BlockchainFeatures {
gate: false,
minter: false,
subscriptions: true,
};
blockchains.push(BlockchainInfo {
BlockchainInfo {
chain_id: monero_config.chain_id.to_string(),
chain_metadata: None,
contract_address: None,
features: features,
})
}
},
None => (),
};
}).collect();
Self {
uri: config.instance().hostname(),
title: config.instance_title.clone(),

View file

@ -625,9 +625,7 @@ async fn get_signature(
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let ethereum_config = config.blockchain()
.ok_or(MastodonError::NotSupported)?
.ethereum_config()
let ethereum_config = config.ethereum_config()
.ok_or(MastodonError::NotSupported)?;
// User must have a public ethereum address
let wallet_address = current_user

View file

@ -66,9 +66,7 @@ pub async fn authorize_subscription(
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let ethereum_config = config.blockchain()
.ok_or(MastodonError::NotSupported)?
.ethereum_config()
let ethereum_config = config.ethereum_config()
.ok_or(MastodonError::NotSupported)?;
// The user must have a public ethereum address,
// because subscribers should be able
@ -115,8 +113,7 @@ pub async fn register_subscription_option(
let maybe_payment_option = match subscription_option.into_inner() {
SubscriptionOption::Ethereum => {
let ethereum_config = config.blockchain()
.and_then(|conf| conf.ethereum_config())
let ethereum_config = config.ethereum_config()
.ok_or(MastodonError::NotSupported)?;
let contract_set = maybe_ethereum_contracts.as_ref().as_ref()
.ok_or(MastodonError::NotSupported)?;
@ -142,8 +139,7 @@ pub async fn register_subscription_option(
}
},
SubscriptionOption::Monero { price, payout_address } => {
let monero_config = config.blockchain()
.and_then(|conf| conf.monero_config())
let monero_config = config.monero_config()
.ok_or(MastodonError::NotSupported)?;
if price == 0 {
return Err(ValidationError("price must be greater than 0").into());
@ -207,9 +203,7 @@ async fn create_invoice_view(
db_pool: web::Data<DbPool>,
invoice_data: web::Json<InvoiceData>,
) -> Result<HttpResponse, MastodonError> {
let monero_config = config.blockchain()
.ok_or(MastodonError::NotSupported)?
.monero_config()
let monero_config = config.monero_config()
.ok_or(MastodonError::NotSupported)?;
if invoice_data.sender_id == invoice_data.recipient_id {
return Err(ValidationError("sender must be different from recipient").into());