Implement basic BeaconChain persistence.

This commit is contained in:
Paul Hauner
2019-05-27 16:13:32 +10:00
parent 76602a65fc
commit 9ed8a4d380
13 changed files with 137 additions and 74 deletions

View File

@@ -1,5 +1,6 @@
use crate::checkpoint::CheckPoint;
use crate::errors::{BeaconChainError as Error, BlockProductionError};
use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
use fork_choice::{ForkChoice, ForkChoiceError};
use log::{debug, trace};
use operation_pool::DepositInsertStatus;
@@ -140,6 +141,51 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
})
}
/// Attempt to load an existing instance from the given `store`.
pub fn from_store(store: Arc<T::Store>) -> Result<Option<BeaconChain<T>>, Error> {
let key = Hash256::from_slice(&BEACON_CHAIN_DB_KEY.as_bytes());
let p: PersistedBeaconChain<T> = match store.get(&key) {
Err(e) => return Err(e.into()),
Ok(None) => return Ok(None),
Ok(Some(p)) => p,
};
let spec = T::EthSpec::spec();
let slot_clock = T::SlotClock::new(
spec.genesis_slot,
p.state.genesis_time,
spec.seconds_per_slot,
);
let fork_choice = T::ForkChoice::new(store.clone());
Ok(Some(BeaconChain {
store,
slot_clock,
op_pool: OperationPool::default(),
canonical_head: RwLock::new(p.canonical_head),
finalized_head: RwLock::new(p.finalized_head),
state: RwLock::new(p.state),
spec,
fork_choice: RwLock::new(fork_choice),
}))
}
/// Attempt to save this instance to `self.store`.
pub fn persist(&self) -> Result<(), Error> {
let p: PersistedBeaconChain<T> = PersistedBeaconChain {
canonical_head: self.canonical_head.read().clone(),
finalized_head: self.finalized_head.read().clone(),
state: self.state.read().clone(),
};
let key = Hash256::from_slice(&BEACON_CHAIN_DB_KEY.as_bytes());
self.store.put(&key, &p)?;
Ok(())
}
/// Returns the beacon block body for each beacon block root in `roots`.
///
/// Fails if any root in `roots` does not have a corresponding block.

View File

@@ -1,9 +1,10 @@
use serde_derive::Serialize;
use ssz_derive::{Decode, Encode};
use types::{BeaconBlock, BeaconState, EthSpec, Hash256};
/// Represents some block and it's associated state. Generally, this will be used for tracking the
/// head, justified head and finalized head.
#[derive(Clone, Serialize, PartialEq, Debug)]
#[derive(Clone, Serialize, PartialEq, Debug, Encode, Decode)]
pub struct CheckPoint<E: EthSpec> {
pub beacon_block: BeaconBlock,
pub beacon_block_root: Hash256,

View File

@@ -1,6 +1,7 @@
mod beacon_chain;
mod checkpoint;
mod errors;
mod persisted_beacon_chain;
pub use self::beacon_chain::{
BeaconChain, BeaconChainTypes, BlockProcessingOutcome, InvalidBlock, ValidBlock,

View File

@@ -0,0 +1,30 @@
use crate::{BeaconChainTypes, CheckPoint};
use ssz::{Decode, Encode};
use ssz_derive::{Decode, Encode};
use store::{DBColumn, Error as StoreError, StoreItem};
use types::BeaconState;
/// 32-byte key for accessing the `PersistedBeaconChain`.
pub const BEACON_CHAIN_DB_KEY: &str = "PERSISTEDBEACONCHAINPERSISTEDBEA";
#[derive(Encode, Decode)]
pub struct PersistedBeaconChain<T: BeaconChainTypes> {
pub canonical_head: CheckPoint<T::EthSpec>,
pub finalized_head: CheckPoint<T::EthSpec>,
// TODO: operations pool.
pub state: BeaconState<T::EthSpec>,
}
impl<T: BeaconChainTypes> StoreItem for PersistedBeaconChain<T> {
fn db_column() -> DBColumn {
DBColumn::BeaconChain
}
fn as_store_bytes(&self) -> Vec<u8> {
self.as_ssz_bytes()
}
fn from_store_bytes(bytes: &mut [u8]) -> Result<Self, StoreError> {
Self::from_ssz_bytes(bytes).map_err(Into::into)
}
}