Skip to content

Commit 08b4f28

Browse files
committed
integrate with update message
1 parent f853597 commit 08b4f28

File tree

3 files changed

+180
-68
lines changed

3 files changed

+180
-68
lines changed

libsigner/src/v0/messages.rs

Lines changed: 136 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -542,47 +542,121 @@ impl StacksMessageCodec for MockBlock {
542542
}
543543

544544
/// Message for update the Signer State infos
545-
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
545+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
546546
pub struct StateMachineUpdate {
547-
burn_block: ConsensusHash,
548-
burn_block_height: u64,
549-
current_miner_pkh: Hash160,
550-
parent_tenure_id: ConsensusHash,
551-
parent_tenure_last_block: StacksBlockId,
552-
parent_tenure_last_block_height: u64,
553-
active_signer_protocol_version: u64,
554-
local_supported_signer_protocol_version: u64,
547+
/// The tip burn block (i.e., the latest bitcoin block) seen by this signer
548+
pub burn_block: ConsensusHash,
549+
/// The tip burn block height (i.e., the latest bitcoin block) seen by this signer
550+
pub burn_block_height: u64,
551+
/// The signer's view of who the current miner should be (and their tenure building info)
552+
pub current_miner: StateMachineUpdateMinerState,
553+
/// The active signing protocol version
554+
pub active_signer_protocol_version: u64,
555+
/// The highest supported signing protocol by the local signer
556+
pub local_supported_signer_protocol_version: u64,
557+
}
558+
559+
/// Message for update the Signer State infos
560+
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
561+
pub enum StateMachineUpdateMinerState {
562+
/// There is an active miner
563+
ActiveMiner {
564+
/// The pubkeyhash of the current miner's signing key
565+
current_miner_pkh: Hash160,
566+
/// The tenure ID of the current miner's active tenure
567+
tenure_id: ConsensusHash,
568+
/// The tenure that the current miner is building on top of
569+
parent_tenure_id: ConsensusHash,
570+
/// The last block of the parent tenure (which should be
571+
/// the block that the next tenure starts from)
572+
parent_tenure_last_block: StacksBlockId,
573+
/// The height of the last block of the parent tenure (which should be
574+
/// the block that the next tenure starts from)
575+
parent_tenure_last_block_height: u64,
576+
},
577+
/// The signer doesn't believe there's any valid miner
578+
NoValidMiner,
579+
}
580+
581+
impl StateMachineUpdateMinerState {
582+
fn get_variant_id(&self) -> u8 {
583+
match self {
584+
StateMachineUpdateMinerState::NoValidMiner => 0,
585+
StateMachineUpdateMinerState::ActiveMiner { .. } => 1,
586+
}
587+
}
588+
}
589+
590+
impl StacksMessageCodec for StateMachineUpdateMinerState {
591+
fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), CodecError> {
592+
self.get_variant_id().consensus_serialize(fd)?;
593+
match self {
594+
StateMachineUpdateMinerState::ActiveMiner {
595+
current_miner_pkh,
596+
tenure_id,
597+
parent_tenure_id,
598+
parent_tenure_last_block,
599+
parent_tenure_last_block_height,
600+
} => {
601+
current_miner_pkh.consensus_serialize(fd)?;
602+
tenure_id.consensus_serialize(fd)?;
603+
parent_tenure_id.consensus_serialize(fd)?;
604+
parent_tenure_last_block.consensus_serialize(fd)?;
605+
parent_tenure_last_block_height.consensus_serialize(fd)?;
606+
}
607+
StateMachineUpdateMinerState::NoValidMiner => return Ok(()),
608+
}
609+
Ok(())
610+
}
611+
612+
fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, CodecError> {
613+
let variant_id: u8 = read_next(fd)?;
614+
match variant_id {
615+
0 => Ok(StateMachineUpdateMinerState::NoValidMiner),
616+
1 => {
617+
let current_miner_pkh = read_next(fd)?;
618+
let tenure_id = read_next(fd)?;
619+
let parent_tenure_id = read_next(fd)?;
620+
let parent_tenure_last_block = read_next(fd)?;
621+
let parent_tenure_last_block_height = read_next(fd)?;
622+
Ok(StateMachineUpdateMinerState::ActiveMiner {
623+
current_miner_pkh,
624+
tenure_id,
625+
parent_tenure_id,
626+
parent_tenure_last_block,
627+
parent_tenure_last_block_height,
628+
})
629+
}
630+
other => Err(CodecError::DeserializeError(format!(
631+
"Unexpect miner state variant in StateMachineUpdate: {other}"
632+
))),
633+
}
634+
}
555635
}
556636

