Skip to content

Commit f2f16c0

Browse files
authored
Merge branch 'develop' into fix/5193-stackerdb-decoherence
2 parents 3d1e690 + 02054f6 commit f2f16c0

File tree

18 files changed

+557
-69
lines changed

18 files changed

+557
-69
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ jobs:
8181
- tests::epoch_25::microblocks_disabled
8282
- tests::should_succeed_handling_malformed_and_valid_txs
8383
- tests::nakamoto_integrations::simple_neon_integration
84+
- tests::nakamoto_integrations::simple_neon_integration_with_flash_blocks_on_epoch_3
8485
- tests::nakamoto_integrations::mine_multiple_per_tenure_integration
8586
- tests::nakamoto_integrations::block_proposal_api_endpoint
8687
- tests::nakamoto_integrations::miner_writes_proposed_block_to_stackerdb

clarity/src/vm/docs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1831,7 +1831,7 @@ and block times are accurate only to within two hours. See [BIP113](https://gith
18311831
For a block mined after epoch 3.0, this timestamp comes from the Stacks block header. **Note**: this is the time, according to the miner, when
18321832
the mining of this block started, but is not guaranteed to be accurate. This time will be validated by the signers to be:
18331833
- Greater than the timestamp of the previous block
1834-
- Less than 15 seconds into the future (according to their own local clocks)
1834+
- At most 15 seconds into the future (according to their own local clocks)
18351835
",
18361836
example: "(get-stacks-block-info? time u0) ;; Returns (some u1557860301)
18371837
(get-stacks-block-info? header-hash u0) ;; Returns (some 0x374708fff7719dd5979ec875d56cd2286f6d3cf7ec317a3b25632aab28ec37bb)

contrib/tools/relay-server/src/http.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use crate::to_io_result::ToIoResult;
88
pub struct Request {
99
pub method: String,
1010
pub url: String,
11+
#[allow(dead_code)]
1112
pub protocol: String,
13+
#[allow(dead_code)]
1214
pub headers: HashMap<String, String>,
1315
pub content: Vec<u8>,
1416
}

stacks-common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ testing = ["canonical"]
7878
serde = []
7979
bech32_std = []
8080
bech32_strict = []
81+
strason = []
8182

8283
[target.'cfg(all(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"), not(any(target_os="windows"))))'.dependencies]
8384
sha2 = { version = "0.10", features = ["asm"] }

stacks-signer/src/v0/signer.rs

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,14 @@ impl SignerTrait<SignerMessage> for Signer {
185185
);
186186
}
187187
SignerMessage::BlockPushed(b) => {
188+
let block_push_result = stacks_client.post_block(b);
189+
if let Err(ref e) = &block_push_result {
190+
warn!(
191+
"{self}: Failed to post block {} (id {}): {e:?}",
192+
&b.header.signer_signature_hash(),
193+
&b.block_id()
194+
);
195+
};
188196
// This will infinitely loop until the block is acknowledged by the node
189197
info!(
190198
"{self}: Got block pushed message";
@@ -235,17 +243,17 @@ impl SignerTrait<SignerMessage> for Signer {
235243
received_time,
236244
} => {
237245
info!("{self}: Received a new burn block event for block height {burn_height}");
238-
if let Err(e) =
239-
self.signer_db
240-
.insert_burn_block(burn_header_hash, *burn_height, received_time)
241-
{
242-
warn!(
243-
"Failed to write burn block event to signerdb";
244-
"err" => ?e,
245-
"burn_header_hash" => %burn_header_hash,
246-
"burn_height" => burn_height
247-
);
248-
}
246+
self.signer_db
247+
.insert_burn_block(burn_header_hash, *burn_height, received_time)
248+
.unwrap_or_else(|e| {
249+
error!(
250+
"Failed to write burn block event to signerdb";
251+
"err" => ?e,
252+
"burn_header_hash" => %burn_header_hash,
253+
"burn_height" => burn_height
254+
);
255+
panic!("{self} Failed to write burn block event to signerdb: {e}");
256+
});
249257
*sortition_state = None;
250258
}
251259
}
@@ -774,7 +782,8 @@ impl Signer {
774782
warn!("{self}: Failed to mark block as globally rejected: {e:?}",);
775783
}
776784
if let Err(e) = self.signer_db.insert_block(&block_info) {
777-
warn!("{self}: Failed to update block state: {e:?}",);
785+
error!("{self}: Failed to update block state: {e:?}",);
786+
panic!("{self} Failed to update block state: {e}");
778787
}
779788
}
780789

