diff --git a/ethcore/blockchain/src/blockchain.rs b/ethcore/blockchain/src/blockchain.rs index 389b95c49..b863ff29e 100644 --- a/ethcore/blockchain/src/blockchain.rs +++ b/ethcore/blockchain/src/blockchain.rs @@ -1476,7 +1476,7 @@ impl BlockChain { } } - /// Apply pending insertion updates + // t_nb 9.12 commit changed to become current greatest by applying pending insertion updates pub fn commit(&self) { let mut pending_best_ancient_block = self.pending_best_ancient_block.write(); let mut pending_best_block = self.pending_best_block.write(); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 0b49a267c..640a92578 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -161,7 +161,7 @@ pub trait Drain { } impl<'x> OpenBlock<'x> { - /// Create a new `OpenBlock` ready for transaction pushing. + // t_nb 8.1 Create a new `OpenBlock` ready for transaction pushing. pub fn new<'a, I: IntoIterator>( engine: &'x dyn EthEngine, factories: Factories, @@ -176,6 +176,8 @@ impl<'x> OpenBlock<'x> { ancestry: I, ) -> Result { let number = parent.number() + 1; + + // t_nb 8.1.1 get parent StateDB. let state = State::from_existing( db, parent.state_root().clone(), @@ -198,14 +200,17 @@ impl<'x> OpenBlock<'x> { let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit); let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target); + // t_nb 8.1.2 It calculated child gas limits should be. engine.machine().populate_from_parent( &mut r.block.header, parent, gas_floor_target, gas_ceil_target, ); + // t_nb 8.1.3 this adds engine specific things engine.populate_from_parent(&mut r.block.header, parent); + // t_nb 8.1.3 updating last hashes and the DAO fork, for ethash. engine.machine().on_new_block(&mut r.block)?; engine.on_new_block(&mut r.block, is_epoch_begin, &mut ancestry.into_iter())?; @@ -222,7 +227,7 @@ impl<'x> OpenBlock<'x> { self.block.header.set_gas_limit(U256::max_value()); } - /// Add an uncle to the block, if possible. + // t_nb 8.4 Add an uncle to the block, if possible. /// /// NOTE Will check chain constraints and the uncle number but will NOT check /// that the header itself is actually valid. @@ -343,13 +348,17 @@ impl<'x> OpenBlock<'x> { }) } - /// Turn this into a `LockedBlock`. + // t_nb 8.5 Turn this into a `LockedBlock`. pub fn close_and_lock(self) -> Result { let mut s = self; + // t_nb 8.5.1 engine applies block rewards (Ethash and AuRa do.Clique is empty) s.engine.on_close_block(&mut s.block)?; + + // t_nb 8.5.2 commit account changes from cache to tree s.block.state.commit()?; + // t_nb 8.5.3 fill open block header with all other fields s.block.header.set_transactions_root(ordered_trie_root( s.block.transactions.iter().map(|e| e.rlp_bytes()), )); @@ -506,7 +515,7 @@ impl Drain for SealedBlock { } } -/// Enact the block given by block header, transactions and uncles +// t_nb 8.0 Enact the block given by block header, transactions and uncles pub(crate) fn enact( header: Header, transactions: Vec, @@ -532,6 +541,7 @@ pub(crate) fn enact( None }; + // t_nb 8.1 Created new OpenBlock let mut b = OpenBlock::new( engine, factories, @@ -556,17 +566,22 @@ pub(crate) fn enact( b.block.header.number(), root, env.author, author_balance); } + // t_nb 8.2 transfer all field from current header to OpenBlock header that we created b.populate_from(&header); + + // t_nb 8.3 execute transactions one by one b.push_transactions(transactions)?; + // t_nb 8.4 Push uncles to OpenBlock and check if we have more then max uncles for u in uncles { b.push_uncle(u)?; } + // t_nb 8.5 close block b.close_and_lock() } -/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header +// t_nb 8.0 Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header pub fn enact_verified( block: PreverifiedBlock, engine: &dyn EthEngine, diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6164f2799..6a025ec2c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -275,7 +275,7 @@ impl Importer { }) } - /// This is triggered by a message coming from a block queue when the block is ready for insertion + // t_nb 6.0 This is triggered by a message coming from a block queue when the block is ready for insertion pub fn import_verified_blocks(&self, client: &Client) -> usize { // Shortcut out if we know we're incapable of syncing the chain. if !client.enabled.load(AtomicOrdering::Relaxed) { @@ -315,11 +315,13 @@ impl Importer { invalid_blocks.insert(hash); continue; } - + // t_nb 7.0 check and lock block match self.check_and_lock_block(&bytes, block, client) { Ok((closed_block, pending)) => { imported_blocks.push(hash); let transactions_len = closed_block.transactions.len(); + + // t_nb 8.0 commit block to db let route = self.commit_block( closed_block, &header, @@ -362,6 +364,7 @@ impl Importer { if !imported_blocks.is_empty() { let route = ChainRoute::from(import_results.as_ref()); + // t_nb 10 Notify miner about new included block. if !has_more_blocks_to_import { self.miner.chain_new_blocks( client, @@ -373,6 +376,7 @@ impl Importer { ); } + // t_nb 11 notify rest of system about new block inclusion client.notify(|notify| { notify.new_blocks(NewBlocks::new( imported_blocks.clone(), @@ -394,6 +398,7 @@ impl Importer { imported } + // t_nb 6.0.1 check and lock block, fn check_and_lock_block( &self, bytes: &[u8], @@ -404,13 +409,14 @@ impl Importer { let header = block.header.clone(); // Check the block isn't so old we won't be able to enact it. + // t_nb 7.1 check if block is older then last pruned block let best_block_number = client.chain.read().best_block_number(); if client.pruning_info().earliest_state > header.number() { warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number); bail!("Block is ancient"); } - // Check if parent is in chain + // t_nb 7.2 Check if parent is in chain let parent = match client.block_header_decoded(BlockId::Hash(*header.parent_hash())) { Some(h) => h, None => { @@ -420,7 +426,7 @@ impl Importer { }; let chain = client.chain.read(); - // Verify Block Family + // t_nb 7.3 verify block family let verify_family_result = self.verifier.verify_block_family( &header, &parent, @@ -437,6 +443,7 @@ impl Importer { bail!(e); }; + // t_nb 7.4 verify block external let verify_external_result = self.verifier.verify_block_external(&header, engine); if let Err(e) = verify_external_result { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); @@ -444,7 +451,9 @@ impl Importer { }; // Enact Verified Block + // t_nb 7.5 Get build last hashes. Get parent state db. Get epoch_transition let last_hashes = client.build_last_hashes(header.parent_hash()); + let db = client .state_db .read() @@ -454,6 +463,7 @@ impl Importer { .epoch_transition(parent.number(), *header.parent_hash()) .is_some(); + // t_nb 8.0 Block enacting. Execution of transactions. let enact_result = enact_verified( block, engine, @@ -474,7 +484,7 @@ impl Importer { } }; - // Strip receipts for blocks before validate_receipts_transition, + // t_nb 7.6 Strip receipts for blocks before validate_receipts_transition, // if the expected receipts root header does not match. // (i.e. allow inconsistency in receipts outcome before the transition block) if header.number() < engine.params().validate_receipts_transition @@ -483,7 +493,7 @@ impl Importer { locked_block.strip_receipts_outcomes(); } - // Final Verification + // t_nb 7.7 Final Verification. See if block that we created (executed) matches exactly with block that we received. if let Err(e) = self .verifier .verify_block_final(&header, &locked_block.header) @@ -570,6 +580,7 @@ impl Importer { let mut batch = DBTransaction::new(); + // t_nb 9.1 Gather all ancestry actions. (Used only by AuRa) let ancestry_actions = self .engine .ancestry_actions(&header, &mut chain.ancestry_with_metadata_iter(*parent)); @@ -605,24 +616,28 @@ impl Importer { } }; + // t_nb 9.2 calcuate route between current and latest block. let route = chain.tree_route(best_hash, *parent).expect("forks are only kept when it has common ancestors; tree route from best to prospective's parent always exists; qed"); + + // t_nb 9.3 Check block total difficulty let fork_choice = if route.is_from_route_finalized { ForkChoice::Old } else { self.engine.fork_choice(&new, &best) }; - // CHECK! I *think* this is fine, even if the state_root is equal to another + // t_nb 9.4 CHECK! I *think* this is fine, even if the state_root is equal to another // already-imported block of the same number. // TODO: Prove it with a test. let mut state = block.state.drop().1; - // check epoch end signal, potentially generating a proof on the current - // state. + // t_nb 9.5 check epoch end signal, potentially generating a proof on the current + // state. Write transition into db. if let Some(pending) = pending { chain.insert_pending_transition(&mut batch, header.hash(), pending); } + // t_nb 9.6 push state to database Transaction. (It calls journal_under from JournalDB) state .journal_under(&mut batch, number, hash) .expect("DB commit failed"); @@ -633,6 +648,7 @@ impl Importer { let AncestryAction::MarkFinalized(a) = ancestry_action; if a != header.hash() { + // t_nb 9.7 if there are finalized ancester, mark that chainge in block in db. (Used by AuRa) chain .mark_finalized(&mut batch, a) .expect("Engine's ancestry action must be known blocks; qed"); @@ -645,6 +661,7 @@ impl Importer { }) .collect(); + // t_nb 9.8 insert block let route = chain.insert_block( &mut batch, block_data, @@ -655,6 +672,7 @@ impl Importer { }, ); + // t_nb 9.9 insert traces (if they are enabled) client.tracedb.read().import( &mut batch, TraceImportRequest { @@ -667,15 +685,22 @@ impl Importer { ); let is_canon = route.enacted.last().map_or(false, |h| h == hash); + + // t_nb 9.10 sync cache state.sync_cache(&route.enacted, &route.retracted, is_canon); // Final commit to the DB + // t_nb 9.11 Write Transaction to database (cached) client.db.read().key_value().write_buffered(batch); + // t_nb 9.12 commit changed to become current greatest by applying pending insertion updates (Sync point) chain.commit(); + // t_nb 9.13 check epoch end. Related only to AuRa and it seems light engine self.check_epoch_end(&header, &finalized, &chain, client); + // t_nb 9.14 update last hashes. They are build in step 7.5 client.update_last_hashes(&parent, hash); + // t_nb 9.15 prune ancient states if let Err(e) = client.prune_ancient(state, &chain) { warn!("Failed to prune ancient state data: {}", e); } @@ -1098,7 +1123,7 @@ impl Client { with_call(&call) } - // prune ancient states until below the memory limit or only the minimum amount remain. + // t_nb 9.15 prune ancient states until below the memory limit or only the minimum amount remain. fn prune_ancient( &self, mut state_db: StateDB, @@ -1138,6 +1163,7 @@ impl Client { Ok(()) } + // t_nb 9.14 update last hashes. They are build in step 7.5 fn update_last_hashes(&self, parent: &H256, hash: &H256) { let mut hashes = self.last_hashes.write(); if hashes.front().map_or(false, |h| h == parent) { @@ -1721,11 +1747,14 @@ impl CallContract for Client { } impl ImportBlock for Client { + // t_nb 2.0 import block to client fn import_block(&self, unverified: Unverified) -> EthcoreResult { + // t_nb 2.1 check if header hash is known to us. if self.chain.read().is_known(&unverified.hash()) { bail!(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain)); } + // t_nb 2.2 check if parent is known let status = self.block_status(BlockId::Hash(unverified.parent_hash())); if status == BlockStatus::Unknown { bail!(EthcoreErrorKind::Block(BlockError::UnknownParent( @@ -1743,14 +1772,16 @@ impl ImportBlock for Client { None }; + // t_nb 2.3 match self.importer.block_queue.import(unverified) { Ok(hash) => { + // t_nb 2.4 If block is okay and the queue is empty we propagate the block in a `PriorityTask` to be rebrodcasted if let Some((raw, hash, difficulty)) = raw { self.notify(move |n| n.block_pre_import(&raw, &hash, &difficulty)); } Ok(hash) } - // we only care about block errors (not import errors) + // t_nb 2.5 if block is not okay print error. we only care about block errors (not import errors) Err((Some(block), EthcoreError(EthcoreErrorKind::Block(err), _))) => { self.importer .bad_blocks diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 3022dc8df..e73065587 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1307,6 +1307,7 @@ impl Engine for AuthorityRound { Ok(()) } + // t_nb 8.1.5 fn on_new_block( &self, block: &mut ExecutedBlock, @@ -1531,7 +1532,7 @@ impl Engine for AuthorityRound { Ok(()) } - // Check the validators. + // t_nb 6.4 Check the validators. fn verify_block_external(&self, header: &Header) -> Result<(), Error> { let (validators, set_number) = self.epoch_set(header)?; diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index e979f4066..0113a4589 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -488,7 +488,7 @@ pub trait Engine: Sync + Send { header_timestamp > parent_timestamp } - /// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that + // t_nb 9.1 Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that /// the ancestry exists. fn ancestry_actions( &self, @@ -507,7 +507,7 @@ pub trait Engine: Sync + Send { } } -/// Check whether a given block is the best block based on the default total difficulty rule. +// t_nb 9.3 Check whether a given block is the best block based on the default total difficulty rule. pub fn total_difficulty_fork_choice(new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice { if new.total_score() > best.total_score() { ForkChoice::New @@ -562,7 +562,7 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { self.machine().create_address_scheme(number) } - /// Verify a particular transaction is valid. + // t_nb 5.3.1 Verify a particular transaction is valid. /// /// Unordered verification doesn't rely on the transaction execution order, /// i.e. it should only verify stuff that doesn't assume any previous transactions diff --git a/ethcore/src/machine/impls.rs b/ethcore/src/machine/impls.rs index 8b98cf08d..890b2854f 100644 --- a/ethcore/src/machine/impls.rs +++ b/ethcore/src/machine/impls.rs @@ -238,7 +238,7 @@ impl EthereumMachine { Ok(()) } - /// Logic to perform on a new block: updating last hashes and the DAO + // t_nb 8.1.3 Logic to perform on a new block: updating last hashes and the DAO /// fork, for ethash. pub fn on_new_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { self.push_last_hash(block)?; diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 96141f1d5..c65f97a1a 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1230,7 +1230,7 @@ impl miner::MinerService for Miner { ) } - /// Update sealing if required. + // t_nb 10.4 Update sealing if required. /// Prepare the block and work if the Engine does not seal internally. fn update_sealing(&self, chain: &C, force: ForceUpdateSealing) where @@ -1339,6 +1339,7 @@ impl miner::MinerService for Miner { }) } + // t_nb 10 notify miner about new include blocks fn chain_new_blocks( &self, chain: &C, @@ -1363,11 +1364,11 @@ impl miner::MinerService for Miner { self.nonce_cache.clear(); } - // First update gas limit in transaction queue and minimal gas price. + // t_nb 10.1 First update gas limit in transaction queue and minimal gas price. let gas_limit = *chain.best_block_header().gas_limit(); self.update_transaction_queue_limits(gas_limit); - // Then import all transactions from retracted blocks. + // t_nb 10.2 Then import all transactions from retracted blocks (retracted means from side chain). let client = self.pool_client(chain); { retracted @@ -1378,7 +1379,8 @@ impl miner::MinerService for Miner { let txs = block.transactions() .into_iter() .map(pool::verifier::Transaction::Retracted) - .collect(); + .collect(); + // t_nb 10.2 let _ = self.transaction_queue.import( client.clone(), txs, @@ -1387,12 +1389,13 @@ impl miner::MinerService for Miner { } if has_new_best_block || (imported.len() > 0 && self.options.reseal_on_uncle) { - // Reset `next_allowed_reseal` in case a block is imported. + // t_nb 10.3 Reset `next_allowed_reseal` in case a block is imported. // Even if min_period is high, we will always attempt to create // new pending block. self.sealing.lock().next_allowed_reseal = Instant::now(); if !is_internal_import { + // t_nb 10.4 if it is internal import update sealing // -------------------------------------------------------------------------- // | NOTE Code below requires sealing locks. | // | Make sure to release the locks before calling that method. | @@ -1402,7 +1405,7 @@ impl miner::MinerService for Miner { } if has_new_best_block { - // Make sure to cull transactions after we update sealing. + // t_nb 10.5 Make sure to cull transactions after we update sealing. // Not culling won't lead to old transactions being added to the block // (thanks to Ready), but culling can take significant amount of time, // so best to leave it after we create some work for miners to prevent increased @@ -1424,7 +1427,9 @@ impl miner::MinerService for Miner { &*accounts, service_transaction_checker.as_ref(), ); + // t_nb 10.5 do culling queue.cull(client); + // reseal is only used by InstaSeal engine if engine.should_reseal_on_update() { // force update_sealing here to skip `reseal_required` checks chain.update_sealing(ForceUpdateSealing::Yes); @@ -1435,13 +1440,16 @@ impl miner::MinerService for Miner { warn!(target: "miner", "Error queueing cull: {:?}", e); } } else { + // t_nb 10.5 do culling self.transaction_queue.cull(client); + // reseal is only used by InstaSeal engine if self.engine.should_reseal_on_update() { // force update_sealing here to skip `reseal_required` checks self.update_sealing(chain, ForceUpdateSealing::Yes); } } } + // t_nb 10.6 For service transaction checker update addresses to latest block if let Some(ref service_transaction_checker) = self.service_transaction_checker { match service_transaction_checker.refresh_cache(chain) { Ok(true) => { diff --git a/ethcore/src/snapshot/watcher.rs b/ethcore/src/snapshot/watcher.rs index 8f1bced37..d949c1c4a 100644 --- a/ethcore/src/snapshot/watcher.rs +++ b/ethcore/src/snapshot/watcher.rs @@ -111,6 +111,7 @@ impl Watcher { } impl ChainNotify for Watcher { + // t_nb 11.1 check number of block and trigger snapshot creation if needed. fn new_blocks(&self, new_blocks: NewBlocks) { if self.oracle.is_major_importing() || new_blocks.has_more_blocks_to_import { return; diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index 167884cd0..2e8118946 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -43,7 +43,7 @@ pub trait Backend: Send { /// Treat the backend as a writeable hashdb. fn as_hash_db_mut(&mut self) -> &mut dyn HashDB; - /// Add an account entry to the cache. + // t_nb 9.4 Add an account entry to the cache. fn add_to_account_cache(&mut self, addr: Address, data: Option, modified: bool); /// Add a global code cache entry. This doesn't need to worry about canonicality because diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 7a6368757..740c666e7 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -996,7 +996,7 @@ impl State { Ok(()) } - /// Commits our cached account changes into the trie. + // t_nb 8.5.2 Commits our cached account changes into the trie. pub fn commit(&mut self) -> Result<(), Error> { assert!(self.checkpoints.borrow().is_empty()); // first, commit the sub trees. @@ -1036,7 +1036,7 @@ impl State { Ok(()) } - /// Propagate local cache into shared canonical state cache. + // t_nb 9.4 Propagate local cache into shared canonical state cache. fn propagate_to_global_cache(&mut self) { let mut addresses = self.cache.borrow_mut(); trace!("Committing cache {:?} entries", addresses.len()); diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs index 306851b9f..78942399d 100644 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -147,6 +147,7 @@ impl StateDB { Ok(records) } + // t_nb 9.15 /// Mark a given candidate from an ancient era as canonical, enacting its removals from the /// backing database and reverting any non-canonical historical commit's insertions. pub fn mark_canonical( @@ -158,7 +159,7 @@ impl StateDB { self.db.mark_canonical(batch, end_era, canon_id) } - /// Propagate local cache into the global cache and synchonize + // t_nb 9.10 Propagate local cache into the global cache and synchonize /// the global cache with the best block state. /// This function updates the global cache by removing entries /// that are invalidated by chain reorganization. `sync_cache` diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 0c5b42afe..e789137a7 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -95,6 +95,7 @@ pub mod blocks { type Unverified = Unverified; type Verified = PreverifiedBlock; + // t_nb 4.0 verify_block_basic fn create( input: Self::Input, engine: &dyn EthEngine, @@ -113,6 +114,7 @@ pub mod blocks { } } + // t_nb 5.0 verify standalone block fn verify( un: Self::Unverified, engine: &dyn EthEngine, diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index fff62d429..cb67d689c 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -364,7 +364,7 @@ impl VerificationQueue { } } - // do work. + // do work on this item. let item = { // acquire these locks before getting the item to verify. let mut unverified = verification.unverified.lock(); @@ -387,10 +387,12 @@ impl VerificationQueue { }; let hash = item.hash(); + // t_nb 5.0 verify standalone block (this verification is done in VerificationQueue thread pool) let is_ready = match K::verify(item, &*engine, verification.check_seal) { Ok(verified) => { let mut verifying = verification.verifying.lock(); let mut idx = None; + // find item again and remove it from verified queue for (i, e) in verifying.iter_mut().enumerate() { if e.hash == hash { idx = Some(i); @@ -515,17 +517,20 @@ impl VerificationQueue { } /// Add a block to the queue. + // t_nb 3.0 import block to verification queue pub fn import(&self, input: K::Input) -> Result, Error)> { let hash = input.hash(); let raw_hash = input.raw_hash(); + // t_nb 3.1 check if block is currently processing or marked as bad. { + // t_nb 3.1.0 is currently processing if self.processing.read().contains_key(&hash) { bail!(( Some(input), ErrorKind::Import(ImportErrorKind::AlreadyQueued).into() )); } - + // t_nb 3.1.1 is marked as bad let mut bad = self.verification.bad.lock(); if bad.contains(&hash) || bad.contains(&raw_hash) { bail!(( @@ -533,7 +538,7 @@ impl VerificationQueue { ErrorKind::Import(ImportErrorKind::KnownBad).into() )); } - + // t_nb 3.1.2 its parent is marked as bad if bad.contains(&input.parent_hash()) { bad.insert(hash); bail!(( diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index a4437c719..012e7ba2b 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -63,26 +63,36 @@ impl HeapSizeOf for PreverifiedBlock { } } -/// Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block +// t_nb 4.0 Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block pub fn verify_block_basic( block: &Unverified, engine: &dyn EthEngine, check_seal: bool, ) -> Result<(), Error> { + // t_nb 4.1 verify header params verify_header_params(&block.header, engine, true, check_seal)?; + // t_nb 4.2 verify header time (addded in new OE version) + // t_nb 4.3 verify block integrity verify_block_integrity(block)?; if check_seal { + // t_nb 4.4 Check block seal. It calls engine to verify block basic engine.verify_block_basic(&block.header)?; } + // t_nb 4.5 for all uncled verify header and call engine to verify block basic for uncle in &block.uncles { + // t_nb 4.5.1 verify_header_params(uncle, engine, false, check_seal)?; if check_seal { + // t_nb 4.5.2 engine.verify_block_basic(uncle)?; } } + // t_nb 4.6 call engine.gas_limit_override (Used only by Aura) TODO added in new version + + // t_nb 4.7 for every transaction call engine.verify_transaction_basic for t in &block.transactions { engine.verify_transaction_basic(t, &block.header)?; } @@ -90,7 +100,7 @@ pub fn verify_block_basic( Ok(()) } -/// Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash. +// t_nb 5.0 Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash. /// Still operates on a individual block /// Returns a `PreverifiedBlock` structure populated with transactions pub fn verify_block_unordered( @@ -100,8 +110,10 @@ pub fn verify_block_unordered( ) -> Result { let header = block.header; if check_seal { + // t_nb 5.1 engine.verify_block_unordered(&header)?; for uncle in &block.uncles { + // t_nb 5.2 engine.verify_block_unordered(uncle)?; } } @@ -112,11 +124,14 @@ pub fn verify_block_unordered( None }; + // t_nb 5.3 iterate over all transactions let transactions = block .transactions .into_iter() .map(|t| { + // t_nb 5.3.1 call verify_unordered. Check signatures and calculate address let t = engine.verify_transaction_unordered(t, &header)?; + // t_nb 5.3.2 check if nonce is more then max nonce (EIP-168 and EIP169) if let Some(max_nonce) = nonce_cap { if t.nonce >= max_nonce { return Err(BlockError::TooManyTransactions(t.sender()).into()); @@ -146,7 +161,7 @@ pub struct FullFamilyParams<'a, C: BlockInfo + CallContract + 'a> { pub client: &'a C, } -/// Phase 3 verification. Check block information against parent and uncles. +// t_nb 6.3 Phase 3 verification. Check block information against parent and uncles. pub fn verify_block_family( header: &Header, parent: &Header, @@ -154,6 +169,7 @@ pub fn verify_block_family( do_full: Option>, ) -> Result<(), Error> { // TODO: verify timestamp + // t_nb 6.3.1 verify parent verify_parent(&header, &parent, engine)?; engine.verify_block_family(&header, &parent)?; @@ -162,8 +178,10 @@ pub fn verify_block_family( None => return Ok(()), }; + // t_nb 6.3.2 verify uncles verify_uncles(params.block, params.block_provider, engine)?; + // t_nb 6.3.3 verify all transactions for tx in ¶ms.block.transactions { // transactions are verified against the parent header since the current // state wasn't available when the tx was created diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 139d4faea..5cea92488 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -529,6 +529,7 @@ impl ChainNotify for EthSync { } } + // t_nb 11.4 fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index 12e0db973..2b3dbf655 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -155,6 +155,7 @@ impl SyncHandler { trace!(target: "sync", "Ignoring new block from unconfirmed peer {}", peer_id); return Ok(()); } + // t_nb 1.0 decode RLP let block = Unverified::from_rlp(r.at(0)?.as_raw().to_vec())?; let hash = block.header.hash(); let number = block.header.number(); @@ -166,7 +167,9 @@ impl SyncHandler { let difficulty: U256 = r.val_at(1)?; // Most probably the sent block is being imported by peer right now // Use td and hash, that peer must have for now + // t_nb 1.1 check new block diffuculty it can be found as second item in RLP and update peer diffuculty let parent_td = difficulty.checked_sub(*block.header.difficulty()); + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { if peer .difficulty @@ -181,6 +184,7 @@ impl SyncHandler { peer.latest_hash = *parent_hash; } + // t_nb 1.2 if block number is to older then 20 dont process it let last_imported_number = sync.new_blocks.last_imported_block_number(); if last_imported_number > number && last_imported_number - number > MAX_NEW_BLOCK_AGE { trace!(target: "sync", "Ignored ancient new block {:?}", hash); diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index 9a5b1f5fe..889b6ef3f 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -1421,7 +1421,7 @@ impl ChainSync { self.check_resume(io); } - /// called when block is imported to chain - propagates the blocks and updates transactions sent to peers + // t_nb 11.4 called when block is imported to chain - propagates the blocks and updates transactions sent to peers pub fn chain_new_blocks( &mut self, io: &mut dyn SyncIo, @@ -1437,7 +1437,9 @@ impl ChainSync { if !is_syncing || !sealed.is_empty() || !proposed.is_empty() { trace!(target: "sync", "Propagating blocks, state={:?}", self.state); + // t_nb 11.4.1 propagate latest blocks SyncPropagator::propagate_latest_blocks(self, io, sealed); + // t_nb 11.4.4 propagate proposed blocks SyncPropagator::propagate_proposed_blocks(self, io, proposed); } if !invalid.is_empty() { @@ -1446,7 +1448,7 @@ impl ChainSync { } if !is_syncing && !enacted.is_empty() && !self.peers.is_empty() { - // Select random peer to re-broadcast transactions to. + // t_nb 11.4.5 Select random peer to re-broadcast transactions to. let peer = random::new().gen_range(0, self.peers.len()); trace!(target: "sync", "Re-broadcasting transactions to a random peer."); self.peers.values_mut().nth(peer).map(|peer_info| { diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs index cd28f7fe8..a70fc813d 100644 --- a/ethcore/sync/src/chain/propagator.rs +++ b/ethcore/sync/src/chain/propagator.rs @@ -39,7 +39,7 @@ use super::{ pub struct SyncPropagator; impl SyncPropagator { - /// propagates latest block to a set of peers + // t_nb 11.4.3 propagates latest block to a set of peers pub fn propagate_blocks( sync: &mut ChainSync, chain_info: &BlockChainInfo, @@ -72,7 +72,7 @@ impl SyncPropagator { sent } - /// propagates new known hashes to all peers + // t_nb 11.4.2 propagates new known hashes to all peers pub fn propagate_new_hashes( sync: &mut ChainSync, chain_info: &BlockChainInfo, @@ -279,6 +279,7 @@ impl SyncPropagator { sent_to_peers } + // t_nb 11.4.1 propagate latest blocks to peers pub fn propagate_latest_blocks(sync: &mut ChainSync, io: &mut dyn SyncIo, sealed: &[H256]) { let chain_info = io.chain().chain_info(); if (((chain_info.best_block_number as i64) - (sync.last_sent_block_number as i64)).abs() @@ -287,15 +288,19 @@ impl SyncPropagator { { let peers = sync.get_lagging_peers(&chain_info); if sealed.is_empty() { + // t_nb 11.4.2 let hashes = SyncPropagator::propagate_new_hashes(sync, &chain_info, io, &peers); let peers = ChainSync::select_random_peers(&peers); + // t_nb 11.4.3 let blocks = SyncPropagator::propagate_blocks(sync, &chain_info, io, sealed, &peers); if blocks != 0 || hashes != 0 { trace!(target: "sync", "Sent latest {} blocks and {} hashes to peers.", blocks, hashes); } } else { + // t_nb 11.4.3 SyncPropagator::propagate_blocks(sync, &chain_info, io, sealed, &peers); + // t_nb 11.4.2 SyncPropagator::propagate_new_hashes(sync, &chain_info, io, &peers); trace!(target: "sync", "Sent sealed block to all peers"); }; @@ -303,7 +308,7 @@ impl SyncPropagator { sync.last_sent_block_number = chain_info.best_block_number; } - /// Distribute valid proposed blocks to subset of current peers. + // t_nb 11.4.4 Distribute valid proposed blocks to subset of current peers. (if there is any proposed) pub fn propagate_proposed_blocks( sync: &mut ChainSync, io: &mut dyn SyncIo, diff --git a/ethcore/types/src/transaction/transaction.rs b/ethcore/types/src/transaction/transaction.rs index 55320d21d..f4de8fbcd 100644 --- a/ethcore/types/src/transaction/transaction.rs +++ b/ethcore/types/src/transaction/transaction.rs @@ -468,7 +468,7 @@ impl From for UnverifiedTransaction { } impl SignedTransaction { - /// Try to verify transaction and recover sender. + // t_nb 5.3.1 Try to verify transaction and recover sender. pub fn new(transaction: UnverifiedTransaction) -> Result { if transaction.is_unsigned() { return Err(ethkey::Error::InvalidSignature); diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index cf8a1f380..45d17090b 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -251,6 +251,7 @@ impl TransactionQueue { self.pool.write().listener_mut().0.set_in_chain_checker(f) } + // t_nb 10.2 /// Import a set of transactions to the pool. /// /// Given blockchain and state access (Client) @@ -471,7 +472,7 @@ impl TransactionQueue { (pending_readiness, state_readiness) } - /// Culls all stalled transactions from the pool. + // t_nb 10.5.1 Culls all stalled transactions from the pool. pub fn cull(&self, client: C) { trace_time!("pool::cull"); // We don't care about future transactions, so nonce_cap is not important. diff --git a/parity/informant.rs b/parity/informant.rs index 4f09c137a..59bd915ba 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -336,6 +336,7 @@ impl Informant { } impl ChainNotify for Informant { + // t_nb 11.2 Informant. Prints new block inclusiong to console/log. fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index e5d0deefb..c8199d463 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -175,6 +175,7 @@ impl ChainNotificationHandler { } impl ChainNotify for ChainNotificationHandler { + // t_nb 11.3 RPC. Notify subscriber header/logs about new block fn new_blocks(&self, new_blocks: NewBlocks) { if self.heads_subscribers.read().is_empty() && self.logs_subscribers.read().is_empty() { return; diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index d853145d7..47a826800 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -83,6 +83,7 @@ impl AclStorage for OnChainAclStorage { } impl ChainNotify for OnChainAclStorage { + // t_nb 11.5 SecretStore OnChainAclStorage. fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 158e6cc0a..137e1b0dd 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -168,6 +168,7 @@ impl KeyServerSet for OnChainKeyServerSet { } impl ChainNotify for OnChainKeyServerSet { + // t_nb 11.6 SecretStore OnChainKeyServerSet. fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/secret-store/src/listener/service_contract_listener.rs b/secret-store/src/listener/service_contract_listener.rs index 6e8fb7eb1..8b6490d9a 100644 --- a/secret-store/src/listener/service_contract_listener.rs +++ b/secret-store/src/listener/service_contract_listener.rs @@ -624,6 +624,7 @@ impl Drop for ServiceContractListener { } impl ChainNotify for ServiceContractListener { + // t_nb 11.7 SecretStore ServiceContractListener fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/util/journaldb/src/overlayrecentdb.rs b/util/journaldb/src/overlayrecentdb.rs index 5c919dfec..8a51161c7 100644 --- a/util/journaldb/src/overlayrecentdb.rs +++ b/util/journaldb/src/overlayrecentdb.rs @@ -332,6 +332,7 @@ impl JournalDB for OverlayRecentDB { self.journal_overlay.read().earliest_era } + // t_nb 9.6 fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> io::Result { trace!(target: "journaldb", "entry: #{} ({})", now, id);