From ee65595a761eb88dd782a1acd65b1b02122cf2c1 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 14 Dec 2015 16:14:50 +0100 Subject: [PATCH] HeaderView, BlockView, blockchain api for blocks, block_headers, transaction_hashes, uncle_hashes --- src/blockchain.rs | 71 +++++++++++++++++++++++++++++++------------- src/blockheader.rs | 30 +++++++++++++++++-- src/genesis.rs | 2 +- src/verifiedblock.rs | 4 +-- 4 files changed, 82 insertions(+), 25 deletions(-) diff --git a/src/blockchain.rs b/src/blockchain.rs index 64c6b66a3..c5d74a6de 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::sync::{Arc, RwLock}; +use std::sync::RwLock; use std::path::Path; use std::hash::Hash; use rocksdb::{DB, WriteBatch, Writable}; @@ -70,12 +70,12 @@ impl BlockChain { pub fn new(genesis: Genesis, path: &Path) -> BlockChain { let (genesis_block, genesis_state) = genesis.drain(); - let genesis_header = Rlp::new(&genesis_block).at(0).raw().to_vec(); - let genesis_hash = BlockView::new(&genesis_header).sha3(); + let genesis_header = BlockView::new(&genesis_block).header_view().rlp().raw().to_vec(); + let genesis_hash = HeaderView::new(&genesis_header).sha3(); let genesis_details = BlockDetails { number: U256::from(0u64), - total_difficulty: BlockView::new(&genesis_header).difficulty(), + total_difficulty: HeaderView::new(&genesis_header).difficulty(), parent: H256::new(), children: vec![] }; @@ -94,7 +94,7 @@ impl BlockChain { batch.put(&U256::from(0u8).to_extras_slice(ExtrasIndex::BlockHash), &encode(&genesis_hash)); extras_db.write(batch); - blocks_db.put(&genesis_hash, &genesis_header); + blocks_db.put(&genesis_hash, &genesis_block); } BlockChain { @@ -114,13 +114,8 @@ impl BlockChain { } } - /// Returns reference to genesis hash - pub fn genesis_hash(&self) -> &H256 { - &self.genesis_hash - } - pub fn genesis_block(&self, db: &OverlayDB) -> Block { - let root = BlockView::new(&self.genesis_block).state_root(); + let root = HeaderView::new(&self.genesis_block).state_root(); if db.exists(&root) { return Block::new_existing(db.clone(), root) @@ -141,7 +136,7 @@ impl BlockChain { } pub fn import_block(&self, block: &[u8], db: &OverlayDB) -> ImportRoute { - let view = BlockView::new(block); + let view = HeaderView::new(block); // check if we already know this block if self.is_known(&view.sha3()) { @@ -155,11 +150,6 @@ impl BlockChain { unimplemented!(); } - /// Get the hash of given block's number - pub fn number_hash(&self, hash: &U256) -> Option { - self.query_extras(hash, &self.block_hashes) - } - /// Returns true if the given block is known /// (though not necessarily a part of the canon chain). pub fn is_known(&self, hash: &H256) -> bool { @@ -172,7 +162,48 @@ impl BlockChain { } } - pub fn block(&self, hash: &H256) -> Option { + /// Returns reference to genesis hash + pub fn genesis_hash(&self) -> &H256 { + &self.genesis_hash + } + + /// Get the hash of given block's number + pub fn number_hash(&self, hash: &U256) -> Option { + self.query_extras(hash, &self.block_hashes) + } + + /// Get the partial-header of a block + pub fn block_header(&self, hash: &H256) -> Option
{ + match self.block(hash) { + Some(bytes) => Some(BlockView::new(&bytes).header()), + None => None + } + } + + /// Get a list of transaction hashes for a given block. + /// Returns None if block does not exist. + pub fn transaction_hashes(&self, hash: &H256) -> Option> { + match self.block(hash) { + Some(bytes) => Some(BlockView::new(&bytes).transaction_hashes()), + None => None + } + } + + /// Get a list of uncle hashes for a given block. + /// Returns None if block does not exist. + pub fn uncle_hashes(&self, hash: &H256) -> Option> { + match self.block(hash) { + Some(bytes) => Some(BlockView::new(&bytes).uncle_hashes()), + None => None + } + } + + /// Get the transactions' log blooms of a block + pub fn log_blooms(&self, hash: &H256) -> Option { + self.query_extras(hash, &self.block_logs) + } + + fn block(&self, hash: &H256) -> Option { { let read = self.blocks.read().unwrap(); match read.get(hash) { @@ -195,7 +226,7 @@ impl BlockChain { } } - pub fn query_extras(&self, hash: &K, cache: &Extras) -> Option where + fn query_extras(&self, hash: &K, cache: &Extras) -> Option where T: Clone + Decodable, K: ExtrasSliceConvertable + Eq + Hash + Clone { { @@ -220,7 +251,7 @@ impl BlockChain { } } - pub fn query_extras_exist(&self, hash: &K, cache: &Extras) -> bool where + fn query_extras_exist(&self, hash: &K, cache: &Extras) -> bool where K: ExtrasSliceConvertable + Eq + Hash + Clone { { let read = cache.read().unwrap(); diff --git a/src/blockheader.rs b/src/blockheader.rs index 7ab670f04..baa79a15b 100644 --- a/src/blockheader.rs +++ b/src/blockheader.rs @@ -4,7 +4,7 @@ use util::uint::*; use util::rlp::*; use util::sha3; -/// view onto block header rlp +/// view onto block rlp pub struct BlockView<'a> { rlp: Rlp<'a> } @@ -22,6 +22,32 @@ impl<'a> BlockView<'a> { } } + pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } + pub fn header(&self) -> Header { self.rlp.val_at(0) } + pub fn header_view(&self) -> HeaderView<'a> { HeaderView::new_from_rlp(self.rlp.at(0)) } + pub fn transaction_hashes(&self) -> Vec { self.rlp.val_at(1) } + pub fn uncle_hashes(&self) -> Vec { self.rlp.val_at(2) } +} + +/// view onto block header rlp +pub struct HeaderView<'a> { + rlp: Rlp<'a> +} + +impl<'a> HeaderView<'a> { + pub fn new(bytes: &'a [u8]) -> HeaderView<'a> { + HeaderView { + rlp: Rlp::new(bytes) + } + } + + pub fn new_from_rlp(rlp: Rlp<'a>) -> HeaderView<'a> { + HeaderView { + rlp: rlp + } + } + + pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } pub fn parent_hash(&self) -> H256 { self.rlp.val_at(0) } pub fn uncles_hash(&self) -> H256 { self.rlp.val_at(1) } pub fn author(&self) -> Address { self.rlp.val_at(2) } @@ -44,7 +70,7 @@ impl<'a> BlockView<'a> { } } -impl<'a> sha3::Hashable for BlockView<'a> { +impl<'a> sha3::Hashable for HeaderView<'a> { fn sha3(&self) -> H256 { self.rlp.raw().sha3() } diff --git a/src/genesis.rs b/src/genesis.rs index cc405fc82..16cbab3e1 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -106,7 +106,7 @@ fn test_genesis() { use blockheader::*; let g = Genesis::new_frontier(); - let view = BlockView::new_from_rlp(Rlp::new(&g.block).at(0)); + let view = BlockView::new(&g.block).header_view(); let genesis_hash = H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap(); assert_eq!(view.sha3(), genesis_hash); } diff --git a/src/verifiedblock.rs b/src/verifiedblock.rs index 49d2340a7..2ad915856 100644 --- a/src/verifiedblock.rs +++ b/src/verifiedblock.rs @@ -2,7 +2,7 @@ use blockheader::*; use transaction::*; pub struct VerifiedBlock<'a> { - blockview: BlockView<'a>, + blockview: HeaderView<'a>, transactions: Vec } @@ -10,7 +10,7 @@ impl<'a> VerifiedBlock<'a> { // todo, new should also take transactions pub fn new(bytes: &'a [u8]) -> VerifiedBlock<'a> { VerifiedBlock { - blockview: BlockView::new(bytes), + blockview: HeaderView::new(bytes), transactions: vec![] } }