ensure genesis validator set in DB
This commit is contained in:
parent
a278dd5a0a
commit
af868a7439
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -340,7 +340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "elastic-array"
|
name = "elastic-array"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "git+https://github.com/paritytech/elastic-array?branch=0.7.0#970a11eca8a6b3591b476155c5896b4757b5c7b8"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -713,7 +713,7 @@ version = "1.7.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"elastic-array 0.7.0 (git+https://github.com/paritytech/elastic-array?branch=0.7.0)",
|
"elastic-array 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)",
|
"eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)",
|
||||||
"ethcore-bigint 0.1.2",
|
"ethcore-bigint 0.1.2",
|
||||||
@ -2018,7 +2018,7 @@ name = "rlp"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"elastic-array 0.7.0 (git+https://github.com/paritytech/elastic-array?branch=0.7.0)",
|
"elastic-array 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-bigint 0.1.2",
|
"ethcore-bigint 0.1.2",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2790,7 +2790,7 @@ dependencies = [
|
|||||||
"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8"
|
"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8"
|
||||||
"checksum dtoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5edd69c67b2f8e0911629b7e6b8a34cb3956613cd7c6e6414966dee349c2db4f"
|
"checksum dtoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5edd69c67b2f8e0911629b7e6b8a34cb3956613cd7c6e6414966dee349c2db4f"
|
||||||
"checksum either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2b503c86dad62aaf414ecf2b8c527439abedb3f8d812537f0b12bfd6f32a91"
|
"checksum either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2b503c86dad62aaf414ecf2b8c527439abedb3f8d812537f0b12bfd6f32a91"
|
||||||
"checksum elastic-array 0.7.0 (git+https://github.com/paritytech/elastic-array?branch=0.7.0)" = "<none>"
|
"checksum elastic-array 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71a64decd4b8cd06654a4e643c45cb558ad554abbffd82a7e16e34f45f51b605"
|
||||||
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
|
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
|
||||||
"checksum eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
|
"checksum eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
|
||||||
"checksum ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63df67d0af5e3cb906b667ca1a6e00baffbed87d0d8f5f78468a1f5eb3a66345"
|
"checksum ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63df67d0af5e3cb906b667ca1a6e00baffbed87d0d8f5f78468a1f5eb3a66345"
|
||||||
|
@ -810,9 +810,11 @@ impl BlockChain {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
transitions.candidates.push(transition);
|
// ensure we don't write any duplicates.
|
||||||
|
if transitions.candidates.iter().find(|c| c.block_hash == transition.block_hash).is_none() {
|
||||||
batch.write(db::COL_EXTRA, &epoch_num, &transitions);
|
transitions.candidates.push(transition);
|
||||||
|
batch.write(db::COL_EXTRA, &epoch_num, &transitions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a child to a given block. Assumes that the block hash is in
|
/// Add a child to a given block. Assumes that the block hash is in
|
||||||
|
@ -49,7 +49,7 @@ use evm::{Factory as EvmFactory, Schedule};
|
|||||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||||
use factory::Factories;
|
use factory::Factories;
|
||||||
use futures::{future, Future};
|
use futures::{future, Future};
|
||||||
use header::BlockNumber;
|
use header::{BlockNumber, Header};
|
||||||
use io::*;
|
use io::*;
|
||||||
use log_entry::LocalizedLogEntry;
|
use log_entry::LocalizedLogEntry;
|
||||||
use miner::{Miner, MinerService, TransactionImportResult};
|
use miner::{Miner, MinerService, TransactionImportResult};
|
||||||
@ -247,17 +247,29 @@ impl Client {
|
|||||||
exit_handler: Mutex::new(None),
|
exit_handler: Mutex::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// prune old states.
|
||||||
{
|
{
|
||||||
let state_db = client.state_db.lock().boxed_clone();
|
let state_db = client.state_db.lock().boxed_clone();
|
||||||
let chain = client.chain.read();
|
let chain = client.chain.read();
|
||||||
client.prune_ancient(state_db, &chain)?;
|
client.prune_ancient(state_db, &chain)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure genesis epoch proof in the DB.
|
||||||
|
{
|
||||||
|
let mut batch = DBTransaction::new();
|
||||||
|
let chain = client.chain.read();
|
||||||
|
client.generate_epoch_proof(&mut batch, &spec.genesis_header(), 0, &*chain);
|
||||||
|
client.db.read().write_buffered(batch);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
|
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
|
||||||
trace!(target: "client", "Found registrar at {}", reg_addr);
|
trace!(target: "client", "Found registrar at {}", reg_addr);
|
||||||
let registrar = Registry::new(reg_addr);
|
let registrar = Registry::new(reg_addr);
|
||||||
*client.registrar.lock() = Some(registrar);
|
*client.registrar.lock() = Some(registrar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure buffered changes are flushed.
|
||||||
|
client.db.read().flush().map_err(ClientError::Database)?;
|
||||||
Ok(client)
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,7 +593,7 @@ impl Client {
|
|||||||
let entering_new_epoch = {
|
let entering_new_epoch = {
|
||||||
use engines::EpochChange;
|
use engines::EpochChange;
|
||||||
match self.engine.is_epoch_end(block.header(), Some(block_data), Some(&receipts)) {
|
match self.engine.is_epoch_end(block.header(), Some(block_data), Some(&receipts)) {
|
||||||
EpochChange::Yes(e, p) => Some((block.header().clone(), e, p)),
|
EpochChange::Yes(e, _) => Some((block.header().clone(), e)),
|
||||||
EpochChange::No => None,
|
EpochChange::No => None,
|
||||||
EpochChange::Unsure(_) => {
|
EpochChange::Unsure(_) => {
|
||||||
warn!(target: "client", "Detected invalid engine implementation.");
|
warn!(target: "client", "Detected invalid engine implementation.");
|
||||||
@ -599,48 +611,8 @@ impl Client {
|
|||||||
state.journal_under(&mut batch, number, hash).expect("DB commit failed");
|
state.journal_under(&mut batch, number, hash).expect("DB commit failed");
|
||||||
let route = chain.insert_block(&mut batch, block_data, receipts);
|
let route = chain.insert_block(&mut batch, block_data, receipts);
|
||||||
|
|
||||||
if let Some((header, epoch, expected)) = entering_new_epoch {
|
if let Some((header, epoch)) = entering_new_epoch {
|
||||||
use std::cell::RefCell;
|
self.generate_epoch_proof(&mut batch, &header, epoch, &chain);
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
debug!(target: "client", "Generating validation proof for block {}", hash);
|
|
||||||
|
|
||||||
// proof is two-part. state items read in lexicographical order,
|
|
||||||
// and the secondary "proof" part.
|
|
||||||
let read_values = RefCell::new(BTreeSet::new());
|
|
||||||
let block_id = BlockId::Hash(hash.clone());
|
|
||||||
let proof = {
|
|
||||||
let call = |a, d| {
|
|
||||||
let tx = self.contract_call_tx(block_id, a, d);
|
|
||||||
let (result, items) = self.prove_transaction(tx, block_id)
|
|
||||||
.ok_or_else(|| format!("Unable to make call to generate epoch proof."))?;
|
|
||||||
|
|
||||||
read_values.borrow_mut().extend(items);
|
|
||||||
Ok(result)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.engine.epoch_proof(&header, &call)
|
|
||||||
};
|
|
||||||
|
|
||||||
match proof {
|
|
||||||
Ok(proof) => {
|
|
||||||
if proof != expected {
|
|
||||||
warn!(target: "client", "Extracted epoch change proof different than expected.");
|
|
||||||
warn!(target: "client", "Using a custom engine implementation?");
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert into database, using the generated proof.
|
|
||||||
chain.insert_epoch_transition(&mut batch, epoch, EpochTransition {
|
|
||||||
block_hash: hash.clone(),
|
|
||||||
proof: proof,
|
|
||||||
state_proof: read_values.into_inner().into_iter().collect(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
warn!(target: "client", "Error generating epoch change proof for block {}: {}", hash, e);
|
|
||||||
warn!(target: "client", "Snapshots generated by this node will be incomplete.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tracedb.read().import(&mut batch, TraceImportRequest {
|
self.tracedb.read().import(&mut batch, TraceImportRequest {
|
||||||
@ -665,6 +637,46 @@ impl Client {
|
|||||||
route
|
route
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate an epoch transition proof at the given block, and write it into the given blockchain.
|
||||||
|
fn generate_epoch_proof(&self, batch: &mut DBTransaction, header: &Header, epoch_number: u64, chain: &BlockChain) {
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
let hash = header.hash();
|
||||||
|
debug!(target: "client", "Generating validation proof for block {}", hash);
|
||||||
|
|
||||||
|
// proof is two-part. state items read in lexicographical order,
|
||||||
|
// and the secondary "proof" part.
|
||||||
|
let read_values = RefCell::new(BTreeSet::new());
|
||||||
|
let block_id = BlockId::Hash(hash.clone());
|
||||||
|
let proof = {
|
||||||
|
let call = |a, d| {
|
||||||
|
let tx = self.contract_call_tx(block_id, a, d);
|
||||||
|
let (result, items) = self.prove_transaction(tx, block_id)
|
||||||
|
.ok_or_else(|| format!("Unable to make call to generate epoch proof."))?;
|
||||||
|
|
||||||
|
read_values.borrow_mut().extend(items);
|
||||||
|
Ok(result)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.engine.epoch_proof(&header, &call)
|
||||||
|
};
|
||||||
|
|
||||||
|
// insert into database, using the generated proof.
|
||||||
|
match proof {
|
||||||
|
Ok(proof) =>
|
||||||
|
chain.insert_epoch_transition(batch, epoch_number, EpochTransition {
|
||||||
|
block_hash: hash.clone(),
|
||||||
|
proof: proof,
|
||||||
|
state_proof: read_values.into_inner().into_iter().collect(),
|
||||||
|
}),
|
||||||
|
Err(e) => {
|
||||||
|
warn!(target: "client", "Error generating epoch change proof for block {}: {}", hash, e);
|
||||||
|
warn!(target: "client", "Snapshots generated by this node will be incomplete.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// prune ancient states until below the memory limit or only the minimum amount remain.
|
// prune ancient states until below the memory limit or only the minimum amount remain.
|
||||||
fn prune_ancient(&self, mut state_db: StateDB, chain: &BlockChain) -> Result<(), ClientError> {
|
fn prune_ancient(&self, mut state_db: StateDB, chain: &BlockChain) -> Result<(), ClientError> {
|
||||||
let number = match state_db.journal_db().latest_era() {
|
let number = match state_db.journal_db().latest_era() {
|
||||||
|
Loading…
Reference in New Issue
Block a user