hash block and transactions while reading them

This commit is contained in:
debris 2016-12-13 18:06:46 +01:00
parent 591a642121
commit ce7af59ad3
9 changed files with 120 additions and 3 deletions

1
Cargo.lock generated
View File

@ -173,6 +173,7 @@ name = "db"
version = "0.1.0"
dependencies = [
"bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bitcrypto 0.1.0",
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chain 0.1.0",
"elastic-array 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -2,11 +2,11 @@ extern crate crypto as rcrypto;
extern crate primitives;
extern crate siphasher;
pub use rcrypto::digest::Digest;
use std::hash::Hasher;
use rcrypto::sha1::Sha1;
use rcrypto::sha2::Sha256;
use rcrypto::ripemd160::Ripemd160;
use rcrypto::digest::Digest;
use siphasher::sip::SipHasher24;
use primitives::hash::{H32, H160, H256};
@ -72,6 +72,12 @@ impl DHash256 {
pub fn new() -> Self {
DHash256::default()
}
pub fn finish(mut self) -> H256 {
let mut result = H256::default();
self.result(&mut *result);
result
}
}
impl Digest for DHash256 {

View File

@ -8,6 +8,7 @@ elastic-array = "0.5"
rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" }
ethcore-devtools = { path = "../devtools" }
primitives = { path = "../primitives" }
bitcrypto = { path = "../crypto" }
byteorder = "0.5"
chain = { path = "../chain" }
serialization = { path = "../serialization" }

View File

@ -1,6 +1,10 @@
use std::io;
use primitives::hash::H256;
use chain::{Block, OutPoint, TransactionOutput, merkle_root, Transaction};
use serialization::{Serializable, serialized_list_size};
use serialization::{
Serializable, serialized_list_size,
Deserializable, Reader, Error as ReaderError
};
use indexed_header::IndexedBlockHeader;
use indexed_transaction::IndexedTransaction;
use {TransactionOutputObserver, PreviousTransactionOutputProvider};
@ -87,3 +91,14 @@ impl IndexedBlock {
self.transactions.iter().all(|tx| tx.raw.is_final(height, self.header.raw.time))
}
}
impl Deserializable for IndexedBlock {
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, ReaderError> where T: io::Read {
let block = IndexedBlock {
header: try!(reader.read()),
transactions: try!(reader.read_list()),
};
Ok(block)
}
}

View File

@ -1,5 +1,8 @@
use std::io;
use primitives::hash::H256;
use chain::BlockHeader;
use serialization::{Deserializable, Reader, Error as ReaderError};
use read_and_hash::ReadAndHash;
#[derive(Debug, Clone)]
pub struct IndexedBlockHeader {
@ -24,3 +27,16 @@ impl IndexedBlockHeader {
}
}
}
impl Deserializable for IndexedBlockHeader {
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, ReaderError> where T: io::Read {
let data = try!(reader.read_and_hash::<BlockHeader>());
// TODO: use len
let header = IndexedBlockHeader {
raw: data.data,
hash: data.hash,
};
Ok(header)
}
}

View File

@ -1,6 +1,8 @@
use std::cmp;
use std::{cmp, io};
use primitives::hash::H256;
use chain::{Transaction, OutPoint, TransactionOutput};
use serialization::{Deserializable, Reader, Error as ReaderError};
use read_and_hash::ReadAndHash;
use PreviousTransactionOutputProvider;
#[derive(Debug, Clone)]
@ -33,6 +35,19 @@ impl cmp::PartialEq for IndexedTransaction {
}
}
impl Deserializable for IndexedTransaction {
fn deserialize<T>(reader: &mut Reader<T>) -> Result<Self, ReaderError> where T: io::Read {
let data = try!(reader.read_and_hash::<Transaction>());
// TODO: use len
let tx = IndexedTransaction {
raw: data.data,
hash: data.hash,
};
Ok(tx)
}
}
impl<'a> PreviousTransactionOutputProvider for &'a [IndexedTransaction] {
fn previous_transaction_output(&self, prevout: &OutPoint) -> Option<TransactionOutput> {
self.iter()

View File

@ -1,5 +1,6 @@
//! Bitcoin database
extern crate bitcrypto as crypto;
extern crate elastic_array;
extern crate rocksdb;
extern crate parking_lot;
@ -31,6 +32,7 @@ mod update_context;
mod indexed_block;
mod indexed_header;
mod indexed_transaction;
mod read_and_hash;
#[derive(Debug, Clone)]
pub enum BlockRef {

33
db/src/read_and_hash.rs Normal file
View File

@ -0,0 +1,33 @@
use std::io;
use crypto::{DHash256, Digest};
use primitives::hash::H256;
use serialization::{Reader, Error as ReaderError, Deserializable};
pub struct HashedData<T> {
pub len: usize,
pub hash: H256,
pub data: T,
}
pub trait ReadAndHash {
fn read_and_hash<T>(&mut self) -> Result<HashedData<T>, ReaderError> where T: Deserializable;
}
impl<R> ReadAndHash for Reader<R> where R: io::Read {
fn read_and_hash<T>(&mut self) -> Result<HashedData<T>, ReaderError> where T: Deserializable {
let mut len = 0usize;
let mut hasher = DHash256::new();
let data = self.read_with_proxy(|bytes| {
len += bytes.len();
hasher.input(bytes);
})?;
let result = HashedData {
hash: hasher.finish(),
data: data,
len: len,
};
Ok(result)
}
}

View File

@ -84,6 +84,11 @@ impl<R> Reader<R> where R: io::Read {
T::deserialize(self)
}
pub fn read_with_proxy<T, F>(&mut self, proxy: F) -> Result<T, Error> where T: Deserializable, F: FnMut(&[u8]) {
let mut reader = Reader::from_read(Proxy::new(self, proxy));
T::deserialize(&mut reader)
}
pub fn read_slice(&mut self, bytes: &mut [u8]) -> Result<(), Error> {
io::Read::read_exact(self, bytes).map_err(|_| Error::UnexpectedEnd)
}
@ -148,3 +153,26 @@ impl<R, T> Iterator for ReadIterator<R, T> where R: io::Read, T: Deserializable
}
}
}
struct Proxy<F, T> {
from: F,
to: T,
}
impl<F, T> Proxy<F, T> {
fn new(from: F, to: T) -> Self {
Proxy {
from: from,
to: to,
}
}
}
impl<F, T> io::Read for Proxy<F, T> where F: io::Read, T: FnMut(&[u8]) {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
let len = try!(io::Read::read(&mut self.from, buf));
let to = &mut self.to;
to(&buf[..len]);
Ok(len)
}
}