Ethereum classic (#1706)

* Add Ethereum Classic support

(Rename homestead-dogmatic -> classic)

* Additional change needed.

* More needed changes.

* Separate database path for known forks.

* Address minor grumble.
This commit is contained in:
Gav Wood 2016-07-25 10:20:22 +02:00 committed by GitHub
parent 8574bfd546
commit e734810293
8 changed files with 20 additions and 14 deletions

View File

@ -1,5 +1,6 @@
{
"name": "Frontier/Homestead",
"name": "Ethereum Classic",
"forkName": "classic",
"engine": {
"Ethash": {
"params": {

View File

@ -149,9 +149,9 @@ const HISTORY: u64 = 1200;
const CLIENT_DB_VER_STR: &'static str = "5.3";
/// Get the path for the databases given the root path and information on the databases.
pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf {
pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256, fork_name: Option<&String>) -> PathBuf {
let mut dir = path.to_path_buf();
dir.push(H64::from(genesis_hash).hex());
dir.push(format!("{:?}{}", H64::from(genesis_hash), fork_name.map(|f| format!("-{}", f)).unwrap_or_default()));
//TODO: sec/fat: pruned/full versioning
// version here is a bit useless now, since it's controlled only be the pruning algo.
dir.push(format!("v{}-sec-{}", CLIENT_DB_VER_STR, pruning));
@ -174,7 +174,7 @@ impl Client {
miner: Arc<Miner>,
message_channel: IoChannel<ClientIoMessage>,
) -> Result<Arc<Client>, ClientError> {
let path = get_db_path(path, config.pruning, spec.genesis_header().hash());
let path = get_db_path(path, config.pruning, spec.genesis_header().hash(), spec.fork_name.as_ref());
let gb = spec.genesis_block();
let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path));
let tracedb = Arc::new(try!(TraceDB::new(config.tracing, &path, chain.clone())));

View File

@ -33,14 +33,10 @@ use super::spec::*;
pub fn new_olympic() -> Spec { Spec::load(include_bytes!("../../res/ethereum/olympic.json")) }
/// Create a new Frontier mainnet chain spec.
pub fn new_frontier() -> Spec {
Spec::load(include_bytes!("../../res/ethereum/frontier.json"))
}
pub fn new_frontier() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier.json")) }
/// Create a new Frontier mainnet chain spec without the DAO hardfork.
pub fn new_frontier_dogmatic() -> Spec {
Spec::load(include_bytes!("../../res/ethereum/frontier-dogmatic.json"))
}
pub fn new_classic() -> Spec { Spec::load(include_bytes!("../../res/ethereum/classic.json")) }
/// Create a new Frontier chain spec as though it never changes to Homestead.
pub fn new_frontier_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier_test.json")) }

View File

@ -62,6 +62,9 @@ impl ClientService {
panic_handler.forward_from(&io_service);
info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name()));
if spec.fork_name.is_some() {
warn!("Your chain is an alternative fork. {}", Colour::Red.bold().paint("TRANSACTIONS MAY BE REPLAYED ON THE MAINNET!"));
}
let client = try!(Client::new(config, spec, db_path, miner, io_service.channel()));
panic_handler.forward_from(client.deref());
let client_io = Arc::new(ClientIoHandler {

View File

@ -58,6 +58,8 @@ pub struct Spec {
pub name: String,
/// What engine are we using for this?
pub engine: Box<Engine>,
/// The fork identifier for this chain. Only needed to distinguish two chains sharing the same genesis.
pub fork_name: Option<String>,
/// Known nodes on the network in enode format.
pub nodes: Vec<String>,
@ -105,6 +107,7 @@ impl From<ethjson::spec::Spec> for Spec {
name: s.name.into(),
params: params.clone(),
engine: Spec::engine(s.engine, params, builtins),
fork_name: s.fork_name.map(Into::into),
nodes: s.nodes.unwrap_or_else(Vec::new),
parent_hash: g.parent_hash,
transactions_root: g.transactions_root,
@ -118,7 +121,7 @@ impl From<ethjson::spec::Spec> for Spec {
seal_fields: seal.fields,
seal_rlp: seal.rlp,
state_root_memo: RwLock::new(g.state_root),
genesis_state: From::from(s.accounts)
genesis_state: From::from(s.accounts),
}
}
}

View File

@ -26,6 +26,9 @@ use spec::{Params, Genesis, Engine, State};
pub struct Spec {
/// Spec name.
pub name: String,
/// Special fork name.
#[serde(rename="forkName")]
pub fork_name: Option<String>,
/// Engine.
pub engine: Engine,
/// Spec params.

View File

@ -201,7 +201,7 @@ impl Configuration {
pub fn spec(&self) -> Spec {
match self.chain().as_str() {
"frontier" | "homestead" | "mainnet" => ethereum::new_frontier(),
"homestead-dogmatic" => ethereum::new_frontier_dogmatic(),
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => ethereum::new_classic(),
"morden" | "testnet" => ethereum::new_morden(),
"olympic" => ethereum::new_olympic(),
f => Spec::load(contents(f).unwrap_or_else(|_| {
@ -288,7 +288,7 @@ impl Configuration {
let mut latest_era = None;
let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted];
for i in jdb_types.into_iter() {
let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i, kvdb::DatabaseConfig::default());
let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash(), spec.fork_name.as_ref()), "state"), *i, kvdb::DatabaseConfig::default());
trace!(target: "parity", "Looking for best DB: {} at {:?}", i, db.latest_era());
match (latest_era, db.latest_era()) {
(Some(best), Some(this)) if best >= this => {}

View File

@ -188,7 +188,7 @@ fn execute_upgrades(conf: &Configuration, spec: &Spec, client_config: &ClientCon
_ => {},
}
let db_path = get_db_path(Path::new(&conf.path()), client_config.pruning, spec.genesis_header().hash());
let db_path = get_db_path(Path::new(&conf.path()), client_config.pruning, spec.genesis_header().hash(), spec.fork_name.as_ref());
let result = migrate(&db_path, client_config.pruning);
if let Err(err) = result {
die_with_message(&format!("{} DB path: {}", err, db_path.to_string_lossy()));