Skip to content

Commit 0703596

Browse files
authored
Merge branch 'develop' into fix/5044
2 parents 5e75e95 + f3f2e57 commit 0703596

File tree

18 files changed

+555
-68
lines changed

18 files changed

+555
-68
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: 2 additions & 2 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,
@@ -3629,7 +3629,7 @@ impl NakamotoChainState {
36293629
.map_err(|_| ChainstateError::InvalidStacksBlock("Reward set index outside of u16".into()))?;
36303630
let bitvec_value = block_bitvec.get(ix)
36313631
.unwrap_or_else(|| {
3632-
info!("Block header's bitvec is smaller than the reward set, defaulting higher indexes to 1");
3632+
warn!("Block header's bitvec is smaller than the reward set, defaulting higher indexes to 1");
36333633
true
36343634
});
36353635
Ok(bitvec_value)

stackslib/src/chainstate/nakamoto/staging_blocks.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use crate::chainstate::stacks::{Error as ChainstateError, StacksBlock, StacksBlo
3535
use crate::stacks_common::codec::StacksMessageCodec;
3636
use crate::util_lib::db::{
3737
query_int, query_row, query_row_columns, query_row_panic, query_rows, sqlite_open,
38-
tx_begin_immediate, u64_to_sql, DBConn, Error as DBError, FromRow,
38+
table_exists, tx_begin_immediate, u64_to_sql, DBConn, Error as DBError, FromRow,
3939
};
4040

4141
/// The means by which a block is obtained.
@@ -88,7 +88,7 @@ pub const NAKAMOTO_STAGING_DB_SCHEMA_1: &'static [&'static str] = &[
8888
8989
-- block data, including its header
9090
data BLOB NOT NULL,
91-
91+
9292
PRIMARY KEY(block_hash,consensus_hash)
9393
);"#,
9494
r#"CREATE INDEX nakamoto_staging_blocks_by_index_block_hash ON nakamoto_staging_blocks(index_block_hash);"#,
@@ -136,7 +136,7 @@ pub const NAKAMOTO_STAGING_DB_SCHEMA_2: &'static [&'static str] = &[
136136
137137
-- block data, including its header
138138
data BLOB NOT NULL,
139-
139+
140140
PRIMARY KEY(block_hash,consensus_hash)
141141
);"#,
142142
r#"CREATE INDEX nakamoto_staging_blocks_by_index_block_hash ON nakamoto_staging_blocks(index_block_hash);"#,
@@ -149,6 +149,8 @@ pub const NAKAMOTO_STAGING_DB_SCHEMA_2: &'static [&'static str] = &[
149149
r#"INSERT INTO db_version (version) VALUES (2)"#,
150150
];
151151

152+
pub const NAKAMOTO_STAGING_DB_SCHEMA_LATEST: u32 = 2;
153+
152154
pub struct NakamotoStagingBlocksConn(rusqlite::Connection);
153155

154156
impl Deref for NakamotoStagingBlocksConn {
@@ -527,7 +529,7 @@ impl<'a> NakamotoStagingBlocksTx<'a> {
527529
processed_time,
528530
obtain_method,
529531
signing_weight,
530-
532+
531533
data
532534
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)",
533535
params![
@@ -594,7 +596,13 @@ impl<'a> NakamotoStagingBlocksTx<'a> {
594596
obtain_method: NakamotoBlockObtainMethod,
595597
) -> Result<(), ChainstateError> {
596598
self.execute("UPDATE nakamoto_staging_blocks SET data = ?1, signing_weight = ?2, obtain_method = ?3 WHERE consensus_hash = ?4 AND block_hash = ?5",
597-
params![&block.serialize_to_vec(), &signing_weight, &obtain_method.to_string(), &block.header.consensus_hash, &block.header.block_hash()])?;
599+
params![
600+
&block.serialize_to_vec(),
601+
&signing_weight,
602+
&obtain_method.to_string(),
603+
&block.header.consensus_hash,
604+
&block.header.block_hash(),
605+
])?;
598606
Ok(())
599607
}
600608
}
@@ -658,13 +666,17 @@ impl StacksChainState {
658666
pub fn get_nakamoto_staging_blocks_db_version(
659667
conn: &Connection,
660668
) -> Result<u32, ChainstateError> {
669+
let db_version_exists = table_exists(&conn, "db_version")?;
670+
if !db_version_exists {
671+
return Ok(1);
672+
}
661673
let qry = "SELECT version FROM db_version ORDER BY version DESC LIMIT 1";
662674
let args = NO_PARAMS;
663675
let version: Option<i64> = match query_row(&conn, qry, args) {
664676
Ok(x) => x,
665677
Err(e) => {
666-
debug!("Failed to get Nakamoto staging blocks DB version: {:?}", &e);
667-
return Ok(1);
678+
error!("Failed to get Nakamoto staging blocks DB version: {:?}", &e);
679+
return Err(ChainstateError::DBError(DBError::Corruption));
668680
}
669681
};
670682

@@ -675,8 +687,8 @@ impl StacksChainState {
675687
Ok(ver)
676688
}
677689
None => {
678-
debug!("No version present in Nakamoto staging blocks DB; defaulting to 1");
679-
Ok(1)
690+
error!("No version present in Nakamoto staging blocks `db_version` table");
691+
Err(ChainstateError::DBError(DBError::Corruption))
680692
}
681693
}
682694
}

0 commit comments

Comments
 (0)