Skip to content

Commit

Permalink
Thread validator change events through code
Browse files Browse the repository at this point in the history
  • Loading branch information
plaidfinch committed May 23, 2024
1 parent db80693 commit f094f22
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ use {
},
StateReadExt as _,
},
event,
params::StakeParameters,
validator, IdentityKey, Uptime,
},
anyhow::Result,
async_trait::async_trait,
cnidarium::StateWrite,
futures::StreamExt as _,
penumbra_proto::StateWriteProto,
penumbra_sct::component::clock::EpochRead,
std::collections::BTreeMap,
tap::Tap,
Expand Down Expand Up @@ -174,6 +176,11 @@ pub trait ValidatorUptimeTracker: StateWrite {
metrics::gauge!(metrics::MISSED_BLOCKS, "identity_key" => identity_key.to_string())
.set(uptime.num_missed_blocks() as f64);

if !voted {
// If the validator didn't sign, we need to emit a missed block event.
self.record_proto(event::validator_missed_block(identity_key));
}

uptime.mark_height_as_signed(height, voted)?;
if uptime.num_missed_blocks() as u64 >= params.missed_blocks_maximum {
self.set_validator_state(&identity_key, validator::State::Jailed)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ use {
/// │ ┌─────────────┐ ┌────────────┐ │ │◀──┘ │
/// └──▶│ Jailed │◀───────│ Active │◀───▶│ Inactive │ │
/// └─────────────┘ └────────────┘ │ │◀────┘
/// │ └──────────────┘
/// │ ▲
/// └──────────────────────────────────────────┘
///
/// │ └──────────────┘
/// │ ▲
/// └──────────────────────────────────────────┘
///
/// ╔═════════════════╗
/// ║ starting state ║
/// ╚═════════════════╝
/// ┏━━━━━━━━━━━━━━━━━┓
/// ┃ terminal state ┃
/// ┗━━━━━━━━━━━━━━━━━┛
/// ┗━━━━━━━━━━━━━━━━━┛
/// ```
///
/// [`add_validator`]: Self::add_validator
Expand Down Expand Up @@ -302,6 +302,8 @@ pub trait ValidatorManager: StateWrite {
tracing::info!("successful state transition");
self.put(validator_state_path, new_state);

self.record_proto(event::validator_state_change(*identity_key, new_state));

Ok((old_state, new_state))
}

Expand Down Expand Up @@ -477,6 +479,10 @@ pub trait ValidatorManager: StateWrite {
// ... and its reward rate data in the JMT.
self.set_validator_rate_data(&validator_identity, initial_rate_data);

// Track the validator's definition in an event (the rest of the attributes will be tracked
// in events emitted by the calls to set_* methods below).
self.record_proto(event::validator_definition_upload(validator.clone()));

// We initialize the validator's state, power, and bonding state.
self.set_initial_validator_state(&validator_identity, initial_state)?;
self.set_validator_power(&validator_identity, initial_voting_power)?;
Expand Down Expand Up @@ -587,7 +593,13 @@ pub trait ValidatorManager: StateWrite {
// consensus key.
self.register_consensus_key(&validator.identity_key, &validator.consensus_key);

self.put(state_key::validators::definitions::by_id(id), validator);
self.put(
state_key::validators::definitions::by_id(id),
validator.clone(),
);

// Track the validator's definition in an event.
self.record_proto(event::validator_definition_upload(validator));

Ok(())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
component::{StateReadExt as _, MAX_VOTING_POWER},
event,
rate::RateData,
state_key,
validator::{self, BondingState::*, State, Validator},
Expand Down Expand Up @@ -250,8 +251,9 @@ pub(crate) trait ValidatorDataWrite: StateWrite {
tracing::debug!(?state, validator_identity = %identity_key, "set bonding state for validator");
self.put(
state_key::validators::pool::bonding_state::by_id(identity_key),
state,
state.clone(),
);
self.record_proto(event::validator_bonding_state_change(*identity_key, state));
}

#[instrument(skip(self))]
Expand All @@ -268,6 +270,10 @@ pub(crate) trait ValidatorDataWrite: StateWrite {
state_key::validators::power::by_id(identity_key),
voting_power,
);
self.record_proto(event::validator_voting_power_change(
*identity_key,
voting_power,
));

Ok(())
}
Expand All @@ -284,6 +290,7 @@ pub(crate) trait ValidatorDataWrite: StateWrite {
}

self.put(state_key::validators::state::by_id(id), initial_state);
self.record_proto(event::validator_state_change(*id, initial_state));
Ok(())
}

Expand All @@ -292,8 +299,9 @@ pub(crate) trait ValidatorDataWrite: StateWrite {
tracing::debug!("setting validator rate data");
self.put(
state_key::validators::rate::current_by_id(identity_key),
rate_data,
rate_data.clone(),
);
self.record_proto(event::validator_rate_data_change(*identity_key, rate_data));
}

#[instrument(skip(self))]
Expand Down
25 changes: 21 additions & 4 deletions crates/core/component/stake/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
validator::{BondingState, Definition, State},
rate,
validator::{BondingState, State, Validator},
Delegate, IdentityKey, Undelegate,
};
use penumbra_num::Amount;
use penumbra_proto::core::component::stake::v1 as pb;
use tendermint::abci::{types::Misbehavior, Event, EventAttributeIndexExt};
use tendermint::abci::types::Misbehavior;

pub fn validator_state_change(
identity_key: IdentityKey,
Expand Down Expand Up @@ -36,9 +37,25 @@ pub fn validator_bonding_state_change(
}
}

pub fn validator_definition_upload(definition: Definition) -> pb::EventValidatorDefinitionUpload {
pub fn validator_rate_data_change(
identity_key: IdentityKey,
rate_data: rate::RateData,
) -> pb::EventRateDataChange {
pb::EventRateDataChange {
identity_key: Some(identity_key.into()),
rate_data: Some(rate_data.into()),
}
}

pub fn validator_definition_upload(validator: Validator) -> pb::EventValidatorDefinitionUpload {
pb::EventValidatorDefinitionUpload {
definition: Some(definition.into()),
validator: Some(validator.into()),
}
}

pub fn validator_missed_block(identity_key: IdentityKey) -> pb::EventValidatorMissedBlock {
pb::EventValidatorMissedBlock {
identity_key: Some(identity_key.into()),
}
}

Expand Down
36 changes: 18 additions & 18 deletions crates/proto/src/gen/penumbra.core.component.stake.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,10 +896,27 @@ impl ::prost::Name for EventValidatorBondingStateChange {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EventRateDataChange {
/// The validator's identity key.
#[prost(message, optional, tag = "1")]
pub identity_key: ::core::option::Option<super::super::super::keys::v1::IdentityKey>,
/// The new rate data.
#[prost(message, optional, tag = "2")]
pub rate_data: ::core::option::Option<RateData>,
}
impl ::prost::Name for EventRateDataChange {
const NAME: &'static str = "EventRateDataChange";
const PACKAGE: &'static str = "penumbra.core.component.stake.v1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!("penumbra.core.component.stake.v1.{}", Self::NAME)
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EventValidatorDefinitionUpload {
/// The validator definition.
#[prost(message, optional, tag = "1")]
pub definition: ::core::option::Option<ValidatorDefinition>,
pub validator: ::core::option::Option<Validator>,
}
impl ::prost::Name for EventValidatorDefinitionUpload {
const NAME: &'static str = "EventValidatorDefinitionUpload";
Expand Down Expand Up @@ -960,23 +977,6 @@ impl ::prost::Name for EventUndelegate {
::prost::alloc::format!("penumbra.core.component.stake.v1.{}", Self::NAME)
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EventRateDataChange {
/// The validator's identity key.
#[prost(message, optional, tag = "1")]
pub identity_key: ::core::option::Option<super::super::super::keys::v1::IdentityKey>,
/// The new rate data.
#[prost(message, optional, tag = "2")]
pub rate_data: ::core::option::Option<RateData>,
}
impl ::prost::Name for EventRateDataChange {
const NAME: &'static str = "EventRateDataChange";
const PACKAGE: &'static str = "penumbra.core.component.stake.v1";
fn full_name() -> ::prost::alloc::string::String {
::prost::alloc::format!("penumbra.core.component.stake.v1.{}", Self::NAME)
}
}
/// Generated client implementations.
#[cfg(feature = "rpc")]
pub mod query_service_client {
Expand Down
24 changes: 12 additions & 12 deletions crates/proto/src/gen/penumbra.core.component.stake.v1.serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1542,12 +1542,12 @@ impl serde::Serialize for EventValidatorDefinitionUpload {
{
use serde::ser::SerializeStruct;
let mut len = 0;
if self.definition.is_some() {
if self.validator.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.core.component.stake.v1.EventValidatorDefinitionUpload", len)?;
if let Some(v) = self.definition.as_ref() {
struct_ser.serialize_field("definition", v)?;
if let Some(v) = self.validator.as_ref() {
struct_ser.serialize_field("validator", v)?;
}
struct_ser.end()
}
Expand All @@ -1559,12 +1559,12 @@ impl<'de> serde::Deserialize<'de> for EventValidatorDefinitionUpload {
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &[
"definition",
"validator",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
Definition,
Validator,
__SkipField__,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
Expand All @@ -1587,7 +1587,7 @@ impl<'de> serde::Deserialize<'de> for EventValidatorDefinitionUpload {
E: serde::de::Error,
{
match value {
"definition" => Ok(GeneratedField::Definition),
"validator" => Ok(GeneratedField::Validator),
_ => Ok(GeneratedField::__SkipField__),
}
}
Expand All @@ -1607,22 +1607,22 @@ impl<'de> serde::Deserialize<'de> for EventValidatorDefinitionUpload {
where
V: serde::de::MapAccess<'de>,
{
let mut definition__ = None;
let mut validator__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::Definition => {
if definition__.is_some() {
return Err(serde::de::Error::duplicate_field("definition"));
GeneratedField::Validator => {
if validator__.is_some() {
return Err(serde::de::Error::duplicate_field("validator"));
}
definition__ = map_.next_value()?;
validator__ = map_.next_value()?;
}
GeneratedField::__SkipField__ => {
let _ = map_.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(EventValidatorDefinitionUpload {
definition: definition__,
validator: validator__,
})
}
}
Expand Down
Binary file modified crates/proto/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
16 changes: 8 additions & 8 deletions proto/penumbra/penumbra/core/component/stake/v1/stake.proto
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,16 @@ message EventValidatorBondingStateChange {
BondingState bonding_state = 2;
}

message EventRateDataChange {
// The validator's identity key.
keys.v1.IdentityKey identity_key = 1;
// The new rate data.
RateData rate_data = 2;
}

message EventValidatorDefinitionUpload {
// The validator definition.
ValidatorDefinition definition = 1;
Validator validator = 1;
}

message EventValidatorMissedBlock {
Expand All @@ -391,11 +398,4 @@ message EventUndelegate {
keys.v1.IdentityKey validator_identity = 1;
// The amount of stake undelegated, in the staking token.
num.v1.Amount amount = 3;
}

message EventRateDataChange {
// The validator's identity key.
keys.v1.IdentityKey identity_key = 1;
// The new rate data.
RateData rate_data = 2;
}

0 comments on commit f094f22

Please sign in to comment.