Skip to content

Commit

Permalink
Merge pull request bnb-chain#1 from bnb-chain/feat/greenfield/validat…
Browse files Browse the repository at this point in the history
…or/proto

feat: change validator proto to adapt to greenfield
  • Loading branch information
unclezoro authored May 21, 2024
2 parents 03f689b + 4e77e57 commit 1282547
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 0 deletions.
133 changes: 133 additions & 0 deletions cometbft/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use crate::{error::Error, prelude::*};
/// Size of an account ID in bytes
pub const LENGTH: usize = 20;

/// Size of a BLS account ID in bytes
pub const BLS_LENGTH: usize = 48;

/// Account IDs
#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Id([u8; LENGTH]); // JSON custom serialization for priv_validator_key.json
Expand Down Expand Up @@ -227,3 +230,133 @@ mod tests {
assert_eq!(id_bytes.ct_eq(&id).unwrap_u8(), 1);
}
}

/// Account IDs
#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct BLSKey([u8; BLS_LENGTH]); // JSON custom serialization for bls key

impl Protobuf<Vec<u8>> for BLSKey {}

impl TryFrom<Vec<u8>> for BLSKey {
type Error = Error;

fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
if value.len() != BLS_LENGTH {
return Err(Error::invalid_account_id_length());
}
let mut slice: [u8; BLS_LENGTH] = [0; BLS_LENGTH];
slice.copy_from_slice(&value[..]);
Ok(BLSKey(slice))
}
}

impl From<BLSKey> for Vec<u8> {
fn from(value: BLSKey) -> Self {
value.as_bytes().to_vec()
}
}

impl Default for BLSKey {
fn default() -> Self {
BLSKey([0; BLS_LENGTH])
}
}

impl TryFrom<Bytes> for BLSKey {
type Error = Error;

fn try_from(value: Bytes) -> Result<Self, Self::Error> {
if value.len() != BLS_LENGTH {
return Err(Error::invalid_account_id_length());
}
let mut slice: [u8; BLS_LENGTH] = [0; BLS_LENGTH];
slice.copy_from_slice(&value[..]);
Ok(BLSKey(slice))
}
}

impl From<BLSKey> for Bytes {
fn from(value: BLSKey) -> Self {
Bytes::copy_from_slice(value.as_bytes())
}
}

impl BLSKey {
/// Create a new account ID from raw bytes
pub fn new(bytes: [u8; BLS_LENGTH]) -> BLSKey {
BLSKey(bytes)
}

/// Borrow the account ID as a byte slice
pub fn as_bytes(&self) -> &[u8] {
&self.0[..]
}
}

impl AsRef<[u8]> for BLSKey {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}

impl ConstantTimeEq for BLSKey {
#[inline]
fn ct_eq(&self, other: &BLSKey) -> subtle::Choice {
self.as_bytes().ct_eq(other.as_bytes())
}
}

impl Display for BLSKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in &self.0 {
write!(f, "{byte:02X}")?;
}
Ok(())
}
}

impl Debug for BLSKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "account::BLSKey({self})")
}
}

/// Decode account ID from hex
impl FromStr for BLSKey {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// Accept either upper or lower case hex
let bytes = hex::decode_upper(s)
.or_else(|_| hex::decode(s))
.map_err(Error::subtle_encoding)?;

bytes.try_into()
}
}

// Todo: Can I remove custom serialization?
impl<'de> Deserialize<'de> for BLSKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(|_| {
de::Error::custom(format!(
"expected {}-character hex string, got {:?}",
BLS_LENGTH * 2,
s
))
})
}
}

impl Serialize for BLSKey {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(
&String::from_utf8(hex::encode_upper(Vec::<u8>::from(*self)))
.map_err(serde::ser::Error::custom)?,
)
}
}
42 changes: 42 additions & 0 deletions cometbft/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ pub struct Info {
/// Validator proposer priority
#[serde(skip)]
pub proposer_priority: ProposerPriority,

pub bls_key: account::BLSKey,

pub relayer_address: account::Id,
}

impl Info {
Expand Down Expand Up @@ -190,6 +194,22 @@ impl Info {
power: vp,
name: None,
proposer_priority: ProposerPriority::default(),
bls_key: account::BLSKey::default(),
relayer_address: account::Id::from(PublicKey::from_raw_ed25519(&[0u8; 32]).unwrap()),
}
}

#[cfg(feature = "rust-crypto")]
/// Create a new validator.
pub fn new_with_bls_and_relayer(pk: PublicKey, vp: vote::Power, bls_key: Vec<u8>, relayer_address: Vec<u8>) -> Info {
Info {
address: account::Id::from(pk),
pub_key: pk,
power: vp,
name: None,
proposer_priority: ProposerPriority::default(),
bls_key: account::BLSKey::try_from(bls_key).unwrap(),
relayer_address: account::Id::try_from(relayer_address).unwrap(),
}
}
}
Expand All @@ -205,6 +225,10 @@ pub struct SimpleValidator {
pub pub_key: PublicKey,
/// Voting power
pub voting_power: vote::Power,
// Bls key
pub bls_key: account::BLSKey,
// Relayer address
pub relayer_address: account::Id,
}

