Skip to content

Commit 89d55dd

Browse files
authored
Merge branch 'develop' into feat/update-cargo-versions
2 parents e5b1fcf + 5f64d2d commit 89d55dd

File tree

28 files changed

+1107
-937
lines changed

28 files changed

+1107
-937
lines changed

.github/workflows/bitcoin-tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ jobs:
133133
- tests::signer::v0::block_validation_response_timeout
134134
- tests::signer::v0::tenure_extend_after_bad_commit
135135
- tests::signer::v0::block_proposal_max_age_rejections
136+
- tests::signer::v0::global_acceptance_depends_on_block_announcement
136137
- tests::nakamoto_integrations::burn_ops_integration_test
137138
- tests::nakamoto_integrations::check_block_heights
138139
- tests::nakamoto_integrations::clarity_burn_state
@@ -143,6 +144,7 @@ jobs:
143144
- tests::nakamoto_integrations::mock_mining
144145
- tests::nakamoto_integrations::multiple_miners
145146
- tests::nakamoto_integrations::follower_bootup_across_multiple_cycles
147+
- tests::nakamoto_integrations::nakamoto_lockup_events
146148
- tests::nakamoto_integrations::utxo_check_on_startup_panic
147149
- tests::nakamoto_integrations::utxo_check_on_startup_recover
148150
- tests::nakamoto_integrations::v3_signer_api_endpoint

.github/workflows/clippy.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
## Perform Clippy checks - currently set to defaults
2+
## https://github.com/rust-lang/rust-clippy#usage
3+
## https://rust-lang.github.io/rust-clippy/master/index.html
4+
##
5+
name: Clippy Checks
6+
7+
# Only run when:
8+
# - PRs are (re)opened against develop branch
9+
on:
10+
pull_request:
11+
branches:
12+
- develop
13+
types:
14+
- opened
15+
- reopened
16+
- synchronize
17+
18+
jobs:
19+
clippy_check:
20+
name: Clippy Check
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout the latest code
24+
id: git_checkout
25+
uses: actions/checkout@v3
26+
- name: Define Rust Toolchain
27+
id: define_rust_toolchain
28+
run: echo "RUST_TOOLCHAIN=$(cat ./rust-toolchain)" >> $GITHUB_ENV
29+
- name: Setup Rust Toolchain
30+
id: setup_rust_toolchain
31+
uses: actions-rust-lang/setup-rust-toolchain@v1
32+
with:
33+
toolchain: ${{ env.RUST_TOOLCHAIN }}
34+
components: clippy
35+
- name: Clippy
36+
id: clippy
37+
uses: actions-rs/clippy-check@v1
38+
with:
39+
token: ${{ secrets.GITHUB_TOKEN }}
40+
args: -p libstackerdb -p stacks-signer -p pox-locking --no-deps --tests --all-features -- -D warnings

CHANGELOG.md

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

1313
### Changed
1414

15+
- Nodes will assume that all PoX anchor blocks exist by default, and stall initial block download indefinitely to await their arrival (#5502)
16+
1517
## [3.1.0.0.1]
1618

1719
### Added

libsigner/src/events.rs

Lines changed: 82 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ pub enum SignerEvent<T: SignerEventTrait> {
114114
/// the time at which this event was received by the signer's event processor
115115
received_time: SystemTime,
116116
},
117+
/// A new processed Stacks block was received from the node with the given block hash
118+
NewBlock {
119+
/// The block header hash for the newly processed stacks block
120+
block_hash: Sha512Trunc256Sum,
121+
/// The block height for the newly processed stacks block
122+
block_height: u64,
123+
},
117124
}
118125

119126
/// Trait to implement a stop-signaler for the event receiver thread.
@@ -298,29 +305,25 @@ impl<T: SignerEventTrait> EventReceiver<T> for SignerEventReceiver<T> {
298305
&request.method(),
299306
)));
300307
}
308+
debug!("Processing {} event", request.url());
301309
if request.url() == "/stackerdb_chunks" {
302-
process_stackerdb_event(event_receiver.local_addr, request)
303-
.map_err(|e| {
304-
error!("Error processing stackerdb_chunks message"; "err" => ?e);
305-
e
306-
})
310+
process_event::<T, StackerDBChunksEvent>(request)
307311
} else if request.url() == "/proposal_response" {
308-
process_proposal_response(request)
312+
process_event::<T, BlockValidateResponse>(request)
309313
} else if request.url() == "/new_burn_block" {
310-
process_new_burn_block_event(request)
314+
process_event::<T, BurnBlockEvent>(request)
311315
} else if request.url() == "/shutdown" {
312316
event_receiver.stop_signal.store(true, Ordering::SeqCst);
313-
return Err(EventError::Terminated);
317+
Err(EventError::Terminated)
318+
} else if request.url() == "/new_block" {
319+
process_event::<T, BlockEvent>(request)
314320
} else {
315321
let url = request.url().to_string();
316-
// `/new_block` is expected, but not specifically handled. do not log.
317-
if &url != "/new_block" {
318-
debug!(
319-
"[{:?}] next_event got request with unexpected url {}, return OK so other side doesn't keep sending this",
320-
event_receiver.local_addr,
321-
url
322-
);
323-
}
322+
debug!(
323+
"[{:?}] next_event got request with unexpected url {}, return OK so other side doesn't keep sending this",
324+
event_receiver.local_addr,
325+
url
326+
);
324327
ack_dispatcher(request);
325328
Err(EventError::UnrecognizedEvent(url))
326329
}
@@ -385,12 +388,13 @@ fn ack_dispatcher(request: HttpRequest) {
385388

386389
// TODO: add tests from mutation testing results #4835
387390
#[cfg_attr(test, mutants::skip)]
388-
/// Process a stackerdb event from the node
389-
fn process_stackerdb_event<T: SignerEventTrait>(
390-
local_addr: Option<SocketAddr>,
391-
mut request: HttpRequest,
392-
) -> Result<SignerEvent<T>, EventError> {
391+
fn process_event<T, E>(mut request: HttpRequest) -> Result<SignerEvent<T>, EventError>
392+
where
393+
T: SignerEventTrait,
394+
E: serde::de::DeserializeOwned + TryInto<SignerEvent<T>, Error = EventError>,
395+
{
393396
let mut body = String::new();
397+
394398
if let Err(e) = request.as_reader().read_to_string(&mut body) {
395399
error!("Failed to read body: {:?}", &e);
396400
ack_dispatcher(request);
@@ -399,27 +403,12 @@ fn process_stackerdb_event<T: SignerEventTrait>(
399403
&e
400404
)));
401405
}
402-
403-
debug!("Got stackerdb_chunks event"; "chunks_event_body" => %body);
404-
let event: StackerDBChunksEvent = serde_json::from_slice(body.as_bytes())
406+
// Regardless of whether we successfully deserialize, we should ack the dispatcher so they don't keep resending it
407+
ack_dispatcher(request);
408+
let json_event: E = serde_json::from_slice(body.as_bytes())
405409
.map_err(|e| EventError::Deserialize(format!("Could not decode body to JSON: {:?}", &e)))?;
406410

407-
let event_contract_id = event.contract_id.clone();
408-
409-
let signer_event = match SignerEvent::try_from(event) {
410-
Err(e) => {
411-
info!(
412-
"[{:?}] next_event got event from an unexpected contract id {}, return OK so other side doesn't keep sending this",
413-
local_addr,
414-
event_contract_id
415-
);
416-
ack_dispatcher(request);
417-
return Err(e);
418-
}
419-
Ok(x) => x,
420-
};
421-
422-
ack_dispatcher(request);
411+
let signer_event: SignerEvent<T> = json_event.try_into()?;
423412

424413
Ok(signer_event)
425414
}
@@ -466,78 +455,69 @@ impl<T: SignerEventTrait> TryFrom<StackerDBChunksEvent> for SignerEvent<T> {
466455
}
467456
}
468457

