store epoch transition proofs in DB
This commit is contained in:
parent
6da6c755a5
commit
a278dd5a0a
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -339,8 +339,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "elastic-array"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/paritytech/elastic-array#346f1ba5982576dab9d0b8fa178b50e1db0a21cd"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/paritytech/elastic-array?branch=0.7.0#970a11eca8a6b3591b476155c5896b4757b5c7b8"
|
||||
dependencies = [
|
||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -713,7 +713,7 @@ version = "1.7.0"
|
||||
dependencies = [
|
||||
"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)",
|
||||
"elastic-array 0.6.0 (git+https://github.com/paritytech/elastic-array)",
|
||||
"elastic-array 0.7.0 (git+https://github.com/paritytech/elastic-array?branch=0.7.0)",
|
||||
"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)",
|
||||
"ethcore-bigint 0.1.2",
|
||||
@ -2018,7 +2018,7 @@ name = "rlp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elastic-array 0.6.0 (git+https://github.com/paritytech/elastic-array)",
|
||||
"elastic-array 0.7.0 (git+https://github.com/paritytech/elastic-array?branch=0.7.0)",
|
||||
"ethcore-bigint 0.1.2",
|
||||
"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)",
|
||||
@ -2790,7 +2790,7 @@ dependencies = [
|
||||
"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 either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2b503c86dad62aaf414ecf2b8c527439abedb3f8d812537f0b12bfd6f32a91"
|
||||
"checksum elastic-array 0.6.0 (git+https://github.com/paritytech/elastic-array)" = "<none>"
|
||||
"checksum elastic-array 0.7.0 (git+https://github.com/paritytech/elastic-array?branch=0.7.0)" = "<none>"
|
||||
"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 ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63df67d0af5e3cb906b667ca1a6e00baffbed87d0d8f5f78468a1f5eb3a66345"
|
||||
|
@ -258,7 +258,7 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
||||
}.fake_sign(req.from);
|
||||
|
||||
self.prove_transaction(transaction, id)
|
||||
.map(|proof| ::request::ExecutionResponse { items: proof })
|
||||
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
|
||||
}
|
||||
|
||||
fn ready_transactions(&self) -> Vec<PendingTransaction> {
|
||||
|
@ -797,6 +797,24 @@ impl BlockChain {
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert an epoch transition. Provide an epoch number being transitioned to
|
||||
/// and epoch transition object.
|
||||
///
|
||||
/// The block the transition occurred at should have already been inserted into the chain.
|
||||
pub fn insert_epoch_transition(&self, batch: &mut DBTransaction, epoch_num: u64, transition: EpochTransition) {
|
||||
let mut transitions = match self.db.read(db::COL_EXTRA, &epoch_num) {
|
||||
Some(existing) => existing,
|
||||
None => EpochTransitions {
|
||||
number: epoch_num,
|
||||
candidates: Vec::with_capacity(1),
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
/// the chain and the child's parent is this block.
|
||||
///
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
use bloomchain;
|
||||
use util::*;
|
||||
use util::kvdb::PREFIX_LEN as DB_PREFIX_LEN;
|
||||
use rlp::*;
|
||||
use header::BlockNumber;
|
||||
use receipt::Receipt;
|
||||
@ -37,6 +38,8 @@ pub enum ExtrasIndex {
|
||||
BlocksBlooms = 3,
|
||||
/// Block receipts index
|
||||
BlockReceipts = 4,
|
||||
/// Epoch transition data index.
|
||||
EpochTransitions = 5,
|
||||
}
|
||||
|
||||
fn with_index(hash: &H256, i: ExtrasIndex) -> H264 {
|
||||
@ -134,6 +137,39 @@ impl Key<BlockReceipts> for H256 {
|
||||
}
|
||||
}
|
||||
|
||||
/// length of epoch keys.
|
||||
pub const EPOCH_KEY_LEN: usize = DB_PREFIX_LEN + 16;
|
||||
|
||||
/// epoch key prefix.
|
||||
/// used to iterate over all epoch transitions in order from genesis.
|
||||
pub fn epoch_key_prefix() -> [u8; DB_PREFIX_LEN] {
|
||||
let mut arr = [0u8; DB_PREFIX_LEN];
|
||||
arr[0] = ExtrasIndex::EpochTransitions as u8;
|
||||
|
||||
arr
|
||||
}
|
||||
|
||||
pub struct EpochTransitionsKey([u8; EPOCH_KEY_LEN]);
|
||||
impl Deref for EpochTransitionsKey {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &[u8] { &self.0[..] }
|
||||
}
|
||||
|
||||
impl Key<EpochTransitions> for u64 {
|
||||
type Target = EpochTransitionsKey;
|
||||
|
||||
fn key(&self) -> Self::Target {
|
||||
let mut arr = [0u8; EPOCH_KEY_LEN];
|
||||
arr[..DB_PREFIX_LEN].copy_from_slice(&epoch_key_prefix()[..]);
|
||||
|
||||
write!(&mut arr[DB_PREFIX_LEN..], "{:016x}", self)
|
||||
.expect("format arg is valid; no more than 16 chars will be written; qed");
|
||||
|
||||
EpochTransitionsKey(arr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Familial details concerning a block
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BlockDetails {
|
||||
@ -144,7 +180,7 @@ pub struct BlockDetails {
|
||||
/// Parent block hash
|
||||
pub parent: H256,
|
||||
/// List of children block hashes
|
||||
pub children: Vec<H256>
|
||||
pub children: Vec<H256>,
|
||||
}
|
||||
|
||||
impl HeapSizeOf for BlockDetails {
|
||||
@ -241,6 +277,60 @@ impl HeapSizeOf for BlockReceipts {
|
||||
}
|
||||
}
|
||||
|
||||
/// Candidate transitions to an epoch with specific number.
|
||||
#[derive(Clone)]
|
||||
pub struct EpochTransitions {
|
||||
pub number: u64,
|
||||
pub candidates: Vec<EpochTransition>,
|
||||
}
|
||||
|
||||
impl Encodable for EpochTransitions {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.begin_list(2).append(&self.number).append_list(&self.candidates);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for EpochTransitions {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(EpochTransitions {
|
||||
number: rlp.val_at(0)?,
|
||||
candidates: rlp.list_at(1)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EpochTransition {
|
||||
pub block_hash: H256, // block hash at which the transition occurred.
|
||||
pub proof: Vec<u8>, // "transition/epoch" proof from the engine.
|
||||
pub state_proof: Vec<DBValue>, // state items necessary to regenerate proof.
|
||||
}
|
||||
|
||||
impl Encodable for EpochTransition {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.begin_list(3)
|
||||
.append(&self.block_hash)
|
||||
.append(&self.proof)
|
||||
.begin_list(self.state_proof.len());
|
||||
|
||||
for item in &self.state_proof {
|
||||
s.append(&&**item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for EpochTransition {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
Ok(EpochTransition {
|
||||
block_hash: rlp.val_at(0)?,
|
||||
proof: rlp.val_at(1)?,
|
||||
state_proof: rlp.at(2)?.iter().map(|x| {
|
||||
Ok(DBValue::from_slice(x.data()?))
|
||||
}).collect::<Result<Vec<_>, _>>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rlp::*;
|
||||
|
@ -31,5 +31,6 @@ pub mod generator;
|
||||
pub use self::blockchain::{BlockProvider, BlockChain};
|
||||
pub use self::cache::CacheSize;
|
||||
pub use self::config::Config;
|
||||
pub use self::extras::EpochTransition;
|
||||
pub use types::tree_route::TreeRoute;
|
||||
pub use self::import_route::ImportRoute;
|
||||
|
@ -32,13 +32,13 @@ use util::kvdb::*;
|
||||
// other
|
||||
use basic_types::Seal;
|
||||
use block::*;
|
||||
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
|
||||
use blockchain::{BlockChain, BlockProvider, EpochTransition, TreeRoute, ImportRoute};
|
||||
use blockchain::extras::TransactionAddress;
|
||||
use client::Error as ClientError;
|
||||
use client::{
|
||||
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
|
||||
MiningBlockChainClient, EngineClient, TraceFilter, CallAnalytics, BlockImportError, Mode,
|
||||
ChainNotify, PruningInfo,
|
||||
ChainNotify, PruningInfo, ProvingBlockChainClient,
|
||||
};
|
||||
use encoded;
|
||||
use engines::Engine;
|
||||
@ -578,15 +578,15 @@ impl Client {
|
||||
|
||||
// generate validation proof if the engine requires them.
|
||||
// TODO: make conditional?
|
||||
let generate_proof = {
|
||||
let entering_new_epoch = {
|
||||
use engines::EpochChange;
|
||||
match self.engine.is_epoch_end(block.header(), Some(block_data), Some(&receipts)) {
|
||||
EpochChange::Yes(_) => true,
|
||||
EpochChange::No => false,
|
||||
EpochChange::Yes(e, p) => Some((block.header().clone(), e, p)),
|
||||
EpochChange::No => None,
|
||||
EpochChange::Unsure(_) => {
|
||||
warn!(target: "client", "Detected invalid engine implementation.");
|
||||
warn!(target: "client", "Engine claims to require more block data, but everything provided.");
|
||||
false
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -596,14 +596,53 @@ impl Client {
|
||||
// TODO: Prove it with a test.
|
||||
let mut state = block.drain();
|
||||
|
||||
if generate_proof {
|
||||
debug!(target: "client", "Generating validation proof for block {}", hash);
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
state.journal_under(&mut batch, number, hash).expect("DB commit failed");
|
||||
let route = chain.insert_block(&mut batch, block_data, receipts);
|
||||
|
||||
if let Some((header, epoch, expected)) = entering_new_epoch {
|
||||
use std::cell::RefCell;
|
||||
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 {
|
||||
traces: traces.into(),
|
||||
block_hash: hash.clone(),
|
||||
@ -893,6 +932,20 @@ impl Client {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transaction for calling contracts from services like engine.
|
||||
// from the null sender, with 50M gas.
|
||||
fn contract_call_tx(&self, block_id: BlockId, address: Address, data: Bytes) -> SignedTransaction {
|
||||
let from = Address::default();
|
||||
Transaction {
|
||||
nonce: self.nonce(&from, block_id).unwrap_or_else(|| self.engine.account_start_nonce()),
|
||||
action: Action::Call(address),
|
||||
gas: U256::from(50_000_000),
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data: data,
|
||||
}.fake_sign(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl snapshot::DatabaseRestore for Client {
|
||||
@ -1483,15 +1536,7 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn call_contract(&self, block_id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||
let from = Address::default();
|
||||
let transaction = Transaction {
|
||||
nonce: self.latest_nonce(&from),
|
||||
action: Action::Call(address),
|
||||
gas: U256::from(50_000_000),
|
||||
gas_price: U256::default(),
|
||||
value: U256::default(),
|
||||
data: data,
|
||||
}.fake_sign(from);
|
||||
let transaction = self.contract_call_tx(block_id, address, data);
|
||||
|
||||
self.call(&transaction, block_id, Default::default())
|
||||
.map_err(|e| format!("{:?}", e))
|
||||
@ -1643,7 +1688,7 @@ impl MayPanic for Client {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::client::ProvingBlockChainClient for Client {
|
||||
impl ProvingBlockChainClient for Client {
|
||||
fn prove_storage(&self, key1: H256, key2: H256, id: BlockId) -> Option<(Vec<Bytes>, H256)> {
|
||||
self.state_at(id)
|
||||
.and_then(move |state| state.prove_storage(key1, key2).ok())
|
||||
@ -1654,7 +1699,7 @@ impl ::client::ProvingBlockChainClient for Client {
|
||||
.and_then(move |state| state.prove_account(key1).ok())
|
||||
}
|
||||
|
||||
fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<Vec<DBValue>> {
|
||||
fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec<DBValue>)> {
|
||||
let (state, mut env_info) = match (self.state_at(id), self.env_info(id)) {
|
||||
(Some(s), Some(e)) => (s, e),
|
||||
_ => return None,
|
||||
@ -1669,8 +1714,9 @@ impl ::client::ProvingBlockChainClient for Client {
|
||||
let res = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&transaction, options);
|
||||
|
||||
match res {
|
||||
Err(ExecutionError::Internal(_)) => return None,
|
||||
_ => return Some(state.drop().1.extract_proof()),
|
||||
Err(ExecutionError::Internal(_)) => None,
|
||||
Err(_) => Some((Vec::new(), state.drop().1.extract_proof())),
|
||||
Ok(res) => Some((res.output, state.drop().1.extract_proof())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -767,7 +767,7 @@ impl ProvingBlockChainClient for TestBlockChainClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn prove_transaction(&self, _: SignedTransaction, _: BlockId) -> Option<Vec<DBValue>> {
|
||||
fn prove_transaction(&self, _: SignedTransaction, _: BlockId) -> Option<(Bytes, Vec<DBValue>)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -324,5 +324,7 @@ pub trait ProvingBlockChainClient: BlockChainClient {
|
||||
fn prove_account(&self, key1: H256, id: BlockId) -> Option<(Vec<Bytes>, BasicAccount)>;
|
||||
|
||||
/// Prove execution of a transaction at the given block.
|
||||
fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<Vec<DBValue>>;
|
||||
/// Returns the output of the call and a vector of database items necessary
|
||||
/// to reproduce it.
|
||||
fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec<DBValue>)>;
|
||||
}
|
||||
|
@ -133,13 +133,13 @@ pub struct AuthorityRound {
|
||||
|
||||
// header-chain validator.
|
||||
struct EpochVerifier {
|
||||
epoch_number: U256,
|
||||
epoch_number: u64,
|
||||
step: Arc<Step>,
|
||||
subchain_validators: SimpleList,
|
||||
}
|
||||
|
||||
impl super::EpochVerifier for EpochVerifier {
|
||||
fn epoch_number(&self) -> U256 { self.epoch_number.clone() }
|
||||
fn epoch_number(&self) -> u64 { self.epoch_number.clone() }
|
||||
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
||||
// always check the seal since it's fast.
|
||||
// nothing heavier to do.
|
||||
|
@ -52,12 +52,12 @@ impl From<ethjson::spec::BasicAuthorityParams> for BasicAuthorityParams {
|
||||
}
|
||||
|
||||
struct EpochVerifier {
|
||||
epoch_number: U256,
|
||||
epoch_number: u64,
|
||||
list: SimpleList,
|
||||
}
|
||||
|
||||
impl super::EpochVerifier for EpochVerifier {
|
||||
fn epoch_number(&self) -> U256 { self.epoch_number.clone() }
|
||||
fn epoch_number(&self) -> u64 { self.epoch_number.clone() }
|
||||
fn verify_light(&self, header: &Header) -> Result<(), Error> {
|
||||
verify_external(header, &self.list)
|
||||
}
|
||||
|
@ -18,14 +18,13 @@
|
||||
|
||||
use error::Error;
|
||||
use header::Header;
|
||||
use util::U256;
|
||||
|
||||
/// Verifier for all blocks within an epoch without accessing
|
||||
///
|
||||
/// See docs on `Engine` relating to proving functions for more details.
|
||||
pub trait EpochVerifier: Sync {
|
||||
/// Get the epoch number.
|
||||
fn epoch_number(&self) -> U256;
|
||||
fn epoch_number(&self) -> u64;
|
||||
|
||||
/// Lightly verify the next block header.
|
||||
/// This may not be a header belonging to a different epoch.
|
||||
@ -41,6 +40,6 @@ pub trait EpochVerifier: Sync {
|
||||
pub struct NoOp;
|
||||
|
||||
impl EpochVerifier for NoOp {
|
||||
fn epoch_number(&self) -> U256 { 0.into() }
|
||||
fn epoch_number(&self) -> u64 { 0 }
|
||||
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ pub enum Seal {
|
||||
}
|
||||
|
||||
/// Type alias for a function we can make calls through synchronously.
|
||||
pub type Call = Fn(Address, Bytes) -> Result<Bytes, String>;
|
||||
pub type Call<'a> = Fn(Address, Bytes) -> Result<Bytes, String> + 'a;
|
||||
|
||||
/// Results of a query of whether an epoch change occurred at the given block.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@ -105,8 +105,8 @@ pub enum EpochChange {
|
||||
Unsure(Unsure),
|
||||
/// No epoch change.
|
||||
No,
|
||||
/// Validation proof required, and the expected output
|
||||
Yes(Bytes),
|
||||
/// Validation proof required, and the new epoch number and expected proof.
|
||||
Yes(u64, Bytes),
|
||||
}
|
||||
|
||||
/// More data required to determine if an epoch change occurred at a given block.
|
||||
|
@ -76,7 +76,7 @@ impl ValidatorSet for ValidatorContract {
|
||||
self.validators.epoch_proof(header, caller)
|
||||
}
|
||||
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, super::SimpleList), ::error::Error> {
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(u64, super::SimpleList), ::error::Error> {
|
||||
self.validators.epoch_set(header, proof)
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ mod multi;
|
||||
|
||||
use std::sync::Weak;
|
||||
use ids::BlockId;
|
||||
use util::{Address, H256, U256};
|
||||
use util::{Address, H256};
|
||||
use ethjson::spec::ValidatorSet as ValidatorSpec;
|
||||
use client::Client;
|
||||
use header::Header;
|
||||
@ -97,7 +97,7 @@ pub trait ValidatorSet: Send + Sync {
|
||||
/// the proof is invalid.
|
||||
///
|
||||
/// Returns the epoch number and proof.
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, SimpleList), ::error::Error>;
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(u64, SimpleList), ::error::Error>;
|
||||
|
||||
/// Checks if a given address is a validator, with the given function
|
||||
/// for executing synchronous calls to contracts.
|
||||
|
@ -19,7 +19,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Weak;
|
||||
use engines::{Call, EpochChange};
|
||||
use util::{H256, Address, RwLock, U256};
|
||||
use util::{H256, Address, RwLock};
|
||||
use ids::BlockId;
|
||||
use header::{BlockNumber, Header};
|
||||
use client::{Client, BlockChainClient};
|
||||
@ -75,19 +75,24 @@ impl ValidatorSet for Multi {
|
||||
fn is_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>)
|
||||
-> EpochChange
|
||||
{
|
||||
self.correct_set_by_number(header.number()).1.is_epoch_end(header, block, receipts)
|
||||
let (set_block, set) = self.correct_set_by_number(header.number());
|
||||
|
||||
match set.is_epoch_end(header, block, receipts) {
|
||||
EpochChange::Yes(num, proof) => EpochChange::Yes(set_block + num, proof),
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
|
||||
fn epoch_proof(&self, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
|
||||
self.correct_set_by_number(header.number()).1.epoch_proof(header, caller)
|
||||
}
|
||||
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(U256, super::SimpleList), ::error::Error> {
|
||||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(u64, super::SimpleList), ::error::Error> {
|
||||
// "multi" epoch is the inner set's epoch plus the transition block to that set.
|
||||
// ensures epoch increases monotonically.
|
||||
let (set_block, set) = self.correct_set_by_number(header.number());
|
||||
let (inner_epoch, list) = set.epoch_set(header, proof)?;
|
||||
Ok((U256::from(set_block) + inner_epoch, list))
|
||||
Ok((set_block + inner_epoch, list))
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool {
|
||||
|
@ -165,8 +165,6 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// TODO: are multiple transitions per block possible?
|
||||
match decoded_events.next() {
|
||||
None => ::engines::EpochChange::No,
|
||||
Some(matched_event) => {
|
||||
@ -184,8 +182,11 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
);
|
||||
|
||||
match (nonce, validators) {
|
||||
(Some(nonce), Some(validators)) =>
|
||||
::engines::EpochChange::Yes(encode_proof(nonce, &validators)),
|
||||
(Some(nonce), Some(validators)) => {
|
||||
let proof = encode_proof(nonce, &validators);
|
||||
let new_epoch = nonce.low_u64();
|
||||
::engines::EpochChange::Yes(new_epoch, proof)
|
||||
}
|
||||
_ => {
|
||||
debug!(target: "engine", "Successfully decoded log turned out to be bad.");
|
||||
::engines::EpochChange::No
|
||||
@ -206,11 +207,11 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
}
|
||||
}
|
||||
|
||||
fn epoch_set(&self, _header: &Header, proof: &[u8]) -> Result<(U256, SimpleList), ::error::Error> {
|
||||
fn epoch_set(&self, _header: &Header, proof: &[u8]) -> Result<(u64, SimpleList), ::error::Error> {
|
||||
use rlp::UntrustedRlp;
|
||||
|
||||
let rlp = UntrustedRlp::new(proof);
|
||||
let nonce: U256 = rlp.val_at(0)?;
|
||||
let nonce: u64 = rlp.val_at(0)?;
|
||||
let validators: Vec<Address> = rlp.list_at(1)?;
|
||||
|
||||
Ok((nonce, SimpleList::new(validators)))
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
/// Preconfigured validator list.
|
||||
|
||||
use util::{H256, Address, HeapSizeOf, U256};
|
||||
use util::{H256, Address, HeapSizeOf};
|
||||
|
||||
use engines::Call;
|
||||
use header::Header;
|
||||
@ -63,8 +63,8 @@ impl ValidatorSet for SimpleList {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn epoch_set(&self, _header: &Header, _: &[u8]) -> Result<(U256, SimpleList), ::error::Error> {
|
||||
Ok((0.into(), self.clone()))
|
||||
fn epoch_set(&self, _header: &Header, _: &[u8]) -> Result<(u64, SimpleList), ::error::Error> {
|
||||
Ok((0, self.clone()))
|
||||
}
|
||||
|
||||
fn contains_with_caller(&self, _bh: &H256, address: &Address, _: &Call) -> bool {
|
||||
|
@ -158,7 +158,7 @@ impl Ethash {
|
||||
// in the future, we might move the Ethash epoch
|
||||
// caching onto this mechanism as well.
|
||||
impl ::engines::EpochVerifier for Arc<Ethash> {
|
||||
fn epoch_number(&self) -> U256 { 0.into() }
|
||||
fn epoch_number(&self) -> u64 { 0 }
|
||||
fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) }
|
||||
fn verify_heavy(&self, header: &Header) -> Result<(), Error> {
|
||||
self.verify_block_unordered(header, None)
|
||||
|
@ -238,7 +238,7 @@ impl Migration for OverlayRecentV7 {
|
||||
}
|
||||
|
||||
let mut count = 0;
|
||||
for (key, value) in source.iter(None) {
|
||||
for (key, value) in source.iter(None).into_iter().flat_map(|inner| inner) {
|
||||
count += 1;
|
||||
if count == 100_000 {
|
||||
count = 0;
|
||||
|
@ -102,7 +102,7 @@ impl Migration for ToV10 {
|
||||
|
||||
fn migrate(&mut self, source: Arc<Database>, config: &Config, dest: &mut Database, col: Option<u32>) -> Result<(), Error> {
|
||||
let mut batch = Batch::new(config, col);
|
||||
for (key, value) in source.iter(col) {
|
||||
for (key, value) in source.iter(col).into_iter().flat_map(|inner| inner) {
|
||||
self.progress.tick();
|
||||
batch.insert(key.to_vec(), value.to_vec(), dest)?;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ impl Migration for ToV9 {
|
||||
fn migrate(&mut self, source: Arc<Database>, config: &Config, dest: &mut Database, col: Option<u32>) -> Result<(), Error> {
|
||||
let mut batch = Batch::new(config, self.column);
|
||||
|
||||
for (key, value) in source.iter(col) {
|
||||
for (key, value) in source.iter(col).into_iter().flat_map(|inner| inner) {
|
||||
self.progress.tick();
|
||||
match self.extract {
|
||||
Extract::Header => {
|
||||
|
@ -367,7 +367,7 @@ fn transaction_proof() {
|
||||
data: Vec::new(),
|
||||
}.fake_sign(address);
|
||||
|
||||
let proof = client.prove_transaction(transaction.clone(), BlockId::Latest).unwrap();
|
||||
let proof = client.prove_transaction(transaction.clone(), BlockId::Latest).unwrap().1;
|
||||
let backend = state::backend::ProofCheck::new(&proof);
|
||||
|
||||
let mut factories = ::factory::Factories::default();
|
||||
|
@ -16,7 +16,7 @@ time = "0.1.34"
|
||||
rocksdb = { git = "https://github.com/paritytech/rust-rocksdb" }
|
||||
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
|
||||
rust-crypto = "0.2.34"
|
||||
elastic-array = { git = "https://github.com/paritytech/elastic-array" }
|
||||
elastic-array = "0.7.0"
|
||||
rlp = { path = "rlp" }
|
||||
heapsize = { version = "0.3", features = ["unstable"] }
|
||||
itertools = "0.5"
|
||||
|
@ -6,7 +6,7 @@ version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
elastic-array = { git = "https://github.com/paritytech/elastic-array" }
|
||||
elastic-array = "0.7.0"
|
||||
ethcore-bigint = { path = "../bigint" }
|
||||
lazy_static = "0.2"
|
||||
rustc-serialize = "0.3"
|
||||
|
@ -125,8 +125,8 @@ pub fn new(backing: Arc<::kvdb::KeyValueDB>, algorithm: Algorithm, col: Option<u
|
||||
}
|
||||
|
||||
// all keys must be at least 12 bytes
|
||||
const DB_PREFIX_LEN : usize = 12;
|
||||
const LATEST_ERA_KEY : [u8; DB_PREFIX_LEN] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||
const DB_PREFIX_LEN : usize = ::kvdb::PREFIX_LEN;
|
||||
const LATEST_ERA_KEY : [u8; ::kvdb::PREFIX_LEN] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -36,6 +36,9 @@ use std::fs::File;
|
||||
const DB_BACKGROUND_FLUSHES: i32 = 2;
|
||||
const DB_BACKGROUND_COMPACTIONS: i32 = 2;
|
||||
|
||||
/// Required length of prefixes.
|
||||
pub const PREFIX_LEN: usize = 12;
|
||||
|
||||
/// Write transaction. Batches a sequence of put/delete operations for efficiency.
|
||||
#[derive(Default, Clone, PartialEq)]
|
||||
pub struct DBTransaction {
|
||||
|
Loading…
Reference in New Issue
Block a user