Skip to content

Commit 9ef0747

Browse files
committed
Add a test for determining the latest supported signer protocol version
Signed-off-by: Jacinta Ferrant <[email protected]>
1 parent d12fb82 commit 9ef0747

File tree

1 file changed

+126
-4
lines changed

1 file changed

+126
-4
lines changed

stacks-signer/src/v0/signer_state.rs

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ impl GlobalStateEvaluator {
6767
}
6868
}
6969

70-
/// Determine what the active signer protocol version should be
71-
fn determine_active_signer_protocol_version(
70+
/// Determine what the maximum signer protocol version that a majority of signers can support
71+
fn determine_latest_supported_signer_protocol_version(
7272
&mut self,
7373
local_address: StacksAddress,
7474
local_update: StateMachineUpdateMessage,
@@ -131,7 +131,7 @@ impl GlobalStateEvaluator {
131131
local_update: StateMachineUpdateMessage,
132132
) -> Option<SignerStateMachine> {
133133
let active_signer_protocol_version =
134-
self.determine_active_signer_protocol_version(local_address, local_update)?;
134+
self.determine_latest_supported_signer_protocol_version(local_address, local_update)?;
135135
let mut state_views = HashMap::new();
136136
for (address, update) in &self.address_updates {
137137
let Some(weight) = self.address_weights.get(address) else {
@@ -792,7 +792,7 @@ impl LocalStateMachine {
792792
let old_protocol_version = local_update.active_signer_protocol_version;
793793
// First check if we should update our active protocol version
794794
let active_signer_protocol_version = eval
795-
.determine_active_signer_protocol_version(local_address, local_update.clone())
795+
.determine_latest_supported_signer_protocol_version(local_address, local_update.clone())
796796
.unwrap_or(old_protocol_version);
797797

798798
let StateMachineUpdateContent::V0 {
@@ -846,3 +846,125 @@ impl LocalStateMachine {
846846
}
847847
}
848848
}
849+
850+
/// Tests for SignerDb
851+
#[cfg(test)]
852+
mod tests {
853+
use clarity::types::chainstate::{StacksBlockId, StacksPrivateKey, StacksPublicKey};
854+
use clarity::util::hash::Hash160;
855+
use libsigner::v0::messages::{StateMachineUpdateContent, StateMachineUpdateMinerState};
856+
857+
use super::*;
858+
859+
fn generate_random_address_with_equal_weights(
860+
num_addresses: u32,
861+
) -> HashMap<StacksAddress, u32> {
862+
let mut address_weights = HashMap::new();
863+
for _ in 0..num_addresses {
864+
let stacks_address = StacksAddress::p2pkh(
865+
false,
866+
&StacksPublicKey::from_private(&StacksPrivateKey::random()),
867+
);
868+
address_weights.insert(stacks_address, 10);
869+
}
870+
address_weights
871+
}
872+
873+
#[test]
874+
fn determine_latest_supported_signer_protocol_versions() {
875+
let address_weights = generate_random_address_with_equal_weights(5);
876+
let active_protocol_version = 0;
877+
let local_supported_signer_protocol_version = 1;
878+
879+
let addresses: Vec<_> = address_weights.keys().cloned().collect();
880+
let local_address = addresses[0];
881+
882+
let local_update = StateMachineUpdateMessage::new(
883+
active_protocol_version,
884+
local_supported_signer_protocol_version,
885+
StateMachineUpdateContent::V0 {
886+
burn_block: ConsensusHash([0x55; 20]),
887+
burn_block_height: 100,
888+
current_miner: StateMachineUpdateMinerState::ActiveMiner {
889+
current_miner_pkh: Hash160([0xab; 20]),
890+
tenure_id: ConsensusHash([0x44; 20]),
891+
parent_tenure_id: ConsensusHash([0x22; 20]),
892+
parent_tenure_last_block: StacksBlockId([0x33; 32]),
893+
parent_tenure_last_block_height: 1,
894+
},
895+
},
896+
)
897+
.unwrap();
898+
899+
let mut address_updates = HashMap::new();
900+
for address in &addresses {
901+
address_updates.insert(*address, local_update.clone());
902+
}
903+
904+
let mut global_eval = GlobalStateEvaluator::new(address_updates, address_weights);
905+
assert_eq!(
906+
global_eval
907+
.determine_latest_supported_signer_protocol_version(
908+
local_address,
909+
local_update.clone()
910+
)
911+
.unwrap(),
912+
local_supported_signer_protocol_version
913+
);
914+
915+
// Let's update 3 signers (60 percent) to support seperate but greater protocol versions
916+
for (i, address) in addresses.into_iter().skip(1).take(3).enumerate() {
917+
let new_version = local_supported_signer_protocol_version + i as u64 + 1;
918+
let new_update = StateMachineUpdateMessage::new(
919+
0,
920+
new_version,
921+
StateMachineUpdateContent::V0 {
922+
burn_block: ConsensusHash([0x55; 20]),
923+
burn_block_height: 100,
924+
current_miner: StateMachineUpdateMinerState::ActiveMiner {
925+
current_miner_pkh: Hash160([0xab; 20]),
926+
tenure_id: ConsensusHash([0x44; 20]),
927+
parent_tenure_id: ConsensusHash([0x22; 20]),
928+
parent_tenure_last_block: StacksBlockId([0x33; 32]),
929+
parent_tenure_last_block_height: 1,
930+
},
931+
},
932+
)
933+
.unwrap();
934+
global_eval.insert_update(address, new_update);
935+
}
936+
937+
assert_eq!(
938+
global_eval
939+
.determine_latest_supported_signer_protocol_version(local_address, local_update)
940+
.unwrap(),
941+
local_supported_signer_protocol_version
942+
);
943+
944+
// Let's tip the scales over to version number 2 by updating the local signer's version...
945+
// i.e. > 70% will have version 2 or higher in their map
946+
let local_update = StateMachineUpdateMessage::new(
947+
active_protocol_version,
948+
3,
949+
StateMachineUpdateContent::V0 {
950+
burn_block: ConsensusHash([0x55; 20]),
951+
burn_block_height: 100,
952+
current_miner: StateMachineUpdateMinerState::ActiveMiner {
953+
current_miner_pkh: Hash160([0xab; 20]),
954+
tenure_id: ConsensusHash([0x44; 20]),
955+
parent_tenure_id: ConsensusHash([0x22; 20]),
956+
parent_tenure_last_block: StacksBlockId([0x33; 32]),
957+
parent_tenure_last_block_height: 1,
958+
},
959+
},
960+
)
961+
.unwrap();
962+
963+
assert_eq!(
964+
global_eval
965+
.determine_latest_supported_signer_protocol_version(local_address, local_update)
966+
.unwrap(),
967+
local_supported_signer_protocol_version + 1
968+
);
969+
}
970+
}

0 commit comments

Comments
 (0)