initial BlocksWriter version

This commit is contained in:
Svyatoslav Nikolsky 2016-11-03 14:37:58 +03:00
parent b482ec54e7
commit 9b5a134d01
2 changed files with 94 additions and 0 deletions

77
sync/src/blocks_writer.rs Normal file
View File

@ -0,0 +1,77 @@
use std::sync::Arc;
use chain;
use db;
use super::Error;
use verification::{Verify, ChainVerifier};
pub struct BlocksWriter {
storage: Arc<db::Store>,
verifier: ChainVerifier,
}
impl BlocksWriter {
pub fn new(storage: Arc<db::Store>) -> BlocksWriter {
BlocksWriter {
storage: storage.clone(),
verifier: ChainVerifier::new(storage),
}
}
pub fn append_block(&mut self, block: chain::Block) -> Result<(), Error> {
// TODO: share same verification code with synchronization_client
if self.storage.best_block().map_or(false, |bb| bb.hash != block.block_header.previous_header_hash) {
return Err(Error::OutOfOrderBlock);
}
match self.verifier.verify(&block) {
Err(err) => Err(Error::Verification(err)),
Ok(_chain) => self.storage.insert_block(&block).map_err(|err| Error::Database(err)),
}
}
}
#[cfg(test)]
mod tests {
use db;
use db::Store;
use std::sync::Arc;
use super::super::Error;
use super::BlocksWriter;
use chain::RepresentH256;
use test_data;
use verification;
#[test]
fn blocks_writer_appends_blocks() {
let db = Arc::new(db::TestStorage::with_genesis_block());
let mut blocks_target = BlocksWriter::new(db.clone());
blocks_target.append_block(test_data::block_h1()).expect("Expecting no error");
assert_eq!(db.best_block().expect("Block is inserted").number, 1);
}
#[test]
fn blocks_writer_verification_error() {
let db = Arc::new(db::TestStorage::with_genesis_block());
let mut blocks_target = BlocksWriter::new(db.clone());
match blocks_target.append_block(test_data::block_h2()).unwrap_err() {
Error::OutOfOrderBlock => (),
_ => panic!("Unexpected error"),
};
assert_eq!(db.best_block().expect("Block is inserted").number, 0);
}
#[test]
fn blocks_writer_out_of_order_block() {
let db = Arc::new(db::TestStorage::with_genesis_block());
let mut blocks_target = BlocksWriter::new(db.clone());
let wrong_block = test_data::block_builder()
.header().parent(test_data::genesis().hash()).build()
.build();
match blocks_target.append_block(wrong_block).unwrap_err() {
Error::Verification(verification::Error::Empty) => (),
_ => panic!("Unexpected error"),
};
assert_eq!(db.best_block().expect("Block is inserted").number, 0);
}
}

View File

@ -11,6 +11,7 @@ extern crate time;
extern crate verification;
extern crate miner;
mod blocks_writer;
mod hash_queue;
mod inbound_connection;
mod inbound_connection_factory;
@ -24,6 +25,22 @@ mod synchronization_server;
use std::sync::Arc;
use parking_lot::{Mutex, RwLock};
/// Sync errors.
#[derive(Debug)]
pub enum Error {
/// Out of order block.
OutOfOrderBlock,
/// Database error.
Database(db::Error),
/// Block verification error.
Verification(verification::Error),
}
/// Create blocks writer.
pub fn create_sync_blocks_writer(db: Arc<db::Store>) -> blocks_writer::BlocksWriter {
blocks_writer::BlocksWriter::new(db)
}
/// Create inbound synchronization connections factory for given `db`.
pub fn create_sync_connection_factory(db: Arc<db::Store>) -> p2p::LocalSyncNodeRef {
use synchronization_chain::Chain as SyncChain;