@@ -895,7 +904,7 @@ impl Signer {
895904
"Failed to set group threshold signature timestamp for {}: {:?}",
896905
block_hash, &e
897906
);
898-
e
907+
panic!("{self} Failed to write block to signerdb: {e}");
899908
});
900909
#[cfg(any(test, feature = "testing"))]
901910
{
@@ -935,24 +944,8 @@ impl Signer {
935944
block.header.signer_signature = signatures;
936945

937946
#[cfg(any(test, feature = "testing"))]
938-
{
939-
if *TEST_SKIP_BLOCK_BROADCAST.lock().unwrap() == Some(true) {
940-
warn!(
941-
"{self}: Skipping block broadcast due to testing directive";
942-
"block_id" => %block.block_id(),
943-
"height" => block.header.chain_length,
944-
"consensus_hash" => %block.header.consensus_hash
945-
);
946-
947-
if let Err(e) = self.signer_db.set_block_broadcasted(
948-
self.reward_cycle,
949-
&block_hash,
950-
get_epoch_time_secs(),
951-
) {
952-
warn!("{self}: Failed to set block broadcasted for {block_hash}: {e:?}");
953-
}
954-
return;
955-
}
947+
if self.test_skip_block_broadcast(&block) {
948+
return;
956949
}
957950
debug!(
958951
"{self}: Broadcasting Stacks block {} to node",
@@ -977,6 +970,29 @@ impl Signer {
977970
}
978971
}
979972

973+
#[cfg(any(test, feature = "testing"))]
974+
fn test_skip_block_broadcast(&self, block: &NakamotoBlock) -> bool {
975+
if *TEST_SKIP_BLOCK_BROADCAST.lock().unwrap() == Some(true) {
976+
let block_hash = block.header.signer_signature_hash();
977+
warn!(
978+
"{self}: Skipping block broadcast due to testing directive";
979+
"block_id" => %block.block_id(),
980+
"height" => block.header.chain_length,
981+
"consensus_hash" => %block.header.consensus_hash
982+
);
983+
984+
if let Err(e) = self.signer_db.set_block_broadcasted(
985+
self.reward_cycle,
986+
&block_hash,
987+
get_epoch_time_secs(),
988+
) {
989+
warn!("{self}: Failed to set block broadcasted for {block_hash}: {e:?}");
990+
}
991+
return true;
992+
}
993+
false
994+
}
995+
980996
/// Send a mock signature to stackerdb to prove we are still alive
981997
fn mock_sign(&mut self, mock_proposal: MockProposal) {
982998
info!("{self}: Mock signing mock proposal: {mock_proposal:?}");

stacks-signer/src/v1/signer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,13 @@ impl SignerTrait<SignerMessage> for Signer {
239239
self.signer_db
240240
.insert_burn_block(burn_header_hash, *burn_height, received_time)
241241
{
242-
warn!(
242+
error!(
243243
"Failed to write burn block event to signerdb";
244244
"err" => ?e,
245245
"burn_header_hash" => %burn_header_hash,
246246
"burn_height" => burn_height
247247
);
248+
panic!("Failed to write burn block event to signerdb");
248249
}
249250
}
250251
}

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ const SORTITION_DB_INITIAL_SCHEMA: &'static [&'static str] = &[
574574
block_height INTEGER NOT NULL,
575575
burn_header_hash TEXT NOT NULL,
576576
sortition_id TEXT NOT NULL,
577-
577+
578578
consensus_hash TEXT NOT NULL,
579579
public_key TEXT NOT NULL,
580580
memo TEXT,
@@ -619,7 +619,7 @@ const SORTITION_DB_INITIAL_SCHEMA: &'static [&'static str] = &[
619619
stacked_ustx TEXT NOT NULL,
620620
num_cycles INTEGER NOT NULL,
621621
622-
-- The primary key here is (txid, burn_header_hash) because
622+
-- The primary key here is (txid, burn_header_hash) because
623623
-- this transaction will be accepted regardless of which sortition
624624
-- history it is in.
625625
PRIMARY KEY(txid,burn_header_hash)
@@ -636,7 +636,7 @@ const SORTITION_DB_INITIAL_SCHEMA: &'static [&'static str] = &[
636636
transfered_ustx TEXT NOT NULL,
637637
memo TEXT NOT NULL,
638638
639-
-- The primary key here is (txid, burn_header_hash) because
639+
-- The primary key here is (txid, burn_header_hash) because
640640
-- this transaction will be accepted regardless of which sortition
641641
-- history it is in.
642642
PRIMARY KEY(txid,burn_header_hash)
@@ -687,11 +687,11 @@ const SORTITION_DB_SCHEMA_4: &'static [&'static str] = &[
687687
delegated_ustx TEXT NOT NULL,
688688
until_burn_height INTEGER,
689689
690-
PRIMARY KEY(txid,burn_header_Hash)
690+
PRIMARY KEY(txid,burn_header_hash)
691691
);"#,
692692
r#"
693693
CREATE TABLE ast_rule_heights (
694-
ast_rule_id INTEGER PRIMAR KEY NOT NULL,
694+
ast_rule_id INTEGER PRIMARY KEY NOT NULL,
695695
block_height INTEGER NOT NULL
696696
);"#,
697697
];
@@ -2261,7 +2261,7 @@ impl<'a> SortitionHandleConn<'a> {
22612261

22622262
/// Get a block commit by txid. In the event of a burnchain fork, this may not be unique.
22632263
/// this function simply returns one of those block commits: only use data that is
2264-
/// immutable across burnchain/pox forks, e.g., parent block ptr,
2264+
/// immutable across burnchain/pox forks, e.g., parent block ptr,
22652265
pub fn get_block_commit_by_txid(
22662266
&self,
22672267
sort_id: &SortitionId,
@@ -2909,7 +2909,6 @@ impl SortitionDB {
29092909
SortitionDB::apply_schema_6(&db_tx, epochs_ref)?;
29102910
SortitionDB::apply_schema_7(&db_tx, epochs_ref)?;
29112911
SortitionDB::apply_schema_8_tables(&db_tx, epochs_ref)?;
2912-
SortitionDB::apply_schema_9(&db_tx, epochs_ref)?;
29132912

29142913
db_tx.instantiate_index()?;
29152914

@@ -2930,6 +2929,11 @@ impl SortitionDB {
29302929
// NOTE: we don't need to provide a migrator here because we're not migrating
29312930
self.apply_schema_8_migration(None)?;
29322931

2932+
let db_tx = SortitionHandleTx::begin(self, &SortitionId::sentinel())?;
2933+
SortitionDB::apply_schema_9(&db_tx, epochs_ref)?;
2934+
2935+
db_tx.commit()?;
2936+
29332937
self.add_indexes()?;
29342938

29352939
debug!("Instantiated SortDB");
@@ -5046,7 +5050,7 @@ impl SortitionDB {
50465050
conn: &Connection,
50475051
sortition: &SortitionId,
50485052
) -> Result<Option<u16>, db_error> {
5049-
let qry = "SELECT vtxindex FROM block_commits WHERE sortition_id = ?1
5053+
let qry = "SELECT vtxindex FROM block_commits WHERE sortition_id = ?1
50505054
AND txid = (
50515055
SELECT winning_block_txid FROM snapshots WHERE sortition_id = ?2 LIMIT 1) LIMIT 1";
50525056
let args = params![sortition, sortition];

stackslib/src/chainstate/nakamoto/miner.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl NakamotoTenureInfo {
108108
}
109109

110110
pub struct NakamotoBlockBuilder {
111-
/// If there's a parent (i.e., not a genesis), this is Some(parent_header)
111+
/// If there's a parent (i.e., not a genesis), this is Some(parent_header)
112112
parent_header: Option<StacksHeaderInfo>,
113113
/// Signed coinbase tx, if starting a new tenure
114114
coinbase_tx: Option<StacksTransaction>,
@@ -280,8 +280,11 @@ impl NakamotoBlockBuilder {
280280
&self.header.parent_block_id,
281281
).map_err(|e| {
282282
warn!(
283-
"Cannot process Nakamoto block: could not load reward set that elected the block";
283+
"Cannot process Nakamoto block: could not find height at which the PoX reward set was calculated";
284284
"err" => ?e,
285+
"stacks_tip" => %self.header.parent_block_id,
286+
"elected_height" => elected_height,
287+
"elected_cycle" => elected_in_cycle
285288
);
286289
Error::NoSuchBlockError
287290
})?;

stackslib/src/chainstate/nakamoto/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ pub struct NakamotoBlockHeader {
612612
/// A Unix time timestamp of when this block was mined, according to the miner.
613613
/// For the signers to consider a block valid, this timestamp must be:
614614
/// * Greater than the timestamp of its parent block
615-
/// * Less than 15 seconds into the future
615+
/// * At most 15 seconds into the future
616616
pub timestamp: u64,
617617
/// Recoverable ECDSA signature from the tenure's miner.
618618
pub miner_signature: MessageSignature,
@@ -734,6 +734,7 @@ impl NakamotoBlockHeader {
734734
write_next(fd, &self.tx_merkle_root)?;
735735
write_next(fd, &self.state_index_root)?;
736736
write_next(fd, &self.timestamp)?;
737+
write_next(fd, &self.pox_treatment)?;
737738
Ok(Sha512Trunc256Sum::from_hasher(hasher))
738739
}
739740

@@ -1876,7 +1877,7 @@ impl NakamotoChainState {
18761877
"stacks_block_id" => %next_ready_block.header.block_id(),
18771878
"parent_block_id" => %next_ready_block.header.parent_block_id
18781879
);
1879-
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1880+
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
18801881
})?;
18811882
let handle = sort_db.index_handle_at_ch(&tenure_change.burn_view_consensus_hash)?;
18821883
let connected_sort_id = get_ancestor_sort_id(&handle, parent_burn_view_sn.block_height, &handle.context.chain_tip)?
@@ -1888,7 +1889,7 @@ impl NakamotoChainState {
18881889
"stacks_block_id" => %next_ready_block.header.block_id(),
18891890
"parent_block_id" => %next_ready_block.header.parent_block_id
18901891
);
1891-
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
1892+
ChainstateError::InvalidStacksBlock("Failed to load burn view of parent block ID".into())
18921893
})?;
18931894
if connected_sort_id != parent_burn_view_sn.sortition_id {
18941895
warn!(
@@ -3608,7 +3609,7 @@ impl NakamotoChainState {
36083609
.map_err(|_| ChainstateError::InvalidStacksBlock("Reward set index outside of u16".into()))?;
36093610
let bitvec_value = block_bitvec.get(ix)
36103611
.unwrap_or_else(|| {
3611-
info!("Block header's bitvec is smaller than the reward set, defaulting higher indexes to 1");
3612+
warn!("Block header's bitvec is smaller than the reward set, defaulting higher indexes to 1");
36123613
true
36133614
});
36143615
Ok(bitvec_value)

0 commit comments

Comments
 (0)