github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/validator/src/journal/chain.rs (about) 1 /* 2 * Copyright 2018 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ------------------------------------------------------------------------------ 16 */ 17 18 use std::fs::File; 19 use std::io; 20 use std::io::prelude::*; 21 use std::marker::Send; 22 use std::marker::Sync; 23 use std::path::PathBuf; 24 use std::sync::atomic::AtomicBool; 25 use std::sync::atomic::Ordering; 26 use std::sync::mpsc; 27 use std::sync::mpsc::channel; 28 use std::sync::mpsc::Receiver; 29 use std::sync::mpsc::RecvError; 30 use std::sync::mpsc::Sender; 31 use std::sync::Arc; 32 use std::sync::Mutex; 33 use std::sync::RwLock; 34 use std::thread; 35 use std::time::Duration; 36 37 use protobuf; 38 39 use batch::Batch; 40 use journal; 41 use journal::block_validator::{BlockValidationResult, BlockValidator, ValidationError}; 42 use journal::block_wrapper::BlockWrapper; 43 use journal::chain_head_lock::ChainHeadLock; 44 use metrics; 45 use state::state_pruning_manager::StatePruningManager; 46 47 use proto::transaction_receipt::TransactionReceipt; 48 use scheduler::TxnExecutionResult; 49 50 const RECV_TIMEOUT_MILLIS: u64 = 100; 51 52 lazy_static! { 53 static ref COLLECTOR: metrics::MetricsCollectorHandle = 54 metrics::get_collector("sawtooth_validator.chain"); 55 } 56 57 #[derive(Debug)] 58 pub enum ChainControllerError { 59 QueueRecvError(RecvError), 60 ChainIdError(io::Error), 61 ChainUpdateError(String), 62 BlockValidationError(ValidationError), 63 BrokenQueue, 64 } 65 66 impl From<RecvError> for ChainControllerError { 67 fn from(err: RecvError) -> Self { 68 ChainControllerError::QueueRecvError(err) 69 } 70 } 71 72 impl From<io::Error> for ChainControllerError { 73 fn from(err: io::Error) -> Self { 74 ChainControllerError::ChainIdError(err) 75 } 76 } 77 78 impl From<ValidationError> for ChainControllerError { 79 fn from(err: ValidationError) -> Self { 80 ChainControllerError::BlockValidationError(err) 81 } 82 } 83 84 pub trait ChainObserver: Send + Sync { 85 fn chain_update(&mut self, block: &BlockWrapper, receipts: &[&TransactionReceipt]); 86 } 87 88 pub trait ChainHeadUpdateObserver: Send + Sync { 89 /// Called when the chain head has updated. 90 /// 91 /// Args: 92 /// block: the new chain head 93 /// committed_batches: all of the batches that have been committed 94 /// on the given fork. This may be across multiple blocks. 95 /// uncommitted_batches: all of the batches that have been uncommitted 96 /// from the previous fork, if one was dropped. 97 fn on_chain_head_updated( 98 &mut self, 99 block: BlockWrapper, 100 committed_batches: Vec<Batch>, 101 uncommitted_batches: Vec<Batch>, 102 ); 103 } 104 105 pub trait BlockCache: Send + Sync { 106 fn contains(&self, block_id: &str) -> bool; 107 108 fn put(&mut self, block: BlockWrapper); 109 110 fn get(&self, block_id: &str) -> Option<BlockWrapper>; 111 } 112 113 #[derive(Debug)] 114 pub enum ChainReadError { 115 GeneralReadError(String), 116 } 117 118 pub trait ChainReader: Send + Sync { 119 fn chain_head(&self) -> Result<Option<BlockWrapper>, ChainReadError>; 120 fn count_committed_transactions(&self) -> Result<usize, ChainReadError>; 121 fn get_block_by_block_num( 122 &self, 123 block_num: u64, 124 ) -> Result<Option<BlockWrapper>, ChainReadError>; 125 } 126 127 pub trait ChainWriter: Send + Sync { 128 fn update_chain( 129 &mut self, 130 new_chain: &[BlockWrapper], 131 old_chain: &[BlockWrapper], 132 ) -> Result<(), ChainControllerError>; 133 } 134 135 struct ChainControllerState<BC: BlockCache, BV: BlockValidator, CW: ChainWriter> { 136 block_cache: BC, 137 block_validator: BV, 138 chain_writer: CW, 139 chain_reader: Box<ChainReader>, 140 chain_head: Option<BlockWrapper>, 141 chain_id_manager: ChainIdManager, 142 observers: Vec<Box<ChainObserver>>, 143 state_pruning_manager: StatePruningManager, 144 } 145 146 #[derive(Clone)] 147 pub struct ChainController<BC: BlockCache, BV: BlockValidator, CW: ChainWriter> { 148 state: Arc<RwLock<ChainControllerState<BC, BV, CW>>>, 149 stop_handle: Arc<Mutex<Option<ChainThreadStopHandle>>>, 150 block_queue_sender: Option<Sender<BlockWrapper>>, 151 validation_result_sender: Option<Sender<(bool, BlockValidationResult)>>, 152 state_pruning_block_depth: u32, 153 chain_head_lock: ChainHeadLock, 154 } 155 156 impl<BC: BlockCache + 'static, BV: BlockValidator + 'static, CW: ChainWriter + 'static> 157 ChainController<BC, BV, CW> 158 { 159 pub fn new( 160 block_cache: BC, 161 block_validator: BV, 162 chain_writer: CW, 163 chain_reader: Box<ChainReader>, 164 chain_head_lock: ChainHeadLock, 165 data_dir: String, 166 state_pruning_block_depth: u32, 167 observers: Vec<Box<ChainObserver>>, 168 state_pruning_manager: StatePruningManager, 169 ) -> Self { 170 let mut chain_controller = ChainController { 171 state: Arc::new(RwLock::new(ChainControllerState { 172 block_cache, 173 block_validator, 174 chain_writer, 175 chain_reader, 176 chain_id_manager: ChainIdManager::new(data_dir), 177 observers, 178 chain_head: None, 179 state_pruning_manager, 180 })), 181 stop_handle: Arc::new(Mutex::new(None)), 182 block_queue_sender: None, 183 validation_result_sender: None, 184 state_pruning_block_depth, 185 chain_head_lock, 186 }; 187 188 chain_controller.initialize_chain_head(); 189 190 chain_controller 191 } 192 193 pub fn chain_head(&self) -> Option<BlockWrapper> { 194 let state = self.state 195 .read() 196 .expect("No lock holder should have poisoned the lock"); 197 198 state.chain_head.clone() 199 } 200 201 pub fn on_block_received(&mut self, block: BlockWrapper) -> Result<(), ChainControllerError> { 202 let mut state = self.state 203 .write() 204 .expect("No lock holder should have poisoned the lock"); 205 206 if has_block_no_lock(&state, block.header_signature()) { 207 return Ok(()); 208 } 209 210 if state.chain_head.is_none() { 211 if let Err(err) = set_genesis(&mut state, &self.chain_head_lock, block.clone()) { 212 warn!( 213 "Unable to set chain head; genesis block {} is not valid: {:?}", 214 block.header_signature(), 215 err 216 ); 217 } 218 return Ok(()); 219 } 220 221 state.block_cache.put(block.clone()); 222 self.submit_blocks_for_verification(&state.block_validator, &[block])?; 223 Ok(()) 224 } 225 226 pub fn has_block(&self, block_id: &str) -> bool { 227 let state = self.state 228 .read() 229 .expect("No lock holder should have poisoned the lock"); 230 has_block_no_lock(&state, block_id) 231 } 232 233 fn on_block_validated(&mut self, commit_new_block: bool, result: BlockValidationResult) { 234 let mut state = self.state 235 .write() 236 .expect("No lock holder should have poisoned the lock"); 237 238 let mut blocks_considered_count = 239 COLLECTOR.counter("ChainController.blocks_considered_count", None, None); 240 blocks_considered_count.inc(); 241 242 let new_block = result.block; 243 let initial_chain_head = result.chain_head.header_signature().clone(); 244 if state 245 .chain_head 246 .as_ref() 247 .map(|block| initial_chain_head != block.header_signature()) 248 .unwrap_or(false) 249 { 250 info!( 251 "Chain head updated from {} to {} while processing block {}", 252 result.chain_head, 253 state.chain_head.as_ref().unwrap(), 254 new_block 255 ); 256 if let Err(err) = 257 self.submit_blocks_for_verification(&state.block_validator, &[new_block]) 258 { 259 error!("Unable to submit block for verification: {:?}", err); 260 } 261 } else if commit_new_block { 262 let mut chain_head_guard = self.chain_head_lock.acquire(); 263 let chain_head_block = new_block.clone(); 264 state.chain_head = Some(new_block); 265 266 state.state_pruning_manager.update_queue( 267 &result 268 .new_chain 269 .iter() 270 .map(|block| block.state_root_hash()) 271 .collect::<Vec<_>>(), 272 &result 273 .current_chain 274 .iter() 275 .map(|block| (block.block_num(), block.state_root_hash())) 276 .collect::<Vec<_>>(), 277 ); 278 279 if let Err(err) = state 280 .chain_writer 281 .update_chain(&result.new_chain, &result.current_chain) 282 { 283 error!("Unable to update chain {:?}", err); 284 return; 285 } 286 287 info!( 288 "Chain head updated to {}", 289 state.chain_head.as_ref().unwrap() 290 ); 291 292 let mut chain_head_gauge = COLLECTOR.gauge("ChainController.chain_head", None, None); 293 chain_head_gauge.set_value(&chain_head_block.header_signature()[0..8]); 294 295 let mut committed_transactions_count = 296 COLLECTOR.counter("ChainController.committed_transactions_count", None, None); 297 committed_transactions_count.inc_n(result.transaction_count); 298 299 let mut block_num_guage = COLLECTOR.gauge("ChainController.block_num", None, None); 300 block_num_guage.set_value(chain_head_block.block_num()); 301 302 let chain_head = state.chain_head.clone().unwrap(); 303 chain_head_guard.notify_on_chain_updated( 304 Some(chain_head), 305 result.committed_batches, 306 result.uncommitted_batches, 307 ); 308 309 state.chain_head.as_ref().map(|block| { 310 block.batches().iter().for_each(|batch| { 311 if batch.trace { 312 debug!( 313 "TRACE: {}: ChainController.on_block_validated", 314 batch.header_signature 315 ) 316 } 317 }) 318 }); 319 320 let mut new_chain = result.new_chain; 321 new_chain.reverse(); 322 323 for block in new_chain { 324 let receipts: Vec<TransactionReceipt> = block 325 .execution_results 326 .iter() 327 .map(TransactionReceipt::from) 328 .collect(); 329 for observer in state.observers.iter_mut() { 330 observer.chain_update(&block, &receipts.iter().collect::<Vec<_>>()); 331 } 332 } 333 let total_committed_txns = match state.chain_reader.count_committed_transactions() { 334 Ok(count) => count, 335 Err(err) => { 336 error!( 337 "Unable to read total committed transactions count: {:?}", 338 err 339 ); 340 0 341 } 342 }; 343 344 let mut committed_transactions_gauge = 345 COLLECTOR.gauge("ChainController.committed_transactions_gauge", None, None); 346 committed_transactions_gauge.set_value(total_committed_txns); 347 348 let chain_head_block_num = state.chain_head.as_ref().unwrap().block_num(); 349 if chain_head_block_num + 1 > self.state_pruning_block_depth as u64 { 350 let prune_at = chain_head_block_num - (self.state_pruning_block_depth as u64); 351 match state.chain_reader.get_block_by_block_num(prune_at) { 352 Ok(Some(block)) => state 353 .state_pruning_manager 354 .add_to_queue(block.block_num(), block.state_root_hash()), 355 Ok(None) => warn!("No block at block height {}; ignoring...", prune_at), 356 Err(err) => error!("Unable to fetch block at height {}: {:?}", prune_at, err), 357 } 358 359 // Execute pruning: 360 state.state_pruning_manager.execute(prune_at) 361 } 362 } else { 363 info!("Rejected new chain head: {}", new_block); 364 } 365 } 366 367 /// Light clone makes a copy of this controller, without access to the stop 368 /// handle. 369 pub fn light_clone(&self) -> Self { 370 ChainController { 371 state: self.state.clone(), 372 // This instance doesn't share the stop handle: it's not a 373 // publicly accessible instance 374 stop_handle: Arc::new(Mutex::new(None)), 375 block_queue_sender: self.block_queue_sender.clone(), 376 validation_result_sender: self.validation_result_sender.clone(), 377 state_pruning_block_depth: self.state_pruning_block_depth, 378 chain_head_lock: self.chain_head_lock.clone(), 379 } 380 } 381 382 fn submit_blocks_for_verification( 383 &self, 384 block_validator: &BV, 385 blocks: &[BlockWrapper], 386 ) -> Result<(), ChainControllerError> { 387 let sender = self.validation_result_sender 388 .as_ref() 389 .expect( 390 "Attempted to submit blocks for validation before starting the chain controller", 391 ) 392 .clone(); 393 block_validator.submit_blocks_for_verification(blocks, sender); 394 Ok(()) 395 } 396 397 pub fn queue_block(&self, block: BlockWrapper) { 398 if self.block_queue_sender.is_some() { 399 let sender = self.block_queue_sender.clone(); 400 if let Err(err) = sender.as_ref().unwrap().send(block) { 401 error!("Unable to add block to block queue: {}", err); 402 } 403 } else { 404 debug!( 405 "Attempting to queue block {} before chain controller is started; Ignoring", 406 block 407 ); 408 } 409 } 410 411 fn initialize_chain_head(&mut self) { 412 // we need to check to see if a genesis block was created and stored, 413 // before this controller was started 414 let mut state = self.state 415 .write() 416 .expect("No lock holder should have poisoned the lock"); 417 418 let chain_head = state 419 .chain_reader 420 .chain_head() 421 .expect("Invalid block store. Head of the block chain cannot be determined"); 422 423 if chain_head.is_some() { 424 info!( 425 "Chain controller initialized with chain head: {}", 426 chain_head.as_ref().unwrap() 427 ); 428 let notify_block = chain_head.clone().unwrap(); 429 state.chain_head = chain_head; 430 let mut gauge = COLLECTOR.gauge("ChainController.chain_head", None, None); 431 gauge.set_value(¬ify_block.header_signature()[0..8]); 432 433 let mut block_num_guage = COLLECTOR.gauge("ChainController.block_num", None, None); 434 block_num_guage.set_value(¬ify_block.block_num()); 435 let mut guard = self.chain_head_lock.acquire(); 436 guard.notify_on_chain_updated(Some(notify_block), vec![], vec![]); 437 } 438 } 439 440 pub fn start(&mut self) { 441 // duplicating what happens at the constructor time, but there are multiple 442 // points in the lifetime of this object where the value of the 443 // block store's chain head may have been set 444 self.initialize_chain_head(); 445 let mut stop_handle = self.stop_handle.lock().unwrap(); 446 if stop_handle.is_none() { 447 let (block_queue_sender, block_queue_receiver) = channel(); 448 let (validation_result_sender, validation_result_receiver) = channel(); 449 450 self.block_queue_sender = Some(block_queue_sender); 451 self.validation_result_sender = Some(validation_result_sender); 452 453 let thread_chain_controller = self.light_clone(); 454 let exit_flag = Arc::new(AtomicBool::new(false)); 455 let mut chain_thread = ChainThread::new( 456 thread_chain_controller, 457 block_queue_receiver, 458 exit_flag.clone(), 459 ); 460 *stop_handle = Some(ChainThreadStopHandle::new(exit_flag.clone())); 461 let chain_thread_builder = 462 thread::Builder::new().name("ChainThread:BlockRecevier".into()); 463 chain_thread_builder 464 .spawn(move || { 465 if let Err(err) = chain_thread.run() { 466 error!("Error occurred during ChainController loop: {:?}", err); 467 } 468 }) 469 .unwrap(); 470 let result_thread_builder = 471 thread::Builder::new().name("ChainThread:ValidationResultRecevier".into()); 472 let mut result_thread_controller = self.light_clone(); 473 let result_thread_exit = exit_flag.clone(); 474 result_thread_builder 475 .spawn(move || loop { 476 let (can_commit, result) = match validation_result_receiver 477 .recv_timeout(Duration::from_millis(RECV_TIMEOUT_MILLIS)) 478 { 479 Err(mpsc::RecvTimeoutError::Timeout) => { 480 if result_thread_exit.load(Ordering::Relaxed) { 481 break; 482 } else { 483 continue; 484 } 485 } 486 Err(_) => { 487 error!("Result queue shutdown unexpectedly"); 488 break; 489 } 490 Ok(res) => res, 491 }; 492 493 if !result_thread_exit.load(Ordering::Relaxed) { 494 result_thread_controller.on_block_validated(can_commit, result); 495 } else { 496 break; 497 } 498 }) 499 .unwrap(); 500 } 501 } 502 503 pub fn stop(&mut self) { 504 let mut stop_handle = self.stop_handle.lock().unwrap(); 505 if stop_handle.is_some() { 506 let handle: ChainThreadStopHandle = stop_handle.take().unwrap(); 507 handle.stop(); 508 } 509 } 510 } 511 512 fn has_block_no_lock<BC: BlockCache, BV: BlockValidator, CW: ChainWriter>( 513 state: &ChainControllerState<BC, BV, CW>, 514 block_id: &str, 515 ) -> bool { 516 state.block_cache.contains(block_id) || state.block_validator.in_process(block_id) 517 || state.block_validator.in_pending(block_id) 518 } 519 520 /// This is used by a non-genesis journal when it has received the 521 /// genesis block from the genesis validator 522 fn set_genesis<BC: BlockCache, BV: BlockValidator, CW: ChainWriter>( 523 state: &mut ChainControllerState<BC, BV, CW>, 524 lock: &ChainHeadLock, 525 block: BlockWrapper, 526 ) -> Result<(), ChainControllerError> { 527 if block.previous_block_id() == journal::NULL_BLOCK_IDENTIFIER { 528 let chain_id = state.chain_id_manager.get_block_chain_id()?; 529 if chain_id 530 .as_ref() 531 .map(|block_id| block_id != block.header_signature()) 532 .unwrap_or(false) 533 { 534 warn!( 535 "Block id does not match block chain id {}. Ignoring initial chain head: {}", 536 chain_id.unwrap(), 537 block.header_signature() 538 ); 539 } else { 540 state.block_validator.validate_block(block.clone())?; 541 542 if chain_id.is_none() { 543 state 544 .chain_id_manager 545 .save_block_chain_id(block.header_signature())?; 546 } 547 548 state.chain_writer.update_chain(&[block.clone()], &[])?; 549 state.chain_head = Some(block.clone()); 550 let mut guard = lock.acquire(); 551 guard.notify_on_chain_updated(Some(block.clone()), vec![], vec![]); 552 } 553 } 554 555 Ok(()) 556 } 557 558 impl<'a> From<&'a TxnExecutionResult> for TransactionReceipt { 559 fn from(result: &'a TxnExecutionResult) -> Self { 560 let mut receipt = TransactionReceipt::new(); 561 562 receipt.set_data(protobuf::RepeatedField::from_vec( 563 result.data.iter().map(|(_, data)| data.clone()).collect(), 564 )); 565 receipt.set_state_changes(protobuf::RepeatedField::from_vec( 566 result.state_changes.clone(), 567 )); 568 receipt.set_events(protobuf::RepeatedField::from_vec(result.events.clone())); 569 receipt.set_transaction_id(result.signature.clone()); 570 571 receipt 572 } 573 } 574 575 struct ChainThread<BC: BlockCache, BV: BlockValidator, CW: ChainWriter> { 576 chain_controller: ChainController<BC, BV, CW>, 577 block_queue: Receiver<BlockWrapper>, 578 exit: Arc<AtomicBool>, 579 } 580 581 trait StopHandle: Clone { 582 fn stop(&self); 583 } 584 585 impl<BC: BlockCache + 'static, BV: BlockValidator + 'static, CW: ChainWriter + 'static> 586 ChainThread<BC, BV, CW> 587 { 588 fn new( 589 chain_controller: ChainController<BC, BV, CW>, 590 block_queue: Receiver<BlockWrapper>, 591 exit_flag: Arc<AtomicBool>, 592 ) -> Self { 593 ChainThread { 594 chain_controller, 595 block_queue, 596 exit: exit_flag, 597 } 598 } 599 600 fn run(&mut self) -> Result<(), ChainControllerError> { 601 loop { 602 let block = match self.block_queue 603 .recv_timeout(Duration::from_millis(RECV_TIMEOUT_MILLIS)) 604 { 605 Err(mpsc::RecvTimeoutError::Timeout) => { 606 if self.exit.load(Ordering::Relaxed) { 607 break Ok(()); 608 } else { 609 continue; 610 } 611 } 612 Err(_) => break Err(ChainControllerError::BrokenQueue), 613 Ok(block) => block, 614 }; 615 self.chain_controller.on_block_received(block)?; 616 617 if self.exit.load(Ordering::Relaxed) { 618 break Ok(()); 619 } 620 } 621 } 622 } 623 624 #[derive(Clone)] 625 struct ChainThreadStopHandle { 626 exit: Arc<AtomicBool>, 627 } 628 629 impl ChainThreadStopHandle { 630 fn new(exit_flag: Arc<AtomicBool>) -> Self { 631 ChainThreadStopHandle { exit: exit_flag } 632 } 633 } 634 635 impl StopHandle for ChainThreadStopHandle { 636 fn stop(&self) { 637 self.exit.store(true, Ordering::Relaxed) 638 } 639 } 640 641 /// The ChainIdManager is in charge of of keeping track of the block-chain-id 642 /// stored in the data_dir. 643 #[derive(Clone, Debug)] 644 struct ChainIdManager { 645 data_dir: String, 646 } 647 648 impl ChainIdManager { 649 pub fn new(data_dir: String) -> Self { 650 ChainIdManager { data_dir } 651 } 652 653 pub fn save_block_chain_id(&self, block_chain_id: &str) -> Result<(), io::Error> { 654 let mut path = PathBuf::new(); 655 path.push(&self.data_dir); 656 path.push("block-chain-id"); 657 658 let mut file = File::create(path)?; 659 file.write_all(block_chain_id.as_bytes()) 660 } 661 662 pub fn get_block_chain_id(&self) -> Result<Option<String>, io::Error> { 663 let mut path = PathBuf::new(); 664 path.push(&self.data_dir); 665 path.push("block-chain-id"); 666 667 match File::open(path) { 668 Ok(mut file) => { 669 let mut contents = String::new(); 670 file.read_to_string(&mut contents)?; 671 Ok(Some(contents)) 672 } 673 Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(None), 674 Err(err) => Err(err), 675 } 676 } 677 } 678 679 #[cfg(tests)] 680 mod tests {}