parity-zcash/sync/src/blocks_writer.rs

77 lines
2.3 KiB
Rust
Raw Normal View History

2016-11-03 04:37:58 -07:00
use std::sync::Arc;
use chain;
use db;
use network::Magic;
2016-11-03 04:37:58 -07:00
use verification::{Verify, ChainVerifier};
use super::Error;
2016-11-03 04:37:58 -07:00
pub struct BlocksWriter {
storage: Arc<db::Store>,
verifier: ChainVerifier,
}
impl BlocksWriter {
pub fn new(storage: db::SharedStore, network: Magic) -> BlocksWriter {
2016-11-03 04:37:58 -07:00
BlocksWriter {
storage: storage.clone(),
verifier: ChainVerifier::new(storage, network),
2016-11-03 04:37:58 -07:00
}
}
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)),
2016-11-17 07:24:04 -08:00
Ok(_chain) => { try!(self.storage.insert_block(&block).map_err(Error::Database)); Ok(()) }
2016-11-03 04:37:58 -07:00
}
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use db::{self, Store};
use network::Magic;
use {test_data, verification};
2016-11-03 04:37:58 -07:00
use super::super::Error;
use super::BlocksWriter;
#[test]
fn blocks_writer_appends_blocks() {
let db = Arc::new(db::TestStorage::with_genesis_block());
let mut blocks_target = BlocksWriter::new(db.clone(), Magic::Testnet);
2016-11-03 04:37:58 -07:00
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(), Magic::Testnet);
2016-11-03 04:37:58 -07:00
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(), Magic::Testnet);
2016-11-03 04:37:58 -07:00
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);
}
}