Use shared ContractSet object when verifing user during registration

Server will not start if blockchain configuration is invalid.
This commit is contained in:
silverpill 2022-06-23 20:48:05 +00:00
parent 6b06d6d18e
commit b618c5b31f
4 changed files with 22 additions and 29 deletions

View file

@ -16,10 +16,9 @@ use super::sync::{
}; };
use super::utils::parse_address; use super::utils::parse_address;
pub const ADAPTER: &str = "IAdapter"; const ADAPTER: &str = "IAdapter";
pub const SUBSCRIPTION: &str = "ISubscription"; const SUBSCRIPTION: &str = "ISubscription";
pub const ERC20: &str = "IERC20"; const ERC721: &str = "IERC721Metadata";
pub const ERC721: &str = "IERC721Metadata";
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ArtifactError { pub enum ArtifactError {
@ -33,7 +32,7 @@ pub enum ArtifactError {
KeyError, KeyError,
} }
pub fn load_abi( fn load_abi(
contract_dir: &Path, contract_dir: &Path,
contract_name: &str, contract_name: &str,
) -> Result<Vec<u8>, ArtifactError> { ) -> Result<Vec<u8>, ArtifactError> {
@ -47,14 +46,13 @@ pub fn load_abi(
Ok(contract_abi) Ok(contract_abi)
} }
#[derive(Clone)]
pub struct ContractSet { pub struct ContractSet {
pub web3: Web3<Http>, pub web3: Web3<Http>,
// Last synced block // Last synced block
pub current_block: u64, pub current_block: u64,
#[allow(dead_code)]
pub adapter: Contract<Http>, pub adapter: Contract<Http>,
pub collectible: Contract<Http>, pub collectible: Contract<Http>,
pub subscription: Contract<Http>, pub subscription: Contract<Http>,
} }

View file

@ -1,25 +1,15 @@
use web3::contract::{Contract, Options}; use web3::contract::Options;
use crate::config::BlockchainConfig; use super::contracts::ContractSet;
use super::api::connect;
use super::contracts::{ADAPTER, load_abi};
use super::errors::EthereumError; use super::errors::EthereumError;
use super::utils::parse_address; use super::utils::parse_address;
pub async fn is_allowed_user( pub async fn is_allowed_user(
config: &BlockchainConfig, contract_set: &ContractSet,
user_address: &str, user_address: &str,
) -> Result<bool, EthereumError> { ) -> Result<bool, EthereumError> {
let web3 = connect(&config.api_url)?;
let adapter_abi = load_abi(&config.contract_dir, ADAPTER)?;
let adapter_address = parse_address(&config.contract_address)?;
let adapter = Contract::from_json(
web3.eth(),
adapter_address,
&adapter_abi,
)?;
let user_address = parse_address(user_address)?; let user_address = parse_address(user_address)?;
let result: bool = adapter.query( let result: bool = contract_set.adapter.query(
"isAllowedUser", (user_address,), "isAllowedUser", (user_address,),
None, Options::default(), None, None, Options::default(), None,
).await?; ).await?;

View file

@ -51,16 +51,15 @@ async fn main() -> std::io::Result<()> {
config.environment, config.environment,
); );
let maybe_contract_set = if let Some(blockchain_config) = &config.blockchain { let maybe_blockchain = if let Some(blockchain_config) = &config.blockchain {
// Create blockchain interface // Create blockchain interface
get_contracts(blockchain_config, &config.storage_dir).await get_contracts(blockchain_config, &config.storage_dir).await
.map_err(|err| log::error!("{}", err)) .map(Some).unwrap()
.ok()
} else { } else {
None None
}; };
scheduler::run(config.clone(), maybe_contract_set, db_pool.clone()); scheduler::run(config.clone(), maybe_blockchain.clone(), db_pool.clone());
log::info!("scheduler started"); log::info!("scheduler started");
let http_socket_addr = format!( let http_socket_addr = format!(
@ -117,6 +116,7 @@ async fn main() -> std::io::Result<()> {
.app_data(web::JsonConfig::default().limit(MAX_UPLOAD_SIZE)) .app_data(web::JsonConfig::default().limit(MAX_UPLOAD_SIZE))
.app_data(web::Data::new(config.clone())) .app_data(web::Data::new(config.clone()))
.app_data(web::Data::new(db_pool.clone())) .app_data(web::Data::new(db_pool.clone()))
.app_data(web::Data::new(maybe_blockchain.clone()))
.app_data(web::Data::clone(&inbox_mutex)) .app_data(web::Data::clone(&inbox_mutex))
.service(actix_files::Files::new( .service(actix_files::Files::new(
"/media", "/media",

View file

@ -11,6 +11,7 @@ use crate::activitypub::deliverer::deliver_activity;
use crate::config::Config; use crate::config::Config;
use crate::database::{Pool, get_database_client}; use crate::database::{Pool, get_database_client};
use crate::errors::{DatabaseError, HttpError, ValidationError}; use crate::errors::{DatabaseError, HttpError, ValidationError};
use crate::ethereum::contracts::ContractSet;
use crate::ethereum::eip4361::verify_eip4361_signature; use crate::ethereum::eip4361::verify_eip4361_signature;
use crate::ethereum::gate::is_allowed_user; use crate::ethereum::gate::is_allowed_user;
use crate::ethereum::identity::{ use crate::ethereum::identity::{
@ -68,6 +69,7 @@ use super::types::{
pub async fn create_account( pub async fn create_account(
config: web::Data<Config>, config: web::Data<Config>,
db_pool: web::Data<Pool>, db_pool: web::Data<Pool>,
maybe_blockchain: web::Data<Option<ContractSet>>,
account_data: web::Json<AccountCreateData>, account_data: web::Json<AccountCreateData>,
) -> Result<HttpResponse, HttpError> { ) -> Result<HttpResponse, HttpError> {
let db_client = &mut **get_database_client(&db_pool).await?; let db_client = &mut **get_database_client(&db_pool).await?;
@ -103,16 +105,19 @@ pub async fn create_account(
}; };
assert!(password_hash.is_some() || wallet_address.is_some()); assert!(password_hash.is_some() || wallet_address.is_some());
if let Some(blockchain_config) = config.blockchain.as_ref() { if let Some(contract_set) = maybe_blockchain.as_ref() {
// Wallet address is required if blockchain integration is enabled // Wallet address is required if blockchain integration is enabled
let wallet_address = wallet_address.as_ref() let wallet_address = wallet_address.as_ref()
.ok_or(ValidationError("wallet address is required"))?; .ok_or(ValidationError("wallet address is required"))?;
let is_allowed = is_allowed_user(blockchain_config, wallet_address).await let is_allowed = is_allowed_user(contract_set, wallet_address).await
.map_err(|_| HttpError::InternalError)?; .map_err(|_| HttpError::InternalError)?;
if !is_allowed { if !is_allowed {
return Err(ValidationError("not allowed to sign up").into()); return Err(ValidationError("not allowed to sign up").into());
} };
} } else {
assert!(config.blockchain.is_none());
};
// Generate RSA private key for actor // Generate RSA private key for actor
let private_key = match web::block(generate_private_key).await { let private_key = match web::block(generate_private_key).await {
Ok(Ok(private_key)) => private_key, Ok(Ok(private_key)) => private_key,