store epoch transition proofs in DB
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user