serve epoch signals over network and check them

This commit is contained in:
Robert Habermeier
2017-08-23 15:37:35 +02:00
parent 7f3e718851
commit 2ff3dff6ea
16 changed files with 298 additions and 30 deletions

View File

@@ -1918,6 +1918,12 @@ impl ProvingBlockChainClient for Client {
false,
)
}
fn epoch_signal(&self, hash: H256) -> Option<Vec<u8>> {
// pending transitions are never deleted, and do not contain
// finality proofs by definition.
self.chain.read().get_pending_transition(hash).map(|pending| pending.proof)
}
}
impl Drop for Client {

View File

@@ -778,6 +778,10 @@ impl ProvingBlockChainClient for TestBlockChainClient {
fn prove_transaction(&self, _: SignedTransaction, _: BlockId) -> Option<(Bytes, Vec<DBValue>)> {
None
}
fn epoch_signal(&self, _: H256) -> Option<Vec<u8>> {
None
}
}
impl super::traits::EngineClient for TestBlockChainClient {

View File

@@ -353,4 +353,7 @@ pub trait ProvingBlockChainClient: BlockChainClient {
/// 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>)>;
/// Get an epoch change signal by block hash.
fn epoch_signal(&self, hash: H256) -> Option<Vec<u8>>;
}

View File

@@ -121,7 +121,7 @@ pub type Headers<'a> = Fn(H256) -> Option<Header> + 'a;
pub type PendingTransitionStore<'a> = Fn(H256) -> Option<PendingTransition> + 'a;
/// Proof dependent on state.
pub trait StateDependentProof {
pub trait StateDependentProof: Send + Sync {
/// Generate a proof, given the state.
fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, String>;
/// Check a proof generated elsewhere (potentially by a peer).
@@ -135,7 +135,7 @@ pub enum Proof {
/// Known proof (extracted from signal)
Known(Vec<u8>),
/// State dependent proof.
WithState(Box<StateDependentProof>),
WithState(Arc<StateDependentProof>),
}
/// Generated epoch verifier.

View File

@@ -47,19 +47,19 @@ lazy_static! {
// state-dependent proofs for the safe contract:
// only "first" proofs are such.
struct StateProof {
header: Header,
header: Mutex<Header>,
provider: Provider,
}
impl ::engines::StateDependentProof for StateProof {
fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, String> {
prove_initial(&self.provider, &self.header, caller)
prove_initial(&self.provider, &*self.header.lock(), caller)
}
fn check_proof(&self, engine: &Engine, proof: &[u8]) -> Result<(), String> {
let (header, state_items) = decode_first_proof(&UntrustedRlp::new(proof))
.map_err(|e| format!("proof incorrectly encoded: {}", e))?;
if header != self.header {
if &header != &*self.header.lock(){
return Err("wrong header in proof".into());
}
@@ -330,11 +330,11 @@ impl ValidatorSet for ValidatorSafeContract {
// transition to the first block of a contract requires finality but has no log event.
if first {
debug!(target: "engine", "signalling transition to fresh contract.");
let state_proof = Box::new(StateProof {
header: header.clone(),
let state_proof = Arc::new(StateProof {
header: Mutex::new(header.clone()),
provider: self.provider.clone(),
});
return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Box<_>));
return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>));
}
// otherwise, we're checking for logs.