hash block and transactions while reading them
This commit is contained in:
parent
591a642121
commit
ce7af59ad3
|
@ -173,6 +173,7 @@ name = "db"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chain 0.1.0",
|
"chain 0.1.0",
|
||||||
"elastic-array 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"elastic-array 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -2,11 +2,11 @@ extern crate crypto as rcrypto;
|
||||||
extern crate primitives;
|
extern crate primitives;
|
||||||
extern crate siphasher;
|
extern crate siphasher;
|
||||||
|
|
||||||
|
pub use rcrypto::digest::Digest;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use rcrypto::sha1::Sha1;
|
use rcrypto::sha1::Sha1;
|
||||||
use rcrypto::sha2::Sha256;
|
use rcrypto::sha2::Sha256;
|
||||||
use rcrypto::ripemd160::Ripemd160;
|
use rcrypto::ripemd160::Ripemd160;
|
||||||
use rcrypto::digest::Digest;
|
|
||||||
use siphasher::sip::SipHasher24;
|
use siphasher::sip::SipHasher24;
|
||||||
use primitives::hash::{H32, H160, H256};
|
use primitives::hash::{H32, H160, H256};
|
||||||
|
|
||||||
|
@ -72,6 +72,12 @@ impl DHash256 {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
DHash256::default()
|
DHash256::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn finish(mut self) -> H256 {
|
||||||
|
let mut result = H256::default();
|
||||||
|
self.result(&mut *result);
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Digest for DHash256 {
|
impl Digest for DHash256 {
|
||||||
|
|
|
@ -8,6 +8,7 @@ elastic-array = "0.5"
|
||||||
rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" }
|
rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" }
|
||||||
ethcore-devtools = { path = "../devtools" }
|
ethcore-devtools = { path = "../devtools" }
|
||||||
primitives = { path = "../primitives" }
|
primitives = { path = "../primitives" }
|
||||||
|
bitcrypto = { path = "../crypto" }
|
||||||
byteorder = "0.5"
|
byteorder = "0.5"
|
||||||
chain = { path = "../chain" }
|
chain = { path = "../chain" }
|
||||||
serialization = { path = "../serialization" }
|
serialization = { path = "../serialization" }
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
use std::io;
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use chain::{Block, OutPoint, TransactionOutput, merkle_root, Transaction};
|
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_header::IndexedBlockHeader;
|
||||||
use indexed_transaction::IndexedTransaction;
|
use indexed_transaction::IndexedTransaction;
|
||||||
use {TransactionOutputObserver, PreviousTransactionOutputProvider};
|
use {TransactionOutputObserver, PreviousTransactionOutputProvider};
|
||||||
|
@ -87,3 +91,14 @@ impl IndexedBlock {
|
||||||
self.transactions.iter().all(|tx| tx.raw.is_final(height, self.header.raw.time))
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::io;
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use chain::BlockHeader;
|
use chain::BlockHeader;
|
||||||
|
use serialization::{Deserializable, Reader, Error as ReaderError};
|
||||||
|
use read_and_hash::ReadAndHash;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct IndexedBlockHeader {
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use std::cmp;
|
use std::{cmp, io};
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use chain::{Transaction, OutPoint, TransactionOutput};
|
use chain::{Transaction, OutPoint, TransactionOutput};
|
||||||
|
use serialization::{Deserializable, Reader, Error as ReaderError};
|
||||||
|
use read_and_hash::ReadAndHash;
|
||||||
use PreviousTransactionOutputProvider;
|
use PreviousTransactionOutputProvider;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[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] {
|
impl<'a> PreviousTransactionOutputProvider for &'a [IndexedTransaction] {
|
||||||
fn previous_transaction_output(&self, prevout: &OutPoint) -> Option<TransactionOutput> {
|
fn previous_transaction_output(&self, prevout: &OutPoint) -> Option<TransactionOutput> {
|
||||||
self.iter()
|
self.iter()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
//! Bitcoin database
|
//! Bitcoin database
|
||||||
|
|
||||||
|
extern crate bitcrypto as crypto;
|
||||||
extern crate elastic_array;
|
extern crate elastic_array;
|
||||||
extern crate rocksdb;
|
extern crate rocksdb;
|
||||||
extern crate parking_lot;
|
extern crate parking_lot;
|
||||||
|
@ -31,6 +32,7 @@ mod update_context;
|
||||||
mod indexed_block;
|
mod indexed_block;
|
||||||
mod indexed_header;
|
mod indexed_header;
|
||||||
mod indexed_transaction;
|
mod indexed_transaction;
|
||||||
|
mod read_and_hash;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum BlockRef {
|
pub enum BlockRef {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,6 +84,11 @@ impl<R> Reader<R> where R: io::Read {
|
||||||
T::deserialize(self)
|
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> {
|
pub fn read_slice(&mut self, bytes: &mut [u8]) -> Result<(), Error> {
|
||||||
io::Read::read_exact(self, bytes).map_err(|_| Error::UnexpectedEnd)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue