mod mapping_db;
mod meta_db;
#[cfg(test)]
mod tests;
pub(crate) mod utils;
use std::{path::PathBuf, str::FromStr, sync::Arc};
use clap::ValueEnum;
use ethereum_types::H256;
use serde::Deserialize;
use sc_cli::{PruningParams, SharedParams};
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::traits::Block as BlockT;
use self::{
mapping_db::{MappingDb, MappingKey, MappingValue},
meta_db::{MetaDb, MetaKey, MetaValue},
};
#[derive(Debug, Clone, clap::Parser)]
pub struct FrontierDbCmd {
#[arg(value_enum, ignore_case = true, required = true)]
pub operation: Operation,
#[arg(value_enum, ignore_case = true, required = true)]
pub column: Column,
#[arg(short('k'), long, required = true)]
pub key: String,
#[arg(long)]
pub value: Option<PathBuf>,
#[command(flatten)]
pub shared_params: SharedParams,
#[allow(missing_docs)]
#[command(flatten)]
pub pruning_params: PruningParams,
}
#[derive(ValueEnum, Debug, Clone)]
pub enum Operation {
Create,
Read,
Update,
Delete,
}
#[derive(ValueEnum, Debug, Clone)]
pub enum Column {
Meta,
Block,
Transaction,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum DbValue<H> {
Meta(MetaValue<H>),
Mapping(MappingValue<H>),
}
impl FrontierDbCmd {
pub fn run<C, B: BlockT>(
&self,
client: Arc<C>,
backend: Arc<fc_db::kv::Backend<B>>,
) -> sc_cli::Result<()>
where
C: ProvideRuntimeApi<B>,
C::Api: fp_rpc::EthereumRuntimeRPCApi<B>,
C: HeaderBackend<B>,
{
match self.column {
Column::Meta => {
let meta_db = MetaDb::new(self, backend);
let key = MetaKey::from_str(&self.key)?;
let value = match utils::maybe_deserialize_value::<B>(
&self.operation,
self.value.as_ref(),
)? {
Some(DbValue::Meta(value)) => Some(value),
None => None,
_ => return Err(format!("Unexpected `{:?}` value", self.value).into()),
};
meta_db.query(&key, &value)?
}
Column::Block | Column::Transaction => {
let mapping_db = MappingDb::new(self, client, backend);
let key = MappingKey::EthBlockOrTransactionHash(
H256::from_str(&self.key).expect("H256 provided key"),
);
let value = match utils::maybe_deserialize_value::<B>(
&self.operation,
self.value.as_ref(),
)? {
Some(DbValue::Mapping(value)) => Some(value),
None => None,
_ => return Err(format!("Unexpected `{:?}` value", self.value).into()),
};
mapping_db.query(&self.column, &key, &value)?
}
}
Ok(())
}
}
impl sc_cli::CliConfiguration for FrontierDbCmd {
fn shared_params(&self) -> &SharedParams {
&self.shared_params
}
fn pruning_params(&self) -> Option<&PruningParams> {
Some(&self.pruning_params)
}
}