diff --git a/CHANGELOG.md b/CHANGELOG.md index ec7db62458..63a820141e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.9] + +This is a hotfix release for improved handling of arriving Stacks blocks through +both the RPC interface and the P2P ineterface. The chainstate directory of +2.0.9 is compatible with the 2.0.8 chainstate. + +## Fixed + +- TOCTTOU bug fixed in the chain processing logic that, which now ensures that + an arriving Stacks block is processed at most once. + ## [2.0.8] - 2021-03-02 This is a hotfix release for improved handling of static analysis storage and diff --git a/Cargo.toml b/Cargo.toml index c476012314..0df800e0b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,7 +91,9 @@ features = ["std"] [dev-dependencies] assert-json-diff = "1.0.0" -criterion = "0.3" +# a nightly rustc regression (35dbef235 2021-03-02) prevents criterion from compiling +# but it isn't necessary for tests: only benchmarks. therefore, commenting out for now. +# criterion = "0.3" stx_genesis = { package = "stx-genesis", path = "./stx-genesis/."} [features] diff --git a/src/chainstate/stacks/db/blocks.rs b/src/chainstate/stacks/db/blocks.rs index abccfb13cc..ec51a8e060 100644 --- a/src/chainstate/stacks/db/blocks.rs +++ b/src/chainstate/stacks/db/blocks.rs @@ -3207,13 +3207,17 @@ impl StacksChainState { ); let sort_handle = SortitionHandleConn::open_reader_consensus(sort_ic, consensus_hash)?; + let mainnet = self.mainnet; + let chain_id = self.chain_id; + let blocks_path = self.blocks_path.clone(); + let mut block_tx = self.db_tx_begin()?; // already in queue or already processed? let index_block_hash = StacksBlockHeader::make_index_block_hash(consensus_hash, &block.block_hash()); if StacksChainState::has_stored_block( - &self.db(), - &self.blocks_path, + &block_tx, + &blocks_path, consensus_hash, &block.block_hash(), )? { @@ -3225,7 +3229,7 @@ impl StacksChainState { ); return Ok(false); } else if StacksChainState::has_staging_block( - &self.db(), + &block_tx, consensus_hash, &block.block_hash(), )? { @@ -3236,7 +3240,7 @@ impl StacksChainState { &index_block_hash ); return Ok(false); - } else if StacksChainState::has_block_indexed(&self.blocks_path, &index_block_hash)? { + } else if StacksChainState::has_block_indexed(&blocks_path, &index_block_hash)? { debug!( "Block already stored to chunk store: {}/{} ({})", consensus_hash, @@ -3249,11 +3253,6 @@ impl StacksChainState { // find all user burns that supported this block let user_burns = sort_handle.get_winning_user_burns_by_block()?; - let mainnet = self.mainnet; - let chain_id = self.chain_id; - let blocks_path = self.blocks_path.clone(); - let mut block_tx = self.db_tx_begin()?; - // does this block match the burnchain state? skip if not let validation_res = StacksChainState::validate_anchored_block_burnchain( &sort_handle,