Custom chainspec support

This commit is contained in:
Artem Vorotnikov
2022-03-26 15:35:02 +03:00
parent d7f1a51294
commit a9aed09b31
3 changed files with 46 additions and 27 deletions

View File

@@ -9,7 +9,7 @@ use akula::{
models::*,
rpc::eth::EthApiServerImpl,
sentry_connector::{
sentry_client_connector::SentryClientConnectorImpl,
chain_config::ChainConfig, sentry_client_connector::SentryClientConnectorImpl,
sentry_client_reactor::SentryClientReactor,
},
stagedsync::{self, stage::*, stages::*, util::*},
@@ -24,6 +24,7 @@ use fastrlp::*;
use jsonrpsee::http_server::HttpServerBuilder;
use rayon::prelude::*;
use std::{
fs::File,
future::pending,
net::SocketAddr,
panic,
@@ -46,13 +47,13 @@ pub struct Opt {
#[clap(long = "datadir", help = "Database directory path", default_value_t)]
pub data_dir: AkulaDataDir,
/// Name of the testnet to join
#[clap(
long = "chain",
help = "Name of the testnet to join",
default_value = "mainnet"
)]
pub chain_name: String,
/// Name of the network to join
#[clap(long)]
pub chain: Option<String>,
/// Chain spec file to use
#[clap(long)]
pub chain_spec_file: Option<PathBuf>,
/// Sentry GRPC service URL
#[clap(
@@ -626,8 +627,15 @@ fn main() -> anyhow::Result<()> {
rt.block_on(async move {
info!("Starting Akula ({})", version_string());
let chains_config = akula::sentry_connector::chain_config::ChainsConfig::new()?;
let chain_config = chains_config.get(&opt.chain_name)?;
let chain_config = if let Some(chain) = opt.chain {
let chains_config = akula::sentry_connector::chain_config::ChainsConfig::new()?;
let chain_config = chains_config.get(&chain)?;
Some(chain_config.chain_spec().clone())
} else if let Some(chain_path) = opt.chain_spec_file {
Some(ron::de::from_reader(File::open(chain_path)?)?)
} else {
None
};
// database setup
let erigon_db = if let Some(erigon_data_dir) = opt.erigon_data_dir {
@@ -652,18 +660,20 @@ fn main() -> anyhow::Result<()> {
.context("failed to create ETL temp dir")?,
);
let db = Arc::new(akula::kv::new_database(&akula_chain_data_dir)?);
{
let chainspec = {
let span = span!(Level::INFO, "", " Genesis initialization ");
let _g = span.enter();
let txn = db.begin_mutable()?;
if akula::genesis::initialize_genesis(
&txn,
&*etl_temp_dir,
chain_config.chain_spec().clone(),
)? {
let (chainspec, initialized) =
akula::genesis::initialize_genesis(&txn, &*etl_temp_dir, chain_config)?;
if initialized {
txn.commit()?;
}
}
chainspec
};
let chain_config = ChainConfig::new(chainspec);
if let Some(listen_address) = opt.rpc_listen_address {
let db = db.clone();

View File

@@ -13,7 +13,7 @@ pub struct ChainConfig {
}
impl ChainConfig {
fn new(chain_spec: ChainSpec) -> Self {
pub fn new(chain_spec: ChainSpec) -> Self {
let genesis = GenesisState::new(chain_spec.clone());
let genesis_header = genesis.header(&genesis.initial_state());
let genesis_block_hash = genesis_header.hash();

View File

@@ -1,8 +1,10 @@
use crate::{
kv::{mdbx::*, tables},
models::*,
res::chainspec::MAINNET,
state::*,
};
use anyhow::format_err;
use tempfile::TempDir;
#[derive(Clone, Debug)]
@@ -62,15 +64,24 @@ impl GenesisState {
pub fn initialize_genesis<'db, E>(
txn: &MdbxTransaction<'db, RW, E>,
etl_temp_dir: &TempDir,
chainspec: ChainSpec,
) -> anyhow::Result<bool>
chainspec: Option<ChainSpec>,
) -> anyhow::Result<(ChainSpec, bool)>
where
E: EnvironmentKind,
{
if txn.get(tables::Config, ())?.is_some() {
return Ok(false);
if let Some(existing_chainspec) = txn.get(tables::Config, ())? {
if let Some(chainspec) = chainspec {
if chainspec != existing_chainspec {
return Err(format_err!(
"Genesis initialized, but chainspec does not match one in database"
));
}
}
return Ok((existing_chainspec, false));
}
let chainspec = chainspec.unwrap_or_else(|| MAINNET.clone());
let genesis = chainspec.genesis.number;
let mut state_buffer = Buffer::new(txn, None);
state_buffer.begin_block(genesis);
@@ -139,9 +150,9 @@ where
txn.set(tables::LastHeader, (), block_hash)?;
txn.set(tables::Config, (), chainspec)?;
txn.set(tables::Config, (), chainspec.clone())?;
Ok(true)
Ok((chainspec, true))
}
#[cfg(test)]
@@ -178,9 +189,7 @@ mod tests {
let tx = db.begin_mutable().unwrap();
let temp_dir = TempDir::new().unwrap();
assert!(
initialize_genesis(&tx, &temp_dir, crate::res::chainspec::MAINNET.clone()).unwrap()
);
assert!(initialize_genesis(&tx, &temp_dir, None).unwrap().1);
let genesis_hash = tx.get(tables::CanonicalHeader, 0.into()).unwrap().unwrap();