diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 53dcfb62c..10e844192 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -770,14 +770,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(); @@ -806,14 +807,12 @@ mod tests { #[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::>(); - 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(); @@ -897,22 +896,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); } } @@ -976,29 +977,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()); diff --git a/ethcore/src/blockchain/generator/block.rs b/ethcore/src/blockchain/generator/block.rs new file mode 100644 index 000000000..0a3dad399 --- /dev/null +++ b/ethcore/src/blockchain/generator/block.rs @@ -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 . + +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, + pub uncles: Vec
+} + +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() + } +} diff --git a/ethcore/src/blockchain/generator/bloom.rs b/ethcore/src/blockchain/generator/bloom.rs new file mode 100644 index 000000000..f61c9d1ff --- /dev/null +++ b/ethcore/src/blockchain/generator/bloom.rs @@ -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 . + +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, ::Item: WithBloom { + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|item| item.with_bloom(self.bloom.clone())) + } +} diff --git a/ethcore/src/blockchain/generator/complete.rs b/ethcore/src/blockchain/generator/complete.rs new file mode 100644 index 000000000..39bd587a0 --- /dev/null +++ b/ethcore/src/blockchain/generator/complete.rs @@ -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 . + +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, ::Item: CompleteBlock { + type Item = Bytes; + + #[inline] + fn next(&mut self) -> Option { + 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 + }) + } +} diff --git a/ethcore/src/blockchain/generator/fork.rs b/ethcore/src/blockchain/generator/fork.rs new file mode 100644 index 000000000..f3a4eb267 --- /dev/null +++ b/ethcore/src/blockchain/generator/fork.rs @@ -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 . + +pub trait Forkable { + fn fork(self, fork_number: usize) -> Self where Self: Sized; +} + +pub struct Fork { + pub iter: I, + pub fork_number: usize, +} + +impl Clone for Fork where I: Iterator + Clone { + fn clone(&self) -> Self { + Fork { + iter: self.iter.clone(), + fork_number: self.fork_number + } + } +} + +impl Iterator for Fork where I: Iterator, ::Item: Forkable { + type Item = ::Item; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|item| item.fork(self.fork_number)) + } +} diff --git a/ethcore/src/blockchain/helpers/generators.rs b/ethcore/src/blockchain/generator/generator.rs similarity index 51% rename from ethcore/src/blockchain/helpers/generators.rs rename to ethcore/src/blockchain/generator/generator.rs index a20b0cf79..d73b81733 100644 --- a/ethcore/src/blockchain/helpers/generators.rs +++ b/ethcore/src/blockchain/generator/generator.rs @@ -14,108 +14,52 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::rlp::*; -use util::hash::{H256, H2048}; -use util::uint::{U256}; +use util::hash::H2048; +use util::uint::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 { - iter: I, - fork_number: usize, -} - -impl Iterator for Fork where I: Iterator, ::Item: Forkable { - type Item = ::Item; - - #[inline] - fn next(&mut self) -> Option { - 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 { - iter: I, - bloom: H2048, -} - -impl Iterator for Bloom where I: Iterator, ::Item: WithBloom { - type Item = ::Item; - - #[inline] - fn next(&mut self) -> Option { - 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 where Self: Sized; + fn fork(&self, fork_number: usize) -> Fork where Self: Clone; /// Should be called to make every consecutive block have given bloom. - fn with_bloom(&mut self, bloom: H2048) -> Bloom 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 where Self::Item: CompleteBlock; } -impl ChainIterator for I where I: Iterator + Sized + Clone { - fn fork(&mut self, fork_number: usize) -> Fork { +impl ChainIterator for I where I: Iterator + Sized { + fn fork(&self, fork_number: usize) -> Fork where I: Clone { Fork { iter: self.clone(), fork_number: fork_number } } - fn with_bloom(&mut self, bloom: H2048) -> Bloom { + 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, - uncles: Vec
-} - -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 where ::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 { 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); + } } + diff --git a/ethcore/src/blockchain/helpers/mod.rs b/ethcore/src/blockchain/generator/mod.rs similarity index 81% rename from ethcore/src/blockchain/helpers/mod.rs rename to ethcore/src/blockchain/generator/mod.rs index 233f8f1f8..88fdec0e4 100644 --- a/ethcore/src/blockchain/helpers/mod.rs +++ b/ethcore/src/blockchain/generator/mod.rs @@ -14,4 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -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}; diff --git a/ethcore/src/blockchain/mod.rs b/ethcore/src/blockchain/mod.rs index 60a1aeb33..b0679b563 100644 --- a/ethcore/src/blockchain/mod.rs +++ b/ethcore/src/blockchain/mod.rs @@ -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;