diff --git a/anchor/common/qbft/src/lib.rs b/anchor/common/qbft/src/lib.rs index 5e8f6027a..b17016fca 100644 --- a/anchor/common/qbft/src/lib.rs +++ b/anchor/common/qbft/src/lib.rs @@ -892,7 +892,7 @@ where qbft_message_type: msg_type, height: *self.instance_height as u64, round: data.round, - identifier: self.identifier.clone(), + identifier: self.identifier.clone().into(), root: data.root, data_round: data.data_round, round_change_justification, diff --git a/anchor/common/ssv_types/src/consensus.rs b/anchor/common/ssv_types/src/consensus.rs index 2c5f09fe8..812fde44e 100644 --- a/anchor/common/ssv_types/src/consensus.rs +++ b/anchor/common/ssv_types/src/consensus.rs @@ -1,5 +1,4 @@ use crate::message::*; -use crate::msgid::{MessageId, Role}; use crate::ValidatorIndex; use sha2::{Digest, Sha256}; use ssz::{Decode, DecodeError, Encode}; @@ -8,7 +7,7 @@ use std::fmt::Debug; use std::hash::Hash; use tree_hash::{PackedEncoding, TreeHash, TreeHashType}; use tree_hash_derive::TreeHash; -use types::typenum::U13; +use types::typenum::{U13, U56}; use types::{ AggregateAndProof, AggregateAndProofBase, AggregateAndProofElectra, BeaconBlock, BlindedBeaconBlock, Checkpoint, CommitteeIndex, EthSpec, Hash256, PublicKeyBytes, Signature, @@ -52,23 +51,13 @@ pub struct QbftMessage { pub qbft_message_type: QbftMessageType, pub height: u64, pub round: u64, - pub identifier: MessageId, + pub identifier: VariableList, // TODO: address redundant typing due to ssz_max encoding in go-client pub root: Hash256, pub data_round: u64, pub round_change_justification: Vec, // always without full_data pub prepare_justification: Vec, // always without full_data } -impl QbftMessage { - pub fn max_round(&self) -> Option { - self.identifier.role().and_then(|role| match role { - Role::Committee | Role::Aggregator => Some(12), // TODO: confirm max_round with ssvlabs - Role::Proposer | Role::SyncCommittee => Some(6), // as per https://github.com/ssvlabs/ssv/blob/main/message/validation/consensus_validation.go#L370 - _ => None, - }) - } -} - /// Different states the QBFT Message may represent #[derive(Clone, Debug, PartialEq, PartialOrd, Copy)] pub enum QbftMessageType { diff --git a/anchor/common/ssv_types/src/msgid.rs b/anchor/common/ssv_types/src/msgid.rs index 47993fa16..56672f80d 100644 --- a/anchor/common/ssv_types/src/msgid.rs +++ b/anchor/common/ssv_types/src/msgid.rs @@ -1,8 +1,9 @@ use crate::committee::CommitteeId; use crate::domain_type::DomainType; -use derive_more::From; +use derive_more::{From, Into}; use ssz::{Decode, DecodeError, Encode}; -use types::PublicKeyBytes; +use types::typenum::U56; +use types::{PublicKeyBytes, VariableList}; const MESSAGE_ID_LEN: usize = 56; @@ -45,13 +46,23 @@ impl TryFrom<&[u8]> for Role { } } +impl Role { + pub fn max_round(self) -> Option { + match self { + Role::Committee | Role::Aggregator => Some(12), // TODO: confirm max_round with ssvlabs + Role::Proposer | Role::SyncCommittee => Some(6), // as per https://github.com/ssvlabs/ssv/blob/main/message/validation/consensus_validation.go#L370 + _ => None, + } + } +} + #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub enum DutyExecutor { Committee(CommitteeId), Validator(PublicKeyBytes), } -#[derive(Debug, Clone, Hash, Eq, PartialEq, From)] +#[derive(Debug, Clone, Hash, Eq, PartialEq, From, Into)] pub struct MessageId([u8; 56]); impl MessageId { @@ -108,6 +119,12 @@ impl TryFrom<&[u8]> for MessageId { } } +impl From for VariableList { + fn from(value: MessageId) -> Self { + value.0.to_vec().into() + } +} + impl Encode for MessageId { fn is_ssz_fixed_len() -> bool { true diff --git a/anchor/message_validator/src/lib.rs b/anchor/message_validator/src/lib.rs index a2a8310a1..a4a070b3d 100644 --- a/anchor/message_validator/src/lib.rs +++ b/anchor/message_validator/src/lib.rs @@ -252,7 +252,12 @@ impl Validator { return Err(ValidationFailure::UnexpectedConsensusMessage); } - let max_round = match consensus_message.max_round() { + let max_round = match signed_ssv_message + .ssv_message() + .msg_id() + .role() + .and_then(Role::max_round) + { Some(max_round) => max_round, None => return Err(ValidationFailure::FailedToGetMaxRound), }; @@ -262,9 +267,9 @@ impl Validator { } // Rule: consensus message must have the same identifier as the ssv message's identifier - if consensus_message.identifier != *signed_ssv_message.ssv_message().msg_id() { + if *consensus_message.identifier != *signed_ssv_message.ssv_message().msg_id().as_ref() { return Err(ValidationFailure::MismatchedIdentifier { - got: hex::encode(&consensus_message.identifier), + got: hex::encode(&*consensus_message.identifier), want: hex::encode(signed_ssv_message.ssv_message().msg_id()), }); } @@ -451,7 +456,7 @@ mod tests { qbft_message_type: self.msg_type, height: 1, round: self.round, - identifier: self.msg_id.clone(), + identifier: self.msg_id.clone().into(), root: Hash256::from([0u8; 32]), data_round: 1, round_change_justification: self.round_change_justification, @@ -528,8 +533,8 @@ mod tests { "Unexpected QbftMessageType in validated QbftMessage" ); assert_eq!( - validated_qbft.identifier, - create_message_id_for_test(Role::Committee), + &*validated_qbft.identifier, + create_message_id_for_test(Role::Committee).as_ref(), "Identifier mismatch after validation" ); } else { @@ -640,7 +645,7 @@ mod tests { qbft_message_type: QbftMessageType::Proposal, height: 1, round: 1, - identifier: msg_id_b, // Mismatched ID + identifier: msg_id_b.into(), // Mismatched ID root: Hash256::from([0u8; 32]), data_round: 1, round_change_justification: vec![],