Skip to content

Commit 230a946

Browse files
authored
Merge pull request #5528 from stacks-network/release/3.0.0.0.4
merge Release/3.0.0.0.4 to master
2 parents 160b495 + 5f54e64 commit 230a946

File tree

8 files changed

+119
-81
lines changed

8 files changed

+119
-81
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1111

1212
### Changed
1313

14+
## [3.0.0.0.4]
15+
16+
### Added
17+
18+
### Changed
19+
20+
- Use the same burn view loader in both block validation and block processing
1421

1522
## [3.0.0.0.3]
1623

stacks-signer/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ and this project adheres to the versioning scheme outlined in the [README.md](RE
1111

1212
### Changed
1313

14+
## [3.0.0.0.4.0]
15+
16+
### Added
17+
18+
### Changed
19+
20+
- Use the same burn view loader in both block validation and block processing
21+
1422
## [3.0.0.0.3.0]
1523

1624
### Added

stacks-signer/src/signerdb.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -871,16 +871,6 @@ where
871871
.map_err(DBError::SerializationError)
872872
}
873873

874-
#[cfg(test)]
875-
pub fn test_signer_db(db_path: &str) -> SignerDb {
876-
use std::fs;
877-
878-
if fs::metadata(db_path).is_ok() {
879-
fs::remove_file(db_path).unwrap();
880-
}
881-
SignerDb::new(db_path).expect("Failed to create signer db")
882-
}
883-
884874
#[cfg(test)]
885875
mod tests {
886876
use std::fs;

stackslib/src/chainstate/burn/db/sortdb.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3986,7 +3986,7 @@ impl<'a> SortitionDBConn<'a> {
39863986
tip,
39873987
reward_cycle_id,
39883988
)?;
3989-
info!("Fetching preprocessed reward set";
3989+
debug!("Fetching preprocessed reward set";
39903990
"tip_sortition_id" => %tip,
39913991
"reward_cycle_id" => reward_cycle_id,
39923992
"prepare_phase_start_sortition_id" => %first_sortition,

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,6 +1788,73 @@ impl NakamotoChainState {
17881788
}
17891789
}
17901790

1791+
/// Get the current burnchain view
1792+
/// This is either:
1793+
/// (1) set by the tenure change tx if one exists
1794+
/// (2) the same as parent block id
1795+
pub fn get_block_burn_view(
1796+
sort_db: &SortitionDB,
1797+
next_ready_block: &NakamotoBlock,
1798+
parent_header_info: &StacksHeaderInfo,
1799+
) -> Result<ConsensusHash, ChainstateError> {
1800+
let burnchain_view = if let Some(tenure_change) = next_ready_block.get_tenure_tx_payload() {
1801+
if let Some(ref parent_burn_view) = parent_header_info.burn_view {
1802+
// check that the tenure_change's burn view descends from the parent
1803+
let parent_burn_view_sn = SortitionDB::get_block_snapshot_consensus(
1804+
sort_db.conn(),
1805+
parent_burn_view,
1806+
)?
1807+
.ok_or_else(|| {
1808+
warn!(
1809+
"Cannot process Nakamoto block: could not find parent block's burnchain view";
1810+
"consensus_hash" => %next_ready_block.header.consensus_hash,
1811+
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1812+
"stacks_block_id" => %next_ready_block.header.block_id(),
1813+
"parent_block_id" => %next_ready_block.header.parent_block_id
1814+
);
1815+
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1816+
})?;
1817+
let handle = sort_db.index_handle_at_ch(&tenure_change.burn_view_consensus_hash)?;
1818+
let connected_sort_id = get_ancestor_sort_id(&handle, parent_burn_view_sn.block_height, &handle.context.chain_tip)?
1819+
.ok_or_else(|| {
1820+
warn!(
1821+
"Cannot process Nakamoto block: could not find parent block's burnchain view";
1822+
"consensus_hash" => %next_ready_block.header.consensus_hash,
1823+
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1824+
"stacks_block_id" => %next_ready_block.header.block_id(),
1825+
"parent_block_id" => %next_ready_block.header.parent_block_id
1826+
);
1827+
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1828+
})?;
1829+
if connected_sort_id != parent_burn_view_sn.sortition_id {
1830+
warn!(
1831+
"Cannot process Nakamoto block: parent block's burnchain view does not connect to own burn view";
1832+
"consensus_hash" => %next_ready_block.header.consensus_hash,
1833+
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1834+
"stacks_block_id" => %next_ready_block.header.block_id(),
1835+
"parent_block_id" => %next_ready_block.header.parent_block_id
1836+
);
1837+
return Err(ChainstateError::InvalidStacksBlock(
1838+
"Does not connect to burn view of parent block ID".into(),
1839+
));
1840+
}
1841+
}
1842+
tenure_change.burn_view_consensus_hash
1843+
} else {
1844+
parent_header_info.burn_view.clone().ok_or_else(|| {
1845+
warn!(
1846+
"Cannot process Nakamoto block: parent block does not have a burnchain view and current block has no tenure tx";
1847+
"consensus_hash" => %next_ready_block.header.consensus_hash,
1848+
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1849+
"stacks_block_id" => %next_ready_block.header.block_id(),
1850+
"parent_block_id" => %next_ready_block.header.parent_block_id
1851+
);
1852+
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1853+
})?
1854+
};
1855+
Ok(burnchain_view)
1856+
}
1857+
17911858
/// Process the next ready block.
17921859
/// If there exists a ready Nakamoto block, then this method returns Ok(Some(..)) with the
17931860
/// receipt. Otherwise, it returns Ok(None).
@@ -1920,62 +1987,8 @@ impl NakamotoChainState {
19201987
// this is either:
19211988
// (1) set by the tenure change tx if one exists
19221989
// (2) the same as parent block id
1923-
1924-
let burnchain_view = if let Some(tenure_change) = next_ready_block.get_tenure_tx_payload() {
1925-
if let Some(ref parent_burn_view) = parent_header_info.burn_view {
1926-
// check that the tenure_change's burn view descends from the parent
1927-
let parent_burn_view_sn = SortitionDB::get_block_snapshot_consensus(
1928-
sort_db.conn(),
1929-
parent_burn_view,
1930-
)?
1931-
.ok_or_else(|| {
1932-
warn!(
1933-
"Cannot process Nakamoto block: could not find parent block's burnchain view";
1934-
"consensus_hash" => %next_ready_block.header.consensus_hash,
1935-
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1936-
"stacks_block_id" => %next_ready_block.header.block_id(),
1937-
"parent_block_id" => %next_ready_block.header.parent_block_id
1938-
);
1939-
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1940-
})?;
1941-
let handle = sort_db.index_handle_at_ch(&tenure_change.burn_view_consensus_hash)?;
1942-
let connected_sort_id = get_ancestor_sort_id(&handle, parent_burn_view_sn.block_height, &handle.context.chain_tip)?
1943-
.ok_or_else(|| {
1944-
warn!(
1945-
"Cannot process Nakamoto block: could not find parent block's burnchain view";
1946-
"consensus_hash" => %next_ready_block.header.consensus_hash,
1947-
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1948-
"stacks_block_id" => %next_ready_block.header.block_id(),
1949-
"parent_block_id" => %next_ready_block.header.parent_block_id
1950-
);
1951-
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1952-
})?;
1953-
if connected_sort_id != parent_burn_view_sn.sortition_id {
1954-
warn!(
1955-
"Cannot process Nakamoto block: parent block's burnchain view does not connect to own burn view";
1956-
"consensus_hash" => %next_ready_block.header.consensus_hash,
1957-
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1958-
"stacks_block_id" => %next_ready_block.header.block_id(),
1959-
"parent_block_id" => %next_ready_block.header.parent_block_id
1960-
);
1961-
return Err(ChainstateError::InvalidStacksBlock(
1962-
"Does not connect to burn view of parent block ID".into(),
1963-
));
1964-
}
1965-
}
1966-
tenure_change.burn_view_consensus_hash
1967-
} else {
1968-
parent_header_info.burn_view.clone().ok_or_else(|| {
1969-
warn!(
1970-
"Cannot process Nakamoto block: parent block does not have a burnchain view and current block has no tenure tx";
1971-
"consensus_hash" => %next_ready_block.header.consensus_hash,
1972-
"stacks_block_hash" => %next_ready_block.header.block_hash(),
1973-
"stacks_block_id" => %next_ready_block.header.block_id(),
1974-
"parent_block_id" => %next_ready_block.header.parent_block_id
1975-
);
1976-
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1977-
})?
1978-
};
1990+
let burnchain_view =
1991+
Self::get_block_burn_view(sort_db, &next_ready_block, &parent_header_info)?;
19791992
let Some(burnchain_view_sn) =
19801993
SortitionDB::get_block_snapshot_consensus(sort_db.conn(), &burnchain_view)?
19811994
else {

stackslib/src/net/api/postblock_proposal.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,30 @@ impl NakamotoBlockProposal {
374374
});
375375
}
376376

377-
let sort_tip = SortitionDB::get_canonical_sortition_tip(sortdb.conn())?;
378-
let burn_dbconn: SortitionHandleConn = sortdb.index_handle(&sort_tip);
379-
let mut db_handle = sortdb.index_handle(&sort_tip);
377+
// open sortition view to the current burn view.
378+
// If the block has a TenureChange with an Extend cause, then the burn view is whatever is
379+
// indicated in the TenureChange.
380+
// Otherwise, it's the same as the block's parent's burn view.
381+
let parent_stacks_header = NakamotoChainState::get_block_header(
382+
chainstate.db(),
383+
&self.block.header.parent_block_id,
384+
)?
385+
.ok_or_else(|| BlockValidateRejectReason {
386+
reason_code: ValidateRejectCode::InvalidBlock,
387+
reason: "Invalid parent block".into(),
388+
})?;
389+
390+
let burn_view_consensus_hash =
391+
NakamotoChainState::get_block_burn_view(sortdb, &self.block, &parent_stacks_header)?;
392+
let sort_tip =
393+
SortitionDB::get_block_snapshot_consensus(sortdb.conn(), &burn_view_consensus_hash)?
394+
.ok_or_else(|| BlockValidateRejectReason {
395+
reason_code: ValidateRejectCode::NoSuchTenure,
396+
reason: "Failed to find sortition for block tenure".to_string(),
397+
})?;
398+
399+
let burn_dbconn: SortitionHandleConn = sortdb.index_handle(&sort_tip.sortition_id);
400+
let mut db_handle = sortdb.index_handle(&sort_tip.sortition_id);
380401

381402
// (For the signer)
382403
// Verify that the block's tenure is on the canonical sortition history
@@ -413,14 +434,6 @@ impl NakamotoBlockProposal {
413434
)?;
414435

415436
// Validate txs against chainstate
416-
let parent_stacks_header = NakamotoChainState::get_block_header(
417-
chainstate.db(),
418-
&self.block.header.parent_block_id,
419-
)?
420-
.ok_or_else(|| BlockValidateRejectReason {
421-
reason_code: ValidateRejectCode::InvalidBlock,
422-
reason: "Invalid parent block".into(),
423-
})?;
424437

425438
// Validate the block's timestamp. It must be:
426439
// - Greater than the parent block's timestamp

testnet/stacks-node/src/nakamoto_node/miner.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,11 @@ pub struct BlockMinerThread {
143143
registered_key: RegisteredKey,
144144
/// Burnchain block snapshot which elected this miner
145145
burn_election_block: BlockSnapshot,
146-
/// Current burnchain tip
146+
/// Current burnchain tip as of the last TenureChange
147+
/// * if the last tenure-change was a BlockFound, then this is the same as the
148+
/// `burn_election_block`.
149+
/// * otherwise, if the last tenure-change is an Extend, then this is the sortition of the burn
150+
/// view consensus hash in the TenureChange
147151
burn_block: BlockSnapshot,
148152
/// The start of the parent tenure for this tenure
149153
parent_tenure_id: StacksBlockId,

testnet/stacks-node/src/tests/signer/v0.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ fn block_proposal_rejection() {
506506
signer_test.wait_for_validate_reject_response(short_timeout, block_signer_signature_hash_2);
507507
assert!(matches!(
508508
reject.reason_code,
509-
ValidateRejectCode::UnknownParent
509+
ValidateRejectCode::InvalidBlock
510510
));
511511

512512
let start_polling = Instant::now();
@@ -532,7 +532,10 @@ fn block_proposal_rejection() {
532532
assert!(matches!(reason_code, RejectCode::SortitionViewMismatch));
533533
} else if signer_signature_hash == block_signer_signature_hash_2 {
534534
found_signer_signature_hash_2 = true;
535-
assert!(matches!(reason_code, RejectCode::ValidationFailed(_)));
535+
assert!(matches!(
536+
reason_code,
537+
RejectCode::ValidationFailed(ValidateRejectCode::InvalidBlock)
538+
));
536539
} else {
537540
continue;
538541
}

0 commit comments

Comments
 (0)