store epoch transition proofs in DB

This commit is contained in:
Robert Habermeier
2017-04-19 14:58:19 +02:00
parent 6da6c755a5
commit a278dd5a0a
26 changed files with 234 additions and 69 deletions

View File

@@ -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.
///

View File

@@ -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::*;

View File

@@ -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;