Fix parallel transactions race-condition (#10995)
* WiP : clear pending txs cache & tick in Miner * Fixed pending transactions * Revert debugging code * Add ToDo comment * Remove commented-out code * Reverse LTO setting * WiP * Try to seal a new block if there are pending transactions * Try resealing only for internal imports * Remove logging * Use AtomicU64 instead of Mutex<BlockNumber> * Remove TxQueue cache clear // Update AtomicUint logic * Update comments in Miner * Revert import of `parking_lot` * Update `transaction-pool` dependency * Call directly `update_sealing` * Call `update_sealing` directly
This commit is contained in:
		
							parent
							
								
									240ef46c72
								
							
						
					
					
						commit
						5e2def1b23
					
				
							
								
								
									
										10
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -1263,7 +1263,7 @@ dependencies = [ | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "transaction-pool 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| @ -1366,7 +1366,7 @@ dependencies = [ | ||||
|  "time-utils 0.1.0", | ||||
|  "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "trace 0.1.0", | ||||
|  "transaction-pool 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "vm 0.1.0", | ||||
| @ -3141,7 +3141,7 @@ dependencies = [ | ||||
|  "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "trace 0.1.0", | ||||
|  "transaction-pool 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "verification 0.1.0", | ||||
|  "vm 0.1.0", | ||||
| @ -4737,7 +4737,7 @@ dependencies = [ | ||||
| 
 | ||||
| [[package]] | ||||
| name = "transaction-pool" | ||||
| version = "2.0.0" | ||||
| version = "2.0.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| @ -5568,7 +5568,7 @@ dependencies = [ | ||||
| "checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" | ||||
| "checksum toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "450441e131c7663af72e63a33c02a6a1fbaaa8601dc652ed6757813bb55aeec7" | ||||
| "checksum trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe82f2f0bf1991e163e757baf044282823155dd326e70f44ce2186c3c320cc9" | ||||
| "checksum transaction-pool 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d8bd3123931aa6e49dd03bc8a2400490e14701d779458d1f1fff1f04c6f666" | ||||
| "checksum transaction-pool 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "454adc482e32785c3beab9415dd0f3c689f29cc2d16717eb62f6a784d53544b4" | ||||
| "checksum transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb4b191d033a35edfce392a38cdcf9790b6cebcb30fa690c312c29da4dc433e" | ||||
| "checksum trie-db 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b65d609ae631d808c6c1cc23a622733d5a0b66a7d67e9f5cd5171562a1f4cb5" | ||||
| "checksum trie-standardmap 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64fda153c00484d640bc91334624be22ead0e5baca917d9fd53ff29bdebcf9b2" | ||||
|  | ||||
| @ -14,6 +14,8 @@ | ||||
| // You should have received a copy of the GNU General Public License
 | ||||
| // along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| use std::sync::atomic::{AtomicU64, Ordering}; | ||||
| 
 | ||||
| use common_types::{ | ||||
| 	header::Header, | ||||
| 	engines::{ | ||||
| @ -51,6 +53,7 @@ impl From<ethjson::spec::InstantSealParams> for InstantSealParams { | ||||
| pub struct InstantSeal { | ||||
| 	params: InstantSealParams, | ||||
| 	machine: Machine, | ||||
| 	last_sealed_block: AtomicU64, | ||||
| } | ||||
| 
 | ||||
| impl InstantSeal { | ||||
| @ -59,6 +62,7 @@ impl InstantSeal { | ||||
| 		InstantSeal { | ||||
| 			params, | ||||
| 			machine, | ||||
| 			last_sealed_block: AtomicU64::new(0), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -71,11 +75,19 @@ impl Engine for InstantSeal { | ||||
| 	fn sealing_state(&self) -> SealingState { SealingState::Ready } | ||||
| 
 | ||||
| 	fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal { | ||||
| 		if block.transactions.is_empty() { | ||||
| 			Seal::None | ||||
| 		} else { | ||||
| 			Seal::Regular(Vec::new()) | ||||
| 		if !block.transactions.is_empty() { | ||||
| 			let block_number = block.header.number(); | ||||
| 			let last_sealed_block = self.last_sealed_block.load(Ordering::SeqCst); | ||||
| 			// Return a regular seal if the given block is _higher_ than
 | ||||
| 			// the last sealed one
 | ||||
| 			if block_number > last_sealed_block { | ||||
| 				let prev_last_sealed_block = self.last_sealed_block.compare_and_swap(last_sealed_block, block_number, Ordering::SeqCst); | ||||
| 				if prev_last_sealed_block == last_sealed_block { | ||||
| 					return Seal::Regular(Vec::new()) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		Seal::None | ||||
| 	} | ||||
| 
 | ||||
| 	fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { | ||||
|  | ||||
| @ -47,7 +47,7 @@ state-db = { path = "../state-db" } | ||||
| time-utils = { path = "../../util/time-utils" } | ||||
| tiny-keccak = "1.4" | ||||
| trace = { path = "../trace" } | ||||
| transaction-pool = "2.0" | ||||
| transaction-pool = "2.0.1" | ||||
| url = "1" | ||||
| vm = { path = "../vm" } | ||||
| 
 | ||||
|  | ||||
| @ -33,7 +33,7 @@ use futures::sync::mpsc; | ||||
| use io::IoChannel; | ||||
| use miner::filter_options::{FilterOptions, FilterOperator}; | ||||
| use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache}; | ||||
| use miner; | ||||
| use miner::{self, MinerService}; | ||||
| use parking_lot::{Mutex, RwLock}; | ||||
| use rayon::prelude::*; | ||||
| use types::{ | ||||
| @ -58,7 +58,7 @@ use using_queue::{UsingQueue, GetAction}; | ||||
| 
 | ||||
| use block::{ClosedBlock, SealedBlock}; | ||||
| use client::{BlockProducer, SealedBlockImporter, Client}; | ||||
| use client_traits::{BlockChain, ChainInfo, Nonce, TransactionInfo}; | ||||
| use client_traits::{BlockChain, ChainInfo, EngineClient, Nonce, TransactionInfo}; | ||||
| use engine::{Engine, signer::EngineSigner}; | ||||
| use machine::executive::contract_address; | ||||
| use spec::Spec; | ||||
| @ -859,9 +859,9 @@ impl Miner { | ||||
| 			false | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/// Prepare pending block, check whether sealing is needed, and then update sealing.
 | ||||
| 	fn prepare_and_update_sealing<C: miner::BlockChainClient>(&self, chain: &C) { | ||||
| 		use miner::MinerService; | ||||
| 		match self.engine.sealing_state() { | ||||
| 			SealingState::Ready => { | ||||
| 				self.maybe_enable_sealing(); | ||||
| @ -1429,6 +1429,9 @@ impl miner::MinerService for Miner { | ||||
| 						service_transaction_checker.as_ref(), | ||||
| 					); | ||||
| 					queue.cull(client); | ||||
| 					if is_internal_import { | ||||
| 						chain.update_sealing(); | ||||
| 					} | ||||
| 				}; | ||||
| 
 | ||||
| 				if let Err(e) = channel.send(ClientIoMessage::<Client>::execute(cull)) { | ||||
| @ -1436,8 +1439,12 @@ impl miner::MinerService for Miner { | ||||
| 				} | ||||
| 			} else { | ||||
| 				self.transaction_queue.cull(client); | ||||
| 				if is_internal_import { | ||||
| 					self.update_sealing(chain); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if let Some(ref service_transaction_checker) = self.service_transaction_checker { | ||||
| 			match service_transaction_checker.refresh_cache(chain) { | ||||
| 				Ok(true) => { | ||||
|  | ||||
| @ -34,7 +34,7 @@ serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| serde_json = "1.0" | ||||
| trace-time = "0.1" | ||||
| transaction-pool = "2.0" | ||||
| transaction-pool = "2.0.1" | ||||
| 
 | ||||
| [dev-dependencies] | ||||
| env_logger = "0.5" | ||||
|  | ||||
| @ -80,7 +80,7 @@ fake-fetch = { path = "../util/fake-fetch" } | ||||
| macros = { path = "../util/macros" } | ||||
| spec = { path = "../ethcore/spec" } | ||||
| pretty_assertions = "0.1" | ||||
| transaction-pool = "2.0" | ||||
| transaction-pool = "2.0.1" | ||||
| verification = { path = "../ethcore/verification" } | ||||
| 
 | ||||
| [features] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user