Merge branch 'master' into finduncles
This commit is contained in:
@@ -466,7 +466,8 @@ impl BlockChain {
|
||||
let mut write_details = self.block_details.write().unwrap();
|
||||
for (hash, details) in update.block_details.into_iter() {
|
||||
batch.put_extras(&hash, &details);
|
||||
write_details.insert(hash, details);
|
||||
write_details.insert(hash.clone(), details);
|
||||
self.note_used(CacheID::Extras(ExtrasIndex::BlockDetails, hash));
|
||||
}
|
||||
|
||||
let mut write_receipts = self.block_receipts.write().unwrap();
|
||||
@@ -802,6 +803,14 @@ impl BlockChain {
|
||||
|
||||
// TODO: handle block_hashes properly.
|
||||
block_hashes.clear();
|
||||
|
||||
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();
|
||||
}
|
||||
if self.cache_size().total() < self.max_cache_size { break; }
|
||||
}
|
||||
|
||||
@@ -123,6 +123,9 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Get block total difficulty.
|
||||
fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
|
||||
|
||||
/// Get block hash.
|
||||
fn block_hash(&self, id: BlockId) -> Option<H256>;
|
||||
|
||||
/// Get address code.
|
||||
fn code(&self, address: &Address) -> Option<Bytes>;
|
||||
|
||||
@@ -540,6 +543,11 @@ impl BlockChainClient for Client {
|
||||
Self::block_hash(&chain, id).and_then(|hash| chain.block_details(&hash)).map(|d| d.total_difficulty)
|
||||
}
|
||||
|
||||
fn block_hash(&self, id: BlockId) -> Option<H256> {
|
||||
let chain = self.chain.read().unwrap();
|
||||
Self::block_hash(&chain, id)
|
||||
}
|
||||
|
||||
fn code(&self, address: &Address) -> Option<Bytes> {
|
||||
self.state().code(address)
|
||||
}
|
||||
|
||||
@@ -42,6 +42,22 @@ pub struct Filter {
|
||||
pub topics: [Option<Vec<H256>>; 4],
|
||||
}
|
||||
|
||||
impl Clone for Filter {
|
||||
fn clone(&self) -> Self {
|
||||
let mut topics = [None, None, None, None];
|
||||
for i in 0..4 {
|
||||
topics[i] = self.topics[i].clone();
|
||||
}
|
||||
|
||||
Filter {
|
||||
from_block: self.from_block.clone(),
|
||||
to_block: self.to_block.clone(),
|
||||
address: self.address.clone(),
|
||||
topics: topics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
/// Returns combinations of each address and topic.
|
||||
pub fn bloom_possibilities(&self) -> Vec<H2048> {
|
||||
|
||||
@@ -108,6 +108,25 @@ fn can_collect_garbage() {
|
||||
assert!(client.blockchain_cache_info().blocks < 100 * 1024);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_handle_long_fork() {
|
||||
let client_result = generate_dummy_client(1200);
|
||||
let client = client_result.reference();
|
||||
for _ in 0..10 {
|
||||
client.import_verified_blocks(&IoChannel::disconnected());
|
||||
}
|
||||
assert_eq!(1200, client.chain_info().best_block_number);
|
||||
|
||||
push_blocks_to_client(client, 45, 1201, 800);
|
||||
push_blocks_to_client(client, 49, 1201, 800);
|
||||
push_blocks_to_client(client, 53, 1201, 600);
|
||||
|
||||
for _ in 0..20 {
|
||||
client.import_verified_blocks(&IoChannel::disconnected());
|
||||
}
|
||||
assert_eq!(2000, client.chain_info().best_block_number);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_mine() {
|
||||
let dummy_blocks = get_good_dummy_block_seq(2);
|
||||
@@ -122,7 +141,7 @@ fn can_mine() {
|
||||
b.hash()
|
||||
}
|
||||
None => { panic!(); }
|
||||
}
|
||||
}
|
||||
};
|
||||
assert!(client.submit_seal(pow_hash, vec![]).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,10 +156,9 @@ pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>
|
||||
rolling_block_number = rolling_block_number + 1;
|
||||
rolling_timestamp = rolling_timestamp + 10;
|
||||
|
||||
if let Err(_) = client.import_block(create_test_block(&header)) {
|
||||
panic!("error importing block which is valid by definition");
|
||||
if let Err(e) = client.import_block(create_test_block(&header)) {
|
||||
panic!("error importing block which is valid by definition: {:?}", e);
|
||||
}
|
||||
|
||||
}
|
||||
client.flush_queue();
|
||||
client.import_verified_blocks(&IoChannel::disconnected());
|
||||
@@ -170,6 +169,34 @@ pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult<Arc<Client>
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_blocks_to_client(client: &Arc<Client>, timestamp_salt: u64, starting_number: usize, block_number: usize) {
|
||||
let test_spec = get_test_spec();
|
||||
let test_engine = test_spec.to_engine().unwrap();
|
||||
let state_root = test_engine.spec().genesis_header().state_root;
|
||||
let mut rolling_hash = client.chain_info().best_block_hash;
|
||||
let mut rolling_block_number = starting_number as u64;
|
||||
let mut rolling_timestamp = timestamp_salt + starting_number as u64 * 10;
|
||||
|
||||
for _ in 0..block_number {
|
||||
let mut header = Header::new();
|
||||
|
||||
header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap());
|
||||
header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap());
|
||||
header.timestamp = rolling_timestamp;
|
||||
header.number = rolling_block_number;
|
||||
header.parent_hash = rolling_hash;
|
||||
header.state_root = state_root.clone();
|
||||
|
||||
rolling_hash = header.hash();
|
||||
rolling_block_number = rolling_block_number + 1;
|
||||
rolling_timestamp = rolling_timestamp + 10;
|
||||
|
||||
if let Err(e) = client.import_block(create_test_block(&header)) {
|
||||
panic!("error importing block which is valid by definition: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> {
|
||||
let dir = RandomTempPath::new();
|
||||
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), IoChannel::disconnected()).unwrap();
|
||||
@@ -253,18 +280,29 @@ pub fn get_temp_state_in(path: &Path) -> State {
|
||||
pub fn get_good_dummy_block_seq(count: usize) -> Vec<Bytes> {
|
||||
let test_spec = get_test_spec();
|
||||
let test_engine = test_spec.to_engine().unwrap();
|
||||
let mut parent = test_engine.spec().genesis_header().hash();
|
||||
get_good_dummy_block_fork_seq(1, count, &test_engine.spec().genesis_header().hash())
|
||||
}
|
||||
|
||||
pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_hash: &H256) -> Vec<Bytes> {
|
||||
let test_spec = get_test_spec();
|
||||
let test_engine = test_spec.to_engine().unwrap();
|
||||
let mut rolling_timestamp = start_number as u64 * 10;
|
||||
let mut parent = *parent_hash;
|
||||
let mut r = Vec::new();
|
||||
for i in 1 .. count + 1 {
|
||||
for i in start_number .. start_number + count + 1 {
|
||||
let mut block_header = Header::new();
|
||||
block_header.gas_limit = decode(test_engine.spec().engine_params.get("minGasLimit").unwrap());
|
||||
block_header.difficulty = decode(test_engine.spec().engine_params.get("minimumDifficulty").unwrap());
|
||||
block_header.timestamp = i as u64;
|
||||
block_header.difficulty = U256::from(i).mul(U256([0, 1, 0, 0]));
|
||||
block_header.timestamp = rolling_timestamp;
|
||||
block_header.number = i as u64;
|
||||
block_header.parent_hash = parent;
|
||||
block_header.state_root = test_engine.spec().genesis_header().state_root;
|
||||
|
||||
parent = block_header.hash();
|
||||
rolling_timestamp = rolling_timestamp + 10;
|
||||
|
||||
r.push(create_test_block(&block_header));
|
||||
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user