469-
/// Process a proposal response from the node
470-
fn process_proposal_response<T: SignerEventTrait>(
471-
mut request: HttpRequest,
472-
) -> Result<SignerEvent<T>, EventError> {
473-
debug!("Got proposal_response event");
474-
let mut body = String::new();
475-
if let Err(e) = request.as_reader().read_to_string(&mut body) {
476-
error!("Failed to read body: {:?}", &e);
458+
impl<T: SignerEventTrait> TryFrom<BlockValidateResponse> for SignerEvent<T> {
459+
type Error = EventError;
477460

478-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
479-
error!("Failed to respond to request: {:?}", &e);
480-
}
481-
return Err(EventError::MalformedRequest(format!(
482-
"Failed to read body: {:?}",
483-
&e
484-
)));
461+
fn try_from(block_validate_response: BlockValidateResponse) -> Result<Self, Self::Error> {
462+
Ok(SignerEvent::BlockValidationResponse(
463+
block_validate_response,
464+
))
485465
}
466+
}
486467

487-
let event: BlockValidateResponse = serde_json::from_slice(body.as_bytes())
488-
.map_err(|e| EventError::Deserialize(format!("Could not decode body to JSON: {:?}", &e)))?;
468+
#[derive(Debug, Deserialize)]
469+
struct BurnBlockEvent {
470+
burn_block_hash: String,
471+
burn_block_height: u64,
472+
reward_recipients: Vec<serde_json::Value>,
473+
reward_slot_holders: Vec<String>,
474+
burn_amount: u64,
475+
}
489476

490-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
491-
error!("Failed to respond to request: {:?}", &e);
477+
impl<T: SignerEventTrait> TryFrom<BurnBlockEvent> for SignerEvent<T> {
478+
type Error = EventError;
479+
480+
fn try_from(burn_block_event: BurnBlockEvent) -> Result<Self, Self::Error> {
481+
let burn_header_hash = burn_block_event
482+
.burn_block_hash
483+
.get(2..)
484+
.ok_or_else(|| EventError::Deserialize("Hex string should be 0x prefixed".into()))
485+
.and_then(|hex| {
486+
BurnchainHeaderHash::from_hex(hex)
487+
.map_err(|e| EventError::Deserialize(format!("Invalid hex string: {e}")))
488+
})?;
489+
490+
Ok(SignerEvent::NewBurnBlock {
491+
burn_height: burn_block_event.burn_block_height,
492+
received_time: SystemTime::now(),
493+
burn_header_hash,
494+
})
492495
}
496+
}
493497

494-
Ok(SignerEvent::BlockValidationResponse(event))
498+
#[derive(Debug, Deserialize)]
499+
struct BlockEvent {
500+
block_hash: String,
501+
block_height: u64,
495502
}
496503

497-
/// Process a new burn block event from the node
498-
fn process_new_burn_block_event<T: SignerEventTrait>(
499-
mut request: HttpRequest,
500-
) -> Result<SignerEvent<T>, EventError> {
501-
debug!("Got burn_block event");
502-
let mut body = String::new();
503-
if let Err(e) = request.as_reader().read_to_string(&mut body) {
504-
error!("Failed to read body: {:?}", &e);
504+
impl<T: SignerEventTrait> TryFrom<BlockEvent> for SignerEvent<T> {
505+
type Error = EventError;
505506

506-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
507-
error!("Failed to respond to request: {:?}", &e);
508-
}
509-
return Err(EventError::MalformedRequest(format!(
510-
"Failed to read body: {:?}",
511-
&e
512-
)));
513-
}
514-
#[derive(Debug, Deserialize)]
515-
struct TempBurnBlockEvent {
516-
burn_block_hash: String,
517-
burn_block_height: u64,
518-
reward_recipients: Vec<serde_json::Value>,
519-
reward_slot_holders: Vec<String>,
520-
burn_amount: u64,
521-
}
522-
let temp: TempBurnBlockEvent = serde_json::from_slice(body.as_bytes())
523-
.map_err(|e| EventError::Deserialize(format!("Could not decode body to JSON: {:?}", &e)))?;
524-
let burn_header_hash = temp
525-
.burn_block_hash
526-
.get(2..)
527-
.ok_or_else(|| EventError::Deserialize("Hex string should be 0x prefixed".into()))
528-
.and_then(|hex| {
529-
BurnchainHeaderHash::from_hex(hex)
530-
.map_err(|e| EventError::Deserialize(format!("Invalid hex string: {e}")))
531-
})?;
532-
let event = SignerEvent::NewBurnBlock {
533-
burn_height: temp.burn_block_height,
534-
received_time: SystemTime::now(),
535-
burn_header_hash,
536-
};
537-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
538-
error!("Failed to respond to request: {:?}", &e);
507+
fn try_from(block_event: BlockEvent) -> Result<Self, Self::Error> {
508+
let block_hash: Sha512Trunc256Sum = block_event
509+
.block_hash
510+
.get(2..)
511+
.ok_or_else(|| EventError::Deserialize("Hex string should be 0x prefixed".into()))
512+
.and_then(|hex| {
513+
Sha512Trunc256Sum::from_hex(hex)
514+
.map_err(|e| EventError::Deserialize(format!("Invalid hex string: {e}")))
515+
})?;
516+
Ok(SignerEvent::NewBlock {
517+
block_hash,
518+
block_height: block_event.block_height,
519+
})
539520
}
540-
Ok(event)
541521
}
542522

543523
pub fn get_signers_db_signer_set_message_id(name: &str) -> Option<(u32, u32)> {

stacks-common/src/util/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ use std::path::Path;
3535
use std::time::{SystemTime, UNIX_EPOCH};
3636
use std::{error, fmt, thread, time};
3737

38+
#[cfg(any(test, feature = "testing"))]
39+
pub mod tests;
40+
3841
pub fn get_epoch_time_secs() -> u64 {
3942
let start = SystemTime::now();
4043
let since_the_epoch = start

0 commit comments

Comments
 (0)