initial BlocksWriter version
This commit is contained in:
parent
b482ec54e7
commit
9b5a134d01
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue