Skip to content

Commit 1855264

Browse files
committed
Add SignerEvent::NewNakamotoBlock and do not update a block to GloballyAccepted until node processes the new block successfully
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent 7267cd0 commit 1855264

File tree

3 files changed

+88
-28
lines changed

3 files changed

+88
-28
lines changed

libsigner/src/events.rs

Lines changed: 56 additions & 20 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 Nakamoto block was received from the node with the given block hash
118+
NewNakamotoBlock {
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.
@@ -311,16 +318,15 @@ impl<T: SignerEventTrait> EventReceiver<T> for SignerEventReceiver<T> {
311318
} else if request.url() == "/shutdown" {
312319
event_receiver.stop_signal.store(true, Ordering::SeqCst);
313320
return Err(EventError::Terminated);
321+
} else if request.url() == "/new_block" {
322+
process_new_block(request)
314323
} else {
315324
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-
}
325+
debug!(
326+
"[{:?}] next_event got request with unexpected url {}, return OK so other side doesn't keep sending this",
327+
event_receiver.local_addr,
328+
url
329+
);
324330
ack_dispatcher(request);
325331
Err(EventError::UnrecognizedEvent(url))
326332
}
@@ -475,9 +481,7 @@ fn process_proposal_response<T: SignerEventTrait>(
475481
if let Err(e) = request.as_reader().read_to_string(&mut body) {
476482
error!("Failed to read body: {:?}", &e);
477483

478-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
479-
error!("Failed to respond to request: {:?}", &e);
480-
}
484+
ack_dispatcher(request);
481485
return Err(EventError::MalformedRequest(format!(
482486
"Failed to read body: {:?}",
483487
&e
@@ -487,10 +491,7 @@ fn process_proposal_response<T: SignerEventTrait>(
487491
let event: BlockValidateResponse = serde_json::from_slice(body.as_bytes())
488492
.map_err(|e| EventError::Deserialize(format!("Could not decode body to JSON: {:?}", &e)))?;
489493

490-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
491-
error!("Failed to respond to request: {:?}", &e);
492-
}
493-
494+
ack_dispatcher(request);
494495
Ok(SignerEvent::BlockValidationResponse(event))
495496
}
496497

@@ -503,9 +504,7 @@ fn process_new_burn_block_event<T: SignerEventTrait>(
503504
if let Err(e) = request.as_reader().read_to_string(&mut body) {
504505
error!("Failed to read body: {:?}", &e);
505506

506-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
507-
error!("Failed to respond to request: {:?}", &e);
508-
}
507+
ack_dispatcher(request);
509508
return Err(EventError::MalformedRequest(format!(
510509
"Failed to read body: {:?}",
511510
&e
@@ -534,9 +533,46 @@ fn process_new_burn_block_event<T: SignerEventTrait>(
534533
received_time: SystemTime::now(),
535534
burn_header_hash,
536535
};
537-
if let Err(e) = request.respond(HttpResponse::empty(200u16)) {
538-
error!("Failed to respond to request: {:?}", &e);
536+
ack_dispatcher(request);
537+
Ok(event)
538+
}
539+
540+
/// Process a new burn block event from the node
541+
fn process_new_block<T: SignerEventTrait>(
542+
mut request: HttpRequest,
543+
) -> Result<SignerEvent<T>, EventError> {
544+
debug!("Got new_block event");
545+
let mut body = String::new();
546+
if let Err(e) = request.as_reader().read_to_string(&mut body) {
547+
error!("Failed to read body: {:?}", &e);
548+
549+
ack_dispatcher(request);
550+
return Err(EventError::MalformedRequest(format!(
551+
"Failed to read body: {:?}",
552+
&e
553+
)));
554+
}
555+
#[derive(Debug, Deserialize)]
556+
struct TempBlockEvent {
557+
block_hash: String,
558+
block_height: u64,
539559
}
560+
561+
let temp: TempBlockEvent = serde_json::from_slice(body.as_bytes())
562+
.map_err(|e| EventError::Deserialize(format!("Could not decode body to JSON: {:?}", &e)))?;
563+
let block_hash: Sha512Trunc256Sum = temp
564+
.block_hash
565+
.get(2..)
566+
.ok_or_else(|| EventError::Deserialize("Hex string should be 0x prefixed".into()))
567+
.and_then(|hex| {
568+
Sha512Trunc256Sum::from_hex(hex)
569+
.map_err(|e| EventError::Deserialize(format!("Invalid hex string: {e}")))
570+
})?;
571+
let event = SignerEvent::NewNakamotoBlock {
572+
block_hash,
573+
block_height: temp.block_height,
574+
};
575+
ack_dispatcher(request);
540576
Ok(event)
541577
}
542578

stacks-signer/src/signerdb.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -811,13 +811,8 @@ impl SignerDb {
811811
block_sighash: &Sha512Trunc256Sum,
812812
ts: u64,
813813
) -> Result<(), DBError> {
814-
let qry = "UPDATE blocks SET broadcasted = ?1, block_info = json_set(block_info, '$.state', ?2) WHERE reward_cycle = ?3 AND signer_signature_hash = ?4";
815-
let args = params![
816-
u64_to_sql(ts)?,
817-
BlockState::GloballyAccepted.to_string(),
818-
u64_to_sql(reward_cycle)?,
819-
block_sighash
820-
];
814+
let qry = "UPDATE blocks SET broadcasted = ?1 WHERE reward_cycle = ?2 AND signer_signature_hash = ?3";
815+
let args = params![u64_to_sql(ts)?, u64_to_sql(reward_cycle)?, block_sighash];
821816

822817
debug!("Marking block {} as broadcasted at {}", block_sighash, ts);
823818
self.db.execute(qry, args)?;
@@ -872,6 +867,7 @@ where
872867
}
873868

874869
#[cfg(test)]
870+
/// Create a test signer db
875871
pub fn test_signer_db(db_path: &str) -> SignerDb {
876872
use std::fs;
877873

@@ -1220,7 +1216,7 @@ mod tests {
12201216
.expect("Unable to get block from db")
12211217
.expect("Unable to get block from db")
12221218
.state,
1223-
BlockState::GloballyAccepted
1219+
BlockState::Unprocessed
12241220
);
12251221
db.insert_block(&block_info_1)
12261222
.expect("Unable to insert block into db a second time");

stacks-signer/src/v0/signer.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ impl SignerTrait<SignerMessage> for Signer {
126126
Some(SignerEvent::BlockValidationResponse(_))
127127
| Some(SignerEvent::MinerMessages(..))
128128
| Some(SignerEvent::NewBurnBlock { .. })
129+
| Some(SignerEvent::NewNakamotoBlock { .. })
129130
| Some(SignerEvent::StatusCheck)
130131
| None => None,
131132
Some(SignerEvent::SignerMessages(msg_parity, ..)) => Some(u64::from(*msg_parity) % 2),
@@ -246,6 +247,33 @@ impl SignerTrait<SignerMessage> for Signer {
246247
});
247248
*sortition_state = None;
248249
}
250+
SignerEvent::NewNakamotoBlock {
251+
block_hash,
252+
block_height,
253+
} => {
254+
debug!(
255+
"{self}: Received a new block event.";
256+
"block_hash" => %block_hash,
257+
"block_height" => block_height
258+
);
259+
if let Ok(Some(mut block_info)) = self
260+
.signer_db
261+
.block_lookup(self.reward_cycle, block_hash)
262+
.inspect_err(|e| warn!("{self}: Failed to load block state: {e:?}"))
263+
{
264+
if block_info.state == BlockState::GloballyAccepted {
265+
// We have already globally accepted this block. Do nothing.
266+
return;
267+
}
268+
if let Err(e) = block_info.mark_globally_accepted() {
269+
warn!("{self}: Failed to mark block as globally accepted: {e:?}");
270+
return;
271+
}
272+
if let Err(e) = self.signer_db.insert_block(&block_info) {
273+
warn!("{self}: Failed to update block state to globally accepted: {e:?}");
274+
}
275+
}
276+
}
249277
}
250278
}
251279

0 commit comments

Comments
 (0)