Merge branch 'master' into thread
This commit is contained in:
@@ -79,7 +79,7 @@ pub trait BlockProvider {
|
||||
}
|
||||
|
||||
/// Get a list of uncles for a given block.
|
||||
/// Returns None if block deos not exist.
|
||||
/// Returns None if block does not exist.
|
||||
fn uncles(&self, hash: &H256) -> Option<Vec<Header>> {
|
||||
self.block(hash).map(|bytes| BlockView::new(&bytes).uncles())
|
||||
}
|
||||
@@ -231,6 +231,24 @@ impl BlockProvider for BlockChain {
|
||||
|
||||
const COLLECTION_QUEUE_SIZE: usize = 8;
|
||||
|
||||
pub struct AncestryIter<'a> {
|
||||
current: H256,
|
||||
chain: &'a BlockChain,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for AncestryIter<'a> {
|
||||
type Item = H256;
|
||||
fn next(&mut self) -> Option<H256> {
|
||||
if self.current.is_zero() {
|
||||
Option::None
|
||||
} else {
|
||||
let mut n = self.chain.block_details(&self.current).unwrap().parent;
|
||||
mem::swap(&mut self.current, &mut n);
|
||||
Some(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockChain {
|
||||
/// Create new instance of blockchain from given Genesis
|
||||
pub fn new(config: BlockChainConfig, genesis: &[u8], path: &Path) -> BlockChain {
|
||||
@@ -490,6 +508,37 @@ impl BlockChain {
|
||||
self.extras_db.write(batch).unwrap();
|
||||
}
|
||||
|
||||
/// Iterator that lists `first` and then all of `first`'s ancestors, by hash.
|
||||
pub fn ancestry_iter(&self, first: H256) -> Option<AncestryIter> {
|
||||
if self.is_known(&first) {
|
||||
Some(AncestryIter {
|
||||
current: first,
|
||||
chain: &self,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a block's `parent`, find every block header which represents a valid possible uncle.
|
||||
pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: usize) -> Option<Vec<Header>> {
|
||||
if !self.is_known(parent) { return None; }
|
||||
|
||||
let mut excluded = HashSet::new();
|
||||
for a in self.ancestry_iter(parent.clone()).unwrap().take(uncle_generations) {
|
||||
excluded.extend(self.uncle_hashes(&a).unwrap().into_iter());
|
||||
excluded.insert(a);
|
||||
}
|
||||
|
||||
let mut ret = Vec::new();
|
||||
for a in self.ancestry_iter(parent.clone()).unwrap().skip(1).take(uncle_generations) {
|
||||
ret.extend(self.block_details(&a).unwrap().children.iter()
|
||||
.filter_map(|h| if excluded.contains(h) { None } else { self.block_header(h) })
|
||||
);
|
||||
}
|
||||
Some(ret)
|
||||
}
|
||||
|
||||
/// Get inserted block info which is critical to preapre extras updates.
|
||||
fn block_info(&self, block_bytes: &[u8]) -> BlockInfo {
|
||||
let block = BlockView::new(block_bytes);
|
||||
@@ -773,11 +822,11 @@ impl BlockChain {
|
||||
|
||||
blocks.shrink_to_fit();
|
||||
block_details.shrink_to_fit();
|
||||
block_hashes.shrink_to_fit();
|
||||
transaction_addresses.shrink_to_fit();
|
||||
block_logs.shrink_to_fit();
|
||||
blocks_blooms.shrink_to_fit();
|
||||
block_receipts.shrink_to_fit();
|
||||
block_hashes.shrink_to_fit();
|
||||
transaction_addresses.shrink_to_fit();
|
||||
block_logs.shrink_to_fit();
|
||||
blocks_blooms.shrink_to_fit();
|
||||
block_receipts.shrink_to_fit();
|
||||
}
|
||||
if self.cache_size().total() < self.max_cache_size.load(AtomicOrder::Relaxed) { break; }
|
||||
}
|
||||
@@ -795,14 +844,15 @@ mod tests {
|
||||
use blockchain::{BlockProvider, BlockChain, BlockChainConfig};
|
||||
use tests::helpers::*;
|
||||
use devtools::*;
|
||||
use blockchain::helpers::generators::{ChainGenerator, ChainIterator};
|
||||
use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer};
|
||||
use views::BlockView;
|
||||
|
||||
#[test]
|
||||
fn basic_blockchain_insert() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let genesis = canon_chain.next().unwrap().rlp();
|
||||
let first = canon_chain.next().unwrap().rlp();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let genesis = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let first = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let genesis_hash = BlockView::new(&genesis).header_view().sha3();
|
||||
let first_hash = BlockView::new(&first).header_view().sha3();
|
||||
|
||||
@@ -827,18 +877,76 @@ mod tests {
|
||||
assert_eq!(bc.block_hash(2), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_ancestry_iter() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let genesis = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let genesis_hash = BlockView::new(&genesis).header_view().sha3();
|
||||
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path());
|
||||
|
||||
let mut block_hashes = vec![genesis_hash.clone()];
|
||||
for _ in 0..10 {
|
||||
let block = canon_chain.generate(&mut finalizer).unwrap();
|
||||
block_hashes.push(BlockView::new(&block).header_view().sha3());
|
||||
bc.insert_block(&block, vec![]);
|
||||
}
|
||||
|
||||
block_hashes.reverse();
|
||||
|
||||
assert_eq!(bc.ancestry_iter(block_hashes[0].clone()).unwrap().collect::<Vec<_>>(), block_hashes)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
fn test_find_uncles() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let genesis = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b1b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
|
||||
let b1a = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b2b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
|
||||
let b2a = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b3b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
|
||||
let b3a = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b4b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
|
||||
let b4a = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b5b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
|
||||
let b5a = canon_chain.generate(&mut finalizer).unwrap();
|
||||
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path());
|
||||
bc.insert_block(&b1a, vec![]);
|
||||
bc.insert_block(&b1b, vec![]);
|
||||
bc.insert_block(&b2a, vec![]);
|
||||
bc.insert_block(&b2b, vec![]);
|
||||
bc.insert_block(&b3a, vec![]);
|
||||
bc.insert_block(&b3b, vec![]);
|
||||
bc.insert_block(&b4a, vec![]);
|
||||
bc.insert_block(&b4b, vec![]);
|
||||
bc.insert_block(&b5a, vec![]);
|
||||
bc.insert_block(&b5b, vec![]);
|
||||
|
||||
assert_eq!(
|
||||
[&b4b, &b3b, &b2b].iter().map(|b| BlockView::new(b).header()).collect::<Vec<_>>(),
|
||||
bc.find_uncle_headers(&BlockView::new(&b4a).header_view().sha3(), 3).unwrap()
|
||||
);
|
||||
|
||||
// TODO: insert block that already includes one of them as an uncle to check it's not allowed.
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
fn test_small_fork() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let genesis = canon_chain.next().unwrap().rlp();
|
||||
let blocks = canon_chain.clone().take(3).map(|block| block.rlp()).collect::<Vec<_>>();
|
||||
let fork = canon_chain.skip(2).fork(1).take(1).next().unwrap().rlp();
|
||||
|
||||
let b1 = blocks[0].clone();
|
||||
let b2 = blocks[1].clone();
|
||||
let b3a = blocks[2].clone();
|
||||
let b3b = fork;
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let genesis = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b1 = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b2 = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b3b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap();
|
||||
let b3a = canon_chain.generate(&mut finalizer).unwrap();
|
||||
|
||||
let genesis_hash = BlockView::new(&genesis).header_view().sha3();
|
||||
let b1_hash= BlockView::new(&b1).header_view().sha3();
|
||||
@@ -922,22 +1030,24 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_reopen_blockchain_db() {
|
||||
let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a059262c330941f3fe2a34d16d6e3c7b30d2ceb37c6a0e9a994c494ee1a61d2410885aa4c8bf8e56e264c0c0".from_hex().unwrap();
|
||||
let b1 = "f90261f901f9a05716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a0e78628dd45a1f8dc495594d83b76c588a3ee67463260f8b7d4a42f574aeab29aa0e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd882520884562791e580a051b3ecba4e3f2b49c11d42dd0851ec514b1be3138080f72a2b6e83868275d98f8877671f479c414b47f862f86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ca09e2709d7ec9bbe6b1bbbf0b2088828d14cd5e8642a1fee22dc74bfa89761a7f9a04bd8813dee4be989accdb708b1c2e325a7e9c695a8024e30e89d6c644e424747c0".from_hex().unwrap();
|
||||
let genesis_hash = H256::from_str("5716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2").unwrap();
|
||||
let b1_hash = H256::from_str("437e51676ff10756fcfee5edd9159fa41dbcb1b2c592850450371cbecd54ee4f").unwrap();
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let genesis = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let first = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let genesis_hash = BlockView::new(&genesis).header_view().sha3();
|
||||
let first_hash = BlockView::new(&first).header_view().sha3();
|
||||
|
||||
let temp = RandomTempPath::new();
|
||||
{
|
||||
let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path());
|
||||
assert_eq!(bc.best_block_hash(), genesis_hash);
|
||||
bc.insert_block(&b1, vec![]);
|
||||
assert_eq!(bc.best_block_hash(), b1_hash);
|
||||
bc.insert_block(&first, vec![]);
|
||||
assert_eq!(bc.best_block_hash(), first_hash);
|
||||
}
|
||||
|
||||
{
|
||||
let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path());
|
||||
assert_eq!(bc.best_block_hash(), b1_hash);
|
||||
assert_eq!(bc.best_block_hash(), first_hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1001,29 +1111,24 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_bloom_filter_simple() {
|
||||
let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a059262c330941f3fe2a34d16d6e3c7b30d2ceb37c6a0e9a994c494ee1a61d2410885aa4c8bf8e56e264c0c0".from_hex().unwrap();
|
||||
|
||||
// block b1 (child of genesis)
|
||||
let b1 = "f90261f901f9a05716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a0e78628dd45a1f8dc495594d83b76c588a3ee67463260f8b7d4a42f574aeab29aa0e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313b90100000000200000000000000000000000000000000000000000020000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080004000000000000000000000020008302000001832fefd882520884562791e580a051b3ecba4e3f2b49c11d42dd0851ec514b1be3138080f72a2b6e83868275d98f8877671f479c414b47f862f86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ca09e2709d7ec9bbe6b1bbbf0b2088828d14cd5e8642a1fee22dc74bfa89761a7f9a04bd8813dee4be989accdb708b1c2e325a7e9c695a8024e30e89d6c644e424747c0".from_hex().unwrap();
|
||||
|
||||
// block b2 (child of b1)
|
||||
let b2 = "f902ccf901f9a04ef46c05763fffc5f7e59f92a7ef438ffccbb578e6e5d0f04e3df8a7fa6c02f6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000200000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap();
|
||||
|
||||
// prepare for fork (b1a, child of genesis)
|
||||
let b1a = "f902ccf901f9a05716670833ec874362d65fea27a7cd35af5897d275b31a44944113111e4e96d2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004001832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap();
|
||||
|
||||
// fork (b2a, child of b1a, with higher total difficulty)
|
||||
let b2a = "f902ccf901f9a0626b0774a7cbdad7bdce07b87d74b6fa91c1c359d725076215d76348f8399f56a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap();
|
||||
|
||||
// fork back :)
|
||||
let b3 = "f902ccf901f9a0e6cd7250e4c32b33c906aca30280911c560ac67bd0a05fbeb874f99ac7e7e47aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c70a5dc56146e5ef025e4e5726a6373c6f12fd2f6784093a19ead0a7d17fb292a040645cbce4fd399e7bb9160b4c30c40d7ee616a030d4e18ef0ed3b02bdb65911a086e608555f63628417032a011d107b36427af37d153f0da02ce3f90fdd5e8c08b90100000000000000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004003832fefd882c0e384562791e880a0e3cc39ff775cc0a32f175995b92e84b729e5c9a3563ff899e3555b908bc21d75887c3cde283f4846a6f8cdf8cb01018304cb2f8080b87e6060604052606e8060106000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063c0406226146037576035565b005b60406004506056565b6040518082815260200191505060405180910390f35b6000600560006000508190555060059050606b565b90561ba05258615c63503c0a600d6994b12ea5750d45b3c69668e2a371b4fbfb9eeff6b8a0a11be762bc90491231274a2945be35a43f23c27775b1ff24dd521702fe15f73ec0".from_hex().unwrap();
|
||||
|
||||
// TODO: From here
|
||||
let bloom_b1 = H2048::from_str("00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000").unwrap();
|
||||
|
||||
let bloom_b2 = H2048::from_str("00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
|
||||
|
||||
let bloom_ba = H2048::from_str("00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
|
||||
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let genesis = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let mut fork = canon_chain.fork(1);
|
||||
let mut fork_finalizer = finalizer.fork();
|
||||
let b1 = fork.with_bloom(bloom_b1.clone()).generate(&mut fork_finalizer).unwrap();
|
||||
let b2 = fork.with_bloom(bloom_b2.clone()).generate(&mut fork_finalizer).unwrap();
|
||||
let b3 = fork.with_bloom(bloom_ba.clone()).generate(&mut fork_finalizer).unwrap();
|
||||
let b1a = canon_chain.with_bloom(bloom_ba.clone()).generate(&mut finalizer).unwrap();
|
||||
let b2a = canon_chain.with_bloom(bloom_ba.clone()).generate(&mut finalizer).unwrap();
|
||||
|
||||
let temp = RandomTempPath::new();
|
||||
let bc = BlockChain::new(BlockChainConfig::default(), &genesis, temp.as_path());
|
||||
|
||||
|
||||
64
ethcore/src/blockchain/generator/block.rs
Normal file
64
ethcore/src/blockchain/generator/block.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use util::rlp::*;
|
||||
use util::{H256, H2048};
|
||||
use util::U256;
|
||||
use util::bytes::Bytes;
|
||||
use header::Header;
|
||||
use transaction::SignedTransaction;
|
||||
|
||||
use super::fork::Forkable;
|
||||
use super::bloom::WithBloom;
|
||||
use super::complete::CompleteBlock;
|
||||
|
||||
/// Helper structure, used for encoding blocks.
|
||||
#[derive(Default)]
|
||||
pub struct Block {
|
||||
pub header: Header,
|
||||
pub transactions: Vec<SignedTransaction>,
|
||||
pub uncles: Vec<Header>
|
||||
}
|
||||
|
||||
impl Encodable for Block {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.begin_list(3);
|
||||
s.append(&self.header);
|
||||
s.append(&self.transactions);
|
||||
s.append(&self.uncles);
|
||||
}
|
||||
}
|
||||
|
||||
impl Forkable for Block {
|
||||
fn fork(mut self, fork_number: usize) -> Self where Self: Sized {
|
||||
self.header.difficulty = self.header.difficulty - U256::from(fork_number);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WithBloom for Block {
|
||||
fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized {
|
||||
self.header.log_bloom = bloom;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl CompleteBlock for Block {
|
||||
fn complete(mut self, parent_hash: H256) -> Bytes {
|
||||
self.header.parent_hash = parent_hash;
|
||||
encode(&self).to_vec()
|
||||
}
|
||||
}
|
||||
35
ethcore/src/blockchain/generator/bloom.rs
Normal file
35
ethcore/src/blockchain/generator/bloom.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use util::hash::H2048;
|
||||
|
||||
pub trait WithBloom {
|
||||
fn with_bloom(self, bloom: H2048) -> Self where Self: Sized;
|
||||
}
|
||||
|
||||
pub struct Bloom<'a, I> where I: 'a {
|
||||
pub iter: &'a mut I,
|
||||
pub bloom: H2048,
|
||||
}
|
||||
|
||||
impl<'a, I> Iterator for Bloom<'a, I> where I: Iterator, <I as Iterator>::Item: WithBloom {
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|item| item.with_bloom(self.bloom.clone()))
|
||||
}
|
||||
}
|
||||
53
ethcore/src/blockchain/generator/complete.rs
Normal file
53
ethcore/src/blockchain/generator/complete.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use util::hash::H256;
|
||||
use util::bytes::Bytes;
|
||||
use util::sha3::Hashable;
|
||||
use views::BlockView;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct BlockFinalizer {
|
||||
parent_hash: H256
|
||||
}
|
||||
|
||||
impl BlockFinalizer {
|
||||
pub fn fork(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CompleteBlock {
|
||||
fn complete(self, parent_hash: H256) -> Bytes;
|
||||
}
|
||||
|
||||
pub struct Complete<'a, I> where I: 'a {
|
||||
pub iter: &'a mut I,
|
||||
pub finalizer: &'a mut BlockFinalizer,
|
||||
}
|
||||
|
||||
impl<'a, I> Iterator for Complete<'a, I> where I: Iterator, <I as Iterator>::Item: CompleteBlock {
|
||||
type Item = Bytes;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|item| {
|
||||
let rlp = item.complete(self.finalizer.parent_hash.clone());
|
||||
self.finalizer.parent_hash = BlockView::new(&rlp).header_view().sha3();
|
||||
rlp
|
||||
})
|
||||
}
|
||||
}
|
||||
42
ethcore/src/blockchain/generator/fork.rs
Normal file
42
ethcore/src/blockchain/generator/fork.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub trait Forkable {
|
||||
fn fork(self, fork_number: usize) -> Self where Self: Sized;
|
||||
}
|
||||
|
||||
pub struct Fork<I> {
|
||||
pub iter: I,
|
||||
pub fork_number: usize,
|
||||
}
|
||||
|
||||
impl<I> Clone for Fork<I> where I: Iterator + Clone {
|
||||
fn clone(&self) -> Self {
|
||||
Fork {
|
||||
iter: self.iter.clone(),
|
||||
fork_number: self.fork_number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Iterator for Fork<I> where I: Iterator, <I as Iterator>::Item: Forkable {
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|item| item.fork(self.fork_number))
|
||||
}
|
||||
}
|
||||
@@ -14,108 +14,52 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use util::rlp::*;
|
||||
use util::hash::{H256, H2048};
|
||||
use util::uint::{U256};
|
||||
use util::hash::H2048;
|
||||
use util::numbers::U256;
|
||||
use util::bytes::Bytes;
|
||||
use header::{BlockNumber, Header};
|
||||
use transaction::SignedTransaction;
|
||||
|
||||
pub trait Forkable {
|
||||
fn fork(self, fork_number: usize) -> Self where Self: Sized;
|
||||
}
|
||||
|
||||
pub struct Fork<I> {
|
||||
iter: I,
|
||||
fork_number: usize,
|
||||
}
|
||||
|
||||
impl<I> Iterator for Fork<I> where I: Iterator, <I as Iterator>::Item: Forkable {
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|item| item.fork(self.fork_number))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WithBloom {
|
||||
fn with_bloom(self, bloom: H2048) -> Self where Self: Sized;
|
||||
}
|
||||
|
||||
pub struct Bloom<I> {
|
||||
iter: I,
|
||||
bloom: H2048,
|
||||
}
|
||||
|
||||
impl<I> Iterator for Bloom<I> where I: Iterator, <I as Iterator>::Item: WithBloom {
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next().map(|item| item.with_bloom(self.bloom.clone()))
|
||||
}
|
||||
}
|
||||
use header::BlockNumber;
|
||||
use super::fork::Fork;
|
||||
use super::bloom::Bloom;
|
||||
use super::complete::{BlockFinalizer, CompleteBlock, Complete};
|
||||
use super::block::Block;
|
||||
|
||||
/// Chain iterator interface.
|
||||
pub trait ChainIterator: Iterator {
|
||||
pub trait ChainIterator: Iterator + Sized {
|
||||
/// Should be called to create a fork of current iterator.
|
||||
/// Blocks generated by fork will have lower difficulty than current chain.
|
||||
fn fork(&mut self, fork_number: usize) -> Fork<Self> where Self: Sized;
|
||||
fn fork(&self, fork_number: usize) -> Fork<Self> where Self: Clone;
|
||||
/// Should be called to make every consecutive block have given bloom.
|
||||
fn with_bloom(&mut self, bloom: H2048) -> Bloom<Self> where Self: Sized;
|
||||
fn with_bloom<'a>(&'a mut self, bloom: H2048) -> Bloom<'a, Self>;
|
||||
/// Should be called to complete block. Without complete, block may have incorrect hash.
|
||||
fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self>;
|
||||
/// Completes and generates block.
|
||||
fn generate<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Option<Bytes> where Self::Item: CompleteBlock;
|
||||
}
|
||||
|
||||
impl<I> ChainIterator for I where I: Iterator + Sized + Clone {
|
||||
fn fork(&mut self, fork_number: usize) -> Fork<Self> {
|
||||
impl<I> ChainIterator for I where I: Iterator + Sized {
|
||||
fn fork(&self, fork_number: usize) -> Fork<Self> where I: Clone {
|
||||
Fork {
|
||||
iter: self.clone(),
|
||||
fork_number: fork_number
|
||||
}
|
||||
}
|
||||
|
||||
fn with_bloom(&mut self, bloom: H2048) -> Bloom<Self> {
|
||||
fn with_bloom<'a>(&'a mut self, bloom: H2048) -> Bloom<'a, Self> {
|
||||
Bloom {
|
||||
iter: self.clone(),
|
||||
iter: self,
|
||||
bloom: bloom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper structure, used for encoding blocks.
|
||||
#[derive(Default)]
|
||||
pub struct Block {
|
||||
header: Header,
|
||||
transactions: Vec<SignedTransaction>,
|
||||
uncles: Vec<Header>
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn rlp(&self) -> Bytes {
|
||||
encode(self).to_vec()
|
||||
fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self> {
|
||||
Complete {
|
||||
iter: self,
|
||||
finalizer: finalizer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Block {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.begin_list(3);
|
||||
s.append(&self.header);
|
||||
s.append(&self.transactions);
|
||||
s.append(&self.uncles);
|
||||
}
|
||||
}
|
||||
|
||||
impl Forkable for Block {
|
||||
fn fork(mut self, fork_number: usize) -> Self where Self: Sized {
|
||||
self.header.difficulty = self.header.difficulty - U256::from(fork_number);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WithBloom for Block {
|
||||
fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized {
|
||||
self.header.log_bloom = bloom;
|
||||
self
|
||||
fn generate<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Option<Bytes> where <I as Iterator>::Item: CompleteBlock {
|
||||
self.complete(finalizer).next()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +68,6 @@ impl WithBloom for Block {
|
||||
pub struct ChainGenerator {
|
||||
/// Next block number.
|
||||
number: BlockNumber,
|
||||
/// Next block parent hash.
|
||||
parent_hash: H256,
|
||||
/// Next block difficulty.
|
||||
difficulty: U256,
|
||||
}
|
||||
@@ -133,7 +75,6 @@ pub struct ChainGenerator {
|
||||
impl ChainGenerator {
|
||||
fn prepare_block(&self) -> Block {
|
||||
let mut block = Block::default();
|
||||
block.header.parent_hash = self.parent_hash.clone();
|
||||
block.header.number = self.number;
|
||||
block.header.difficulty = self.difficulty;
|
||||
block
|
||||
@@ -144,7 +85,6 @@ impl Default for ChainGenerator {
|
||||
fn default() -> Self {
|
||||
ChainGenerator {
|
||||
number: 0,
|
||||
parent_hash: H256::default(),
|
||||
difficulty: U256::from(1000),
|
||||
}
|
||||
}
|
||||
@@ -156,30 +96,28 @@ impl Iterator for ChainGenerator {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let block = self.prepare_block();
|
||||
self.number += 1;
|
||||
self.parent_hash = block.header.hash();
|
||||
Some(block)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::hash::H256;
|
||||
use util::hash::{H256, H2048};
|
||||
use util::sha3::Hashable;
|
||||
use views::BlockView;
|
||||
use super::{ChainIterator, ChainGenerator};
|
||||
use blockchain::generator::{ChainIterator, ChainGenerator, BlockFinalizer};
|
||||
|
||||
#[test]
|
||||
fn canon_chain_generator() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
|
||||
let genesis_rlp = canon_chain.next().unwrap().rlp();
|
||||
let genesis_rlp = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let genesis = BlockView::new(&genesis_rlp);
|
||||
|
||||
assert_eq!(genesis.header_view().parent_hash(), H256::default());
|
||||
assert_eq!(genesis.header_view().number(), 0);
|
||||
|
||||
let b1_rlp = canon_chain.next().unwrap().rlp();
|
||||
let b1_rlp = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b1 = BlockView::new(&b1_rlp);
|
||||
|
||||
assert_eq!(b1.header_view().parent_hash(), genesis.header_view().sha3());
|
||||
@@ -187,17 +125,45 @@ mod tests {
|
||||
|
||||
let mut fork_chain = canon_chain.fork(1);
|
||||
|
||||
let b2_rlp_fork = fork_chain.next().unwrap().rlp();
|
||||
let b2_rlp_fork = fork_chain.generate(&mut finalizer.fork()).unwrap();
|
||||
let b2_fork = BlockView::new(&b2_rlp_fork);
|
||||
|
||||
assert_eq!(b2_fork.header_view().parent_hash(), b1.header_view().sha3());
|
||||
assert_eq!(b2_fork.header_view().number(), 2);
|
||||
|
||||
let b2_rlp = canon_chain.next().unwrap().rlp();
|
||||
let b2_rlp = canon_chain.generate(&mut finalizer).unwrap();
|
||||
let b2 = BlockView::new(&b2_rlp);
|
||||
|
||||
assert_eq!(b2.header_view().parent_hash(), b1.header_view().sha3());
|
||||
assert_eq!(b2.header_view().number(), 2);
|
||||
assert!(b2.header_view().difficulty() > b2_fork.header_view().difficulty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn with_bloom_generator() {
|
||||
let bloom = H2048([0x1; 256]);
|
||||
let mut gen = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
|
||||
let block0_rlp = gen.with_bloom(bloom).generate(&mut finalizer).unwrap();
|
||||
let block1_rlp = gen.generate(&mut finalizer).unwrap();
|
||||
let block0 = BlockView::new(&block0_rlp);
|
||||
let block1 = BlockView::new(&block1_rlp);
|
||||
|
||||
assert_eq!(block0.header_view().number(), 0);
|
||||
assert_eq!(block0.header_view().parent_hash(), H256::default());
|
||||
|
||||
assert_eq!(block1.header_view().number(), 1);
|
||||
assert_eq!(block1.header_view().parent_hash(), block0.header_view().sha3());
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_1000_blocks() {
|
||||
let generator = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
let blocks: Vec<_> = generator.take(1000).complete(&mut finalizer).collect();
|
||||
assert_eq!(blocks.len(), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod generators;
|
||||
mod bloom;
|
||||
mod block;
|
||||
mod complete;
|
||||
mod fork;
|
||||
pub mod generator;
|
||||
|
||||
pub use self::complete::BlockFinalizer;
|
||||
pub use self::generator::{ChainIterator, ChainGenerator};
|
||||
@@ -24,7 +24,7 @@ mod cache;
|
||||
mod tree_route;
|
||||
mod update;
|
||||
#[cfg(test)]
|
||||
mod helpers;
|
||||
mod generator;
|
||||
|
||||
pub use self::blockchain::{BlockProvider, BlockChain, BlockChainConfig};
|
||||
pub use self::cache::CacheSize;
|
||||
|
||||
Reference in New Issue
Block a user