557637
impl StacksMessageCodec for StateMachineUpdate {
558638
fn consensus_serialize<W: Write>(&self, fd: &mut W) -> Result<(), CodecError> {
559-
write_next(fd, &self.burn_block)?;
560-
write_next(fd, &self.burn_block_height)?;
561-
write_next(fd, &self.current_miner_pkh)?;
562-
write_next(fd, &self.parent_tenure_id)?;
563-
write_next(fd, &self.parent_tenure_last_block)?;
564-
write_next(fd, &self.parent_tenure_last_block_height)?;
565-
write_next(fd, &self.active_signer_protocol_version)?;
566-
write_next(fd, &self.local_supported_signer_protocol_version)?;
639+
self.active_signer_protocol_version
640+
.consensus_serialize(fd)?;
641+
self.local_supported_signer_protocol_version
642+
.consensus_serialize(fd)?;
643+
self.burn_block.consensus_serialize(fd)?;
644+
self.burn_block_height.consensus_serialize(fd)?;
645+
self.current_miner.consensus_serialize(fd)?;
567646
Ok(())
568647
}
569648

570649
fn consensus_deserialize<R: Read>(fd: &mut R) -> Result<Self, CodecError> {
571-
let burn_block = read_next::<ConsensusHash, _>(fd)?;
572-
let burn_block_height = read_next::<u64, _>(fd)?;
573-
let current_miner_pkh = read_next::<Hash160, _>(fd)?;
574-
let parent_tenure_id = read_next::<ConsensusHash, _>(fd)?;
575-
let parent_tenure_last_block = read_next::<StacksBlockId, _>(fd)?;
576-
let parent_tenure_last_block_height = read_next::<u64, _>(fd)?;
577-
let active_signer_protocol_version = read_next::<u64, _>(fd)?;
578-
let local_supported_signer_protocol_version = read_next::<u64, _>(fd)?;
650+
let active_signer_protocol_version = read_next(fd)?;
651+
let local_supported_signer_protocol_version = read_next(fd)?;
652+
let burn_block = read_next(fd)?;
653+
let burn_block_height = read_next(fd)?;
654+
let current_miner = read_next(fd)?;
655+
579656
Ok(Self {
580657
burn_block,
581658
burn_block_height,
582-
current_miner_pkh,
583-
parent_tenure_id,
584-
parent_tenure_last_block,
585-
parent_tenure_last_block_height,
659+
current_miner,
586660
active_signer_protocol_version,
587661
local_supported_signer_protocol_version,
588662
})
@@ -2051,72 +2125,66 @@ mod test {
20512125
let signer_message = StateMachineUpdate {
20522126
burn_block: ConsensusHash([0x55; 20]),
20532127
burn_block_height: 100,
2054-
current_miner_pkh: Hash160([0xab; 20]),
2055-
parent_tenure_id: ConsensusHash([0x22; 20]),
2056-
parent_tenure_last_block: StacksBlockId([0x33; 32]),
2057-
parent_tenure_last_block_height: 1,
20582128
active_signer_protocol_version: 2,
20592129
local_supported_signer_protocol_version: 3,
2130+
current_miner: StateMachineUpdateMinerState::ActiveMiner {
2131+
current_miner_pkh: Hash160([0xab; 20]),
2132+
tenure_id: ConsensusHash([0x44; 20]),
2133+
parent_tenure_id: ConsensusHash([0x22; 20]),
2134+
parent_tenure_last_block: StacksBlockId([0x33; 32]),
2135+
parent_tenure_last_block_height: 1,
2136+
},
20602137
};
20612138

20622139
let mut bytes = vec![];
20632140
signer_message.consensus_serialize(&mut bytes).unwrap();
20642141

20652142
// check for raw content for avoiding regressions when structure changes
20662143
let raw_signer_message: Vec<&[u8]> = vec![
2144+
/* active_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 2],
2145+
/* local_supported_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 3],
20672146
/* burn_block*/ &[0x55; 20],
20682147
/* burn_block_height*/ &[0, 0, 0, 0, 0, 0, 0, 100],
2148+
/* current_miner_variant */ &[0x01],
20692149
/* current_miner_pkh */ &[0xab; 20],
2150+
/* tenure_id*/ &[0x44; 20],
20702151
/* parent_tenure_id*/ &[0x22; 20],
20712152
/* parent_tenure_last_block */ &[0x33; 32],
20722153
/* parent_tenure_last_block_height*/ &[0, 0, 0, 0, 0, 0, 0, 1],
2073-
/* active_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 2],
2074-
/* local_supported_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 3],
20752154
];
20762155

20772156
assert_eq!(bytes, raw_signer_message.concat());
20782157

20792158
let signer_message_deserialized =
20802159
StateMachineUpdate::consensus_deserialize(&mut &bytes[..]).unwrap();
20812160

2082-
assert_eq!(
2083-
signer_message.burn_block,
2084-
signer_message_deserialized.burn_block
2085-
);
2161+
assert_eq!(signer_message, signer_message_deserialized);
20862162

2087-
assert_eq!(
2088-
signer_message.burn_block_height,
2089-
signer_message_deserialized.burn_block_height
2090-
);
2091-
2092-
assert_eq!(
2093-
signer_message.current_miner_pkh,
2094-
signer_message_deserialized.current_miner_pkh
2095-
);
2163+
let signer_message = StateMachineUpdate {
2164+
burn_block: ConsensusHash([0x55; 20]),
2165+
burn_block_height: 100,
2166+
active_signer_protocol_version: 2,
2167+
local_supported_signer_protocol_version: 3,
2168+
current_miner: StateMachineUpdateMinerState::NoValidMiner,
2169+
};
20962170

2097-
assert_eq!(
2098-
signer_message.parent_tenure_id,
2099-
signer_message_deserialized.parent_tenure_id
2100-
);
2171+
let mut bytes = vec![];
2172+
signer_message.consensus_serialize(&mut bytes).unwrap();
21012173

2102-
assert_eq!(
2103-
signer_message.parent_tenure_last_block,
2104-
signer_message_deserialized.parent_tenure_last_block
2105-
);
2174+
// check for raw content for avoiding regressions when structure changes
2175+
let raw_signer_message: Vec<&[u8]> = vec![
2176+
/* active_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 2],
2177+
/* local_supported_signer_protocol_version*/ &[0, 0, 0, 0, 0, 0, 0, 3],
2178+
/* burn_block*/ &[0x55; 20],
2179+
/* burn_block_height*/ &[0, 0, 0, 0, 0, 0, 0, 100],
2180+
/* current_miner_variant */ &[0x00],
2181+
];
21062182

2107-
assert_eq!(
2108-
signer_message.parent_tenure_last_block_height,
2109-
signer_message_deserialized.parent_tenure_last_block_height
2110-
);
2183+
assert_eq!(bytes, raw_signer_message.concat());
21112184

2112-
assert_eq!(
2113-
signer_message.active_signer_protocol_version,
2114-
signer_message_deserialized.active_signer_protocol_version
2115-
);
2185+
let signer_message_deserialized =
2186+
StateMachineUpdate::consensus_deserialize(&mut &bytes[..]).unwrap();
21162187

2117-
assert_eq!(
2118-
signer_message.local_supported_signer_protocol_version,
2119-
signer_message_deserialized.local_supported_signer_protocol_version
2120-
);
2188+
assert_eq!(signer_message, signer_message_deserialized);
21212189
}
21222190
}

stacks-signer/src/chainstate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ pub enum SignerChainstateError {
4242
/// The signer could not find information about the parent tenure
4343
#[error("No information available for parent tenure '{0}'")]
4444
NoParentTenureInfo(ConsensusHash),
45+
/// The signer could not find information about the parent tenure
46+
#[error("The local state machine is not ready, so no update message can be produced")]
47+
LocalStateMachineNotReady,
4548
}
4649

4750
impl From<SignerChainstateError> for RejectReason {

stacks-signer/src/v0/signer_state.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ use std::time::{Duration, UNIX_EPOCH};
1717

1818
use blockstack_lib::chainstate::burn::ConsensusHashExtensions;
1919
use blockstack_lib::chainstate::nakamoto::{NakamotoBlock, NakamotoBlockHeader};
20+
use libsigner::v0::messages::{
21+
StateMachineUpdate as StateMachineUpdateMessage, StateMachineUpdateMinerState,
22+
};
2023
use serde::{Deserialize, Serialize};
2124
use slog::{slog_info, slog_warn};
2225
use stacks_common::bitvec::BitVec;
@@ -31,6 +34,9 @@ use crate::chainstate::{
3134
use crate::client::{ClientError, CurrentAndLastSortition, StacksClient};
3235
use crate::signerdb::SignerDb;
3336

37+
/// This is the latest supported protocol version for this signer binary
38+
pub static SUPPORTED_SIGNER_PROTOCOL_VERSION: u64 = 1;
39+
3440
/// A signer state machine view. This struct can
3541
/// be used to encode the local signer's view or
3642
/// the global view.
@@ -93,6 +99,41 @@ pub enum StateMachineUpdate {
9399
BurnBlock(u64),
94100
}
95101

102+
impl TryInto<StateMachineUpdateMessage> for &LocalStateMachine {
103+
type Error = SignerChainstateError;
104+
105+
fn try_into(self) -> Result<StateMachineUpdateMessage, Self::Error> {
106+
let LocalStateMachine::Initialized(state_machine) = self else {
107+
return Err(SignerChainstateError::LocalStateMachineNotReady);
108+
};
109+
110+
let current_miner = match state_machine.current_miner {
111+
MinerState::ActiveMiner {
112+
current_miner_pkh,
113+
tenure_id,
114+
parent_tenure_id,
115+
parent_tenure_last_block,
116+
parent_tenure_last_block_height,
117+
} => StateMachineUpdateMinerState::ActiveMiner {
118+
current_miner_pkh,
119+
tenure_id,
120+
parent_tenure_id,
121+
parent_tenure_last_block,
122+
parent_tenure_last_block_height,
123+
},
124+
MinerState::NoValidMiner => StateMachineUpdateMinerState::NoValidMiner,
125+
};
126+
127+
Ok(StateMachineUpdateMessage {
128+
burn_block: state_machine.burn_block,
129+
burn_block_height: state_machine.burn_block_height,
130+
current_miner,
131+
active_signer_protocol_version: state_machine.active_signer_protocol_version,
132+
local_supported_signer_protocol_version: SUPPORTED_SIGNER_PROTOCOL_VERSION,
133+
})
134+
}
135+
}
136+
96137
impl LocalStateMachine {
97138
/// Initialize a local state machine by querying the local stacks-node
98139
/// and signerdb for the current sortition information

0 commit comments

Comments
 (0)