Allow blockchain config to have sub-types

This commit is contained in:
silverpill 2022-08-10 11:57:18 +00:00
parent c4e5438ac2
commit dc7d533c42
10 changed files with 56 additions and 29 deletions

View file

@ -11,7 +11,7 @@ fn default_chain_sync_step() -> u64 { 1000 }
fn default_chain_reorg_max_depth() -> u64 { 10 }
#[derive(Clone, Deserialize)]
pub struct BlockchainConfig {
pub struct EthereumConfig {
// CAIP-2 chain ID
pub chain_id: ChainId,
// Additional information for clients
@ -30,7 +30,7 @@ pub struct BlockchainConfig {
pub chain_reorg_max_depth: u64,
}
impl BlockchainConfig {
impl EthereumConfig {
pub fn try_ethereum_chain_id(&self) -> Result<u32, ChainIdError> {
parse_caip2_chain_id(&self.chain_id)
}
@ -39,3 +39,16 @@ impl BlockchainConfig {
self.try_ethereum_chain_id().unwrap()
}
}
#[derive(Clone, Deserialize)]
#[serde(untagged)]
pub enum BlockchainConfig {
Ethereum(EthereumConfig),
}
impl BlockchainConfig {
pub fn ethereum_config(&self) -> Option<&EthereumConfig> {
let Self::Ethereum(ethereum_config) = self;
Some(ethereum_config)
}
}

View file

@ -243,11 +243,13 @@ pub fn parse_config() -> Config {
check_directory_owner(&config.storage_dir);
config.try_instance_url().expect("invalid instance URI");
if let Some(blockchain_config) = config.blockchain.as_ref() {
blockchain_config.try_ethereum_chain_id().unwrap();
if !blockchain_config.contract_dir.exists() {
if let Some(ethereum_config) = blockchain_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

@ -2,6 +2,6 @@ mod blockchain;
mod environment;
mod main;
pub use blockchain::BlockchainConfig;
pub use blockchain::EthereumConfig;
pub use environment::Environment;
pub use main::{parse_config, Config, Instance};

View file

@ -8,7 +8,7 @@ use web3::{
transports::Http,
};
use crate::config::BlockchainConfig;
use crate::config::EthereumConfig;
use super::api::connect;
use super::errors::EthereumError;
use super::sync::{
@ -96,7 +96,7 @@ pub struct Blockchain {
}
pub async fn get_contracts(
config: &BlockchainConfig,
config: &EthereumConfig,
storage_dir: &Path,
) -> Result<Blockchain, EthereumError> {
let web3 = connect(&config.api_url)?;

View file

@ -11,7 +11,7 @@ use web3::{
types::{BlockNumber, FilterBuilder},
};
use crate::config::BlockchainConfig;
use crate::config::EthereumConfig;
use crate::database::{Pool, get_database_client};
use crate::errors::DatabaseError;
use crate::ipfs::utils::parse_ipfs_url;
@ -127,7 +127,7 @@ pub async fn process_nft_events(
}
pub fn create_mint_signature(
blockchain_config: &BlockchainConfig,
blockchain_config: &EthereumConfig,
user_address: &str,
token_uri: &str,
) -> Result<SignatureData, EthereumError> {

View file

@ -15,7 +15,7 @@ use crate::activitypub::builders::{
remove_person::prepare_remove_person,
};
use crate::activitypub::identifiers::LocalActorCollection;
use crate::config::{BlockchainConfig, Instance};
use crate::config::{EthereumConfig, Instance};
use crate::database::{Pool, get_database_client};
use crate::errors::{ConversionError, DatabaseError};
use crate::models::notifications::queries::{
@ -245,7 +245,7 @@ pub async fn check_subscriptions(
}
pub fn create_subscription_signature(
blockchain_config: &BlockchainConfig,
blockchain_config: &EthereumConfig,
user_address: &str,
price: u64,
) -> Result<SignatureData, EthereumError> {

View file

@ -53,11 +53,15 @@ async fn main() -> std::io::Result<()> {
);
let maybe_blockchain = if let Some(blockchain_config) = &config.blockchain {
if let Some(ethereum_config) = blockchain_config.ethereum_config() {
// Create blockchain interface
get_contracts(blockchain_config, &config.storage_dir).await
get_contracts(ethereum_config, &config.storage_dir).await
.map(Some).unwrap()
} else {
None
}
} else {
None
};
let maybe_contract_set = maybe_blockchain.clone()
.map(|blockchain| blockchain.contract_set);
@ -148,12 +152,14 @@ async fn main() -> std::io::Result<()> {
.service(nodeinfo::get_nodeinfo)
.service(nodeinfo::get_nodeinfo_2_0);
if let Some(blockchain_config) = &config.blockchain {
if let Some(ethereum_config) = blockchain_config.ethereum_config() {
// Serve artifacts if available
app = app.service(actix_files::Files::new(
"/contracts",
&blockchain_config.contract_dir,
&ethereum_config.contract_dir,
));
}
};
};
app
})
.workers(num_workers)

View file

@ -293,14 +293,16 @@ async fn authorize_subscription(
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let blockchain_config = config.blockchain.as_ref()
let ethereum_config = config.blockchain.as_ref()
.ok_or(HttpError::NotSupported)?
.ethereum_config()
.ok_or(HttpError::NotSupported)?;
// Wallet address must be public, because subscribers should be able
// to verify that payments are actually sent to the recipient.
let wallet_address = current_user.public_wallet_address()
.ok_or(HttpError::PermissionError)?;
let signature = create_subscription_signature(
blockchain_config,
ethereum_config,
&wallet_address,
query_params.price,
).map_err(|_| HttpError::InternalError)?;

View file

@ -41,6 +41,8 @@ fn get_full_api_version(version: &str) -> String {
impl InstanceInfo {
pub fn create(config: &Config, maybe_blockchain: Option<&ContractSet>) -> Self {
let ethereum_config = config.blockchain.as_ref()
.and_then(|conf| conf.ethereum_config());
let blockchain_features = maybe_blockchain.map(|contract_set| {
BlockchainFeatures {
minter: contract_set.collectible.is_some(),
@ -56,14 +58,14 @@ impl InstanceInfo {
registrations: config.registrations_open,
login_message: config.login_message.clone(),
post_character_limit: config.post_character_limit,
blockchain_id: config.blockchain.as_ref()
blockchain_id: ethereum_config
.map(|val| val.chain_id.to_string()),
blockchain_explorer_url: config.blockchain.as_ref()
blockchain_explorer_url: ethereum_config
.and_then(|val| val.explorer_url.clone()),
blockchain_contract_address: config.blockchain.as_ref()
blockchain_contract_address: ethereum_config
.map(|val| val.contract_address.clone()),
blockchain_features: blockchain_features,
blockchain_info: config.blockchain.as_ref()
blockchain_info: ethereum_config
.and_then(|val| val.chain_info.clone()),
ipfs_gateway_url: config.ipfs_gateway_url.clone(),
}

View file

@ -425,7 +425,9 @@ async fn get_signature(
) -> Result<HttpResponse, HttpError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let blockchain_config = config.blockchain.as_ref()
let ethereum_config = config.blockchain.as_ref()
.ok_or(HttpError::NotSupported)?
.ethereum_config()
.ok_or(HttpError::NotSupported)?;
// Wallet address must be public because minting exposes it
let wallet_address = current_user.public_wallet_address()
@ -440,7 +442,7 @@ async fn get_signature(
.ok_or(HttpError::PermissionError)?;
let token_uri = get_ipfs_url(&ipfs_cid);
let signature = create_mint_signature(
blockchain_config,
ethereum_config,
&wallet_address,
&token_uri,
).map_err(|_| HttpError::InternalError)?;