Merge branch 'develop' into fix/2444-rbf-fallbacks

This commit is contained in:
Aaron Blankstein
2021-02-15 15:27:32 -06:00
committed by GitHub
2 changed files with 142 additions and 0 deletions

View File

@@ -19,6 +19,8 @@ incompatible, however.
transaction. Second, fix the "same chainstate hash" fallback check.
- Winning block txid lookups in the SortitionDB have been corrected
to use the txid during the lookup.
- The miner will no longer attempt to mine a new Stacks block if it receives a
microblock in a discontinuous microblock stream.
## [2.0.5] - 2021-02-12

View File

@@ -1356,6 +1356,7 @@ impl StacksChainState {
let mut ret = vec![];
let mut tip: Option<StacksMicroblock> = None;
let mut fork_poison = None;
let mut expected_sequence = start_seq;
// load associated staging microblock data, but best-effort.
// Stop loading once we find a fork juncture.
@@ -1384,6 +1385,18 @@ impl StacksChainState {
}
};
if mblock.header.sequence > expected_sequence {
warn!(
"Discontinuous microblock stream: expected seq {}, got {}",
expected_sequence, mblock.header.sequence
);
break;
}
// expect forks, so expected_sequence may not always increase
expected_sequence =
cmp::min(mblock.header.sequence, expected_sequence).saturating_add(1);
if let Some(tip_mblock) = tip {
if mblock.header.sequence == tip_mblock.header.sequence {
debug!(
@@ -6912,6 +6925,133 @@ pub mod test {
);
}
#[test]
fn stacks_db_staging_microblock_stream_load_continuous_streams() {
let mut chainstate = instantiate_chainstate(
false,
0x80000000,
"stacks_db_staging_microblock_stream_load_continuous_streams",
);
let privk = StacksPrivateKey::from_hex(
"eb05c83546fdd2c79f10f5ad5434a90dd28f7e3acb7c092157aa1bc3656b012c01",
)
.unwrap();
let block = make_empty_coinbase_block(&privk);
let microblocks = make_sample_microblock_stream(&privk, &block.block_hash());
let mut child_block = make_empty_coinbase_block(&privk);
child_block.header.parent_block = block.block_hash();
child_block.header.parent_microblock = microblocks.first().as_ref().unwrap().block_hash();
child_block.header.parent_microblock_sequence =
microblocks.first().as_ref().unwrap().header.sequence;
assert!(StacksChainState::load_staging_microblock(
&chainstate.db(),
&ConsensusHash([2u8; 20]),
&block.block_hash(),
&microblocks[0].block_hash()
)
.unwrap()
.is_none());
assert!(StacksChainState::load_descendant_staging_microblock_stream(
&chainstate.db(),
&StacksBlockHeader::make_index_block_hash(
&ConsensusHash([2u8; 20]),
&block.block_hash()
),
0,
u16::max_value()
)
.unwrap()
.is_none());
store_staging_block(
&mut chainstate,
&ConsensusHash([2u8; 20]),
&block,
&ConsensusHash([1u8; 20]),
1,
2,
);
// don't store the first microblock, but store the rest
for (i, mb) in microblocks.iter().enumerate() {
if i > 0 {
store_staging_microblock(
&mut chainstate,
&ConsensusHash([2u8; 20]),
&block.block_hash(),
mb,
);
}
}
store_staging_block(
&mut chainstate,
&ConsensusHash([3u8; 20]),
&child_block,
&ConsensusHash([2u8; 20]),
1,
2,
);
// block should be stored to staging
assert_block_staging_not_processed(&mut chainstate, &ConsensusHash([2u8; 20]), &block);
assert_block_staging_not_processed(
&mut chainstate,
&ConsensusHash([3u8; 20]),
&child_block,
);
assert_block_not_stored(&mut chainstate, &ConsensusHash([2u8; 20]), &block);
assert_block_not_stored(&mut chainstate, &ConsensusHash([3u8; 20]), &child_block);
// missing head
assert!(StacksChainState::load_staging_microblock(
&chainstate.db(),
&ConsensusHash([2u8; 20]),
&block.block_hash(),
&microblocks[0].block_hash()
)
.unwrap()
.is_none());
// subsequent microblock stream should be stored to staging
assert!(StacksChainState::load_staging_microblock(
&chainstate.db(),
&ConsensusHash([2u8; 20]),
&block.block_hash(),
&microblocks[1].block_hash()
)
.unwrap()
.is_some());
assert_eq!(
StacksChainState::load_staging_microblock(
&chainstate.db(),
&ConsensusHash([2u8; 20]),
&block.block_hash(),
&microblocks[1].block_hash()
)
.unwrap()
.unwrap()
.try_into_microblock()
.unwrap(),
microblocks[1]
);
// can't load descendent stream because missing head
assert!(StacksChainState::load_descendant_staging_microblock_stream(
&chainstate.db(),
&StacksBlockHeader::make_index_block_hash(
&ConsensusHash([2u8; 20]),
&block.block_hash()
),
0,
u16::max_value()
)
.unwrap()
.is_none());
}
#[test]
fn stacks_db_validate_parent_microblock_stream() {
let privk = StacksPrivateKey::from_hex(