/// Info -> SimpleValidator
Expand All @@ -213,6 +237,8 @@ impl From<&Info> for SimpleValidator {
SimpleValidator {
pub_key: info.pub_key,
voting_power: info.power,
bls_key: info.bls_key,
relayer_address: info.relayer_address,
}
}
}
Expand Down Expand Up @@ -320,6 +346,8 @@ mod v1 {
power: value.voting_power.try_into()?,
name: None,
proposer_priority: value.proposer_priority.into(),
bls_key: value.bls_key.try_into()?,
relayer_address: value.relayer_address.try_into()?,
})
}
}
Expand All @@ -331,6 +359,8 @@ mod v1 {
pub_key: Some(value.pub_key.into()),
voting_power: value.power.into(),
proposer_priority: value.proposer_priority.into(),
bls_key: value.bls_key.into(),
relayer_address: value.relayer_address.into(),
}
}
}
Expand All @@ -347,6 +377,8 @@ mod v1 {
.ok_or_else(Error::missing_public_key)?
.try_into()?,
voting_power: value.voting_power.try_into()?,
bls_key: value.bls_key.try_into()?,
relayer_address: value.relayer_address.try_into()?,
})
}
}
Expand All @@ -356,6 +388,8 @@ mod v1 {
RawSimpleValidator {
pub_key: Some(value.pub_key.into()),
voting_power: value.voting_power.into(),
bls_key: value.bls_key.into(),
relayer_address: value.relayer_address.into(),
}
}
}
Expand Down Expand Up @@ -437,6 +471,8 @@ mod v1beta1 {
power: value.voting_power.try_into()?,
name: None,
proposer_priority: value.proposer_priority.into(),
bls_key: value.bls_key.try_into()?,
relayer_address: value.relayer_address.try_into()?,
})
}
}
Expand All @@ -448,6 +484,8 @@ mod v1beta1 {
pub_key: Some(value.pub_key.into()),
voting_power: value.power.into(),
proposer_priority: value.proposer_priority.into(),
bls_key: value.bls_key.into(),
relayer_address: value.relayer_address.into(),
}
}
}
Expand All @@ -464,6 +502,8 @@ mod v1beta1 {
.ok_or_else(Error::missing_public_key)?
.try_into()?,
voting_power: value.voting_power.try_into()?,
bls_key: value.bls_key.try_into()?,
relayer_address: value.relayer_address.try_into()?,
})
}
}
Expand All @@ -473,6 +513,8 @@ mod v1beta1 {
RawSimpleValidator {
pub_key: Some(value.pub_key.into()),
voting_power: value.voting_power.into(),
bls_key: value.bls_key.into(),
relayer_address: value.relayer_address.into(),
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions proto/src/prost/cometbft.types.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,30 @@ pub struct Validator {
#[serde(with = "crate::serializers::from_str_allow_null")]
#[serde(default)]
pub proposer_priority: i64,
#[prost(bytes = "vec", tag = "5")]
#[serde(with = "crate::serializers::bytes::hexstring")]
pub bls_key: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "6")]
#[serde(with = "crate::serializers::bytes::hexstring")]
pub relayer_address: ::prost::alloc::vec::Vec<u8>,
}
/// SimpleValidator is a Validator, which is serialized and hashed in consensus.
/// Address is removed because it's redundant with the pubkey.
/// Proposer priority is removed because it changes every round.
#[derive(::serde::Deserialize, ::serde::Serialize)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SimpleValidator {
#[prost(message, optional, tag = "1")]
pub pub_key: ::core::option::Option<super::super::crypto::v1::PublicKey>,
#[prost(int64, tag = "2")]
pub voting_power: i64,
#[serde(with = "crate::serializers::bytes::hexstring")]
#[prost(bytes = "vec", tag = "3")]
pub bls_key: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "4")]
#[serde(with = "crate::serializers::bytes::hexstring")]
pub relayer_address: ::prost::alloc::vec::Vec<u8>,
}
/// BlockIdFlag indicates which BlockID the signature is for
#[derive(::num_derive::FromPrimitive, ::num_derive::ToPrimitive)]
Expand Down
13 changes: 13 additions & 0 deletions proto/src/prost/cometbft.types.v1beta1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,30 @@ pub struct Validator {
#[serde(with = "crate::serializers::from_str_allow_null")]
#[serde(default)]
pub proposer_priority: i64,
#[prost(bytes = "vec", tag = "5")]
#[serde(with = "crate::serializers::bytes::hexstring")]
pub bls_key: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "6")]
#[serde(with = "crate::serializers::bytes::hexstring")]
pub relayer_address: ::prost::alloc::vec::Vec<u8>,
}
/// SimpleValidator is a Validator, which is serialized and hashed in consensus.
/// Address is removed because it's redundant with the pubkey.
/// Proposer priority is removed because it changes every round.
#[derive(::serde::Deserialize, ::serde::Serialize)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct SimpleValidator {
#[prost(message, optional, tag = "1")]
pub pub_key: ::core::option::Option<super::super::crypto::v1::PublicKey>,
#[prost(int64, tag = "2")]
pub voting_power: i64,
#[serde(with = "crate::serializers::bytes::hexstring")]
#[prost(bytes = "vec", tag = "3")]
pub bls_key: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "4")]
#[serde(with = "crate::serializers::bytes::hexstring")]
pub relayer_address: ::prost::alloc::vec::Vec<u8>,
}
/// BlockIdFlag indicates which BlockID the signature is for
#[derive(::num_derive::FromPrimitive, ::num_derive::ToPrimitive)]
Expand Down

0 comments on commit 1282547

Please sign in to comment.