From 98dbc5eb98de12258ee306ca09344378fba1684d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 5 Dec 2023 15:11:53 +0000 Subject: [PATCH] added support for slashing module --- cosmos-sdk-proto/src/lib.rs | 2 +- cosmos-sdk-proto/src/type_names.rs | 71 ++++++++++++++++ cosmrs/src/base.rs | 2 + cosmrs/src/base/query.rs | 3 + cosmrs/src/base/query/pagination.rs | 85 +++++++++++++++++++ cosmrs/src/lib.rs | 1 + cosmrs/src/signing_info.rs | 35 ++++++++ cosmrs/src/slashing.rs | 33 +++++++ cosmrs/src/slashing/genesis_state.rs | 51 +++++++++++ cosmrs/src/slashing/missed_block.rs | 29 +++++++ cosmrs/src/slashing/msg_unjail.rs | 54 ++++++++++++ cosmrs/src/slashing/params.rs | 54 ++++++++++++ cosmrs/src/slashing/query_params_request.rs | 16 ++++ cosmrs/src/slashing/query_params_response.rs | 29 +++++++ .../slashing/query_signing_info_request.rs | 31 +++++++ .../slashing/query_signing_info_response.rs | 32 +++++++ .../slashing/query_signing_infos_request.rs | 26 ++++++ .../slashing/query_signing_infos_response.rs | 48 +++++++++++ cosmrs/src/slashing/signing_info.rs | 35 ++++++++ .../src/slashing/validator_missed_blocks.rs | 39 +++++++++ cosmrs/src/slashing/validator_signing_info.rs | 77 +++++++++++++++++ 21 files changed, 752 insertions(+), 1 deletion(-) create mode 100644 cosmrs/src/base/query.rs create mode 100644 cosmrs/src/base/query/pagination.rs create mode 100644 cosmrs/src/signing_info.rs create mode 100644 cosmrs/src/slashing.rs create mode 100644 cosmrs/src/slashing/genesis_state.rs create mode 100644 cosmrs/src/slashing/missed_block.rs create mode 100644 cosmrs/src/slashing/msg_unjail.rs create mode 100644 cosmrs/src/slashing/params.rs create mode 100644 cosmrs/src/slashing/query_params_request.rs create mode 100644 cosmrs/src/slashing/query_params_response.rs create mode 100644 cosmrs/src/slashing/query_signing_info_request.rs create mode 100644 cosmrs/src/slashing/query_signing_info_response.rs create mode 100644 cosmrs/src/slashing/query_signing_infos_request.rs create mode 100644 cosmrs/src/slashing/query_signing_infos_response.rs create mode 100644 cosmrs/src/slashing/signing_info.rs create mode 100644 cosmrs/src/slashing/validator_missed_blocks.rs create mode 100644 cosmrs/src/slashing/validator_signing_info.rs diff --git a/cosmos-sdk-proto/src/lib.rs b/cosmos-sdk-proto/src/lib.rs index a54858da..53246eaa 100644 --- a/cosmos-sdk-proto/src/lib.rs +++ b/cosmos-sdk-proto/src/lib.rs @@ -15,7 +15,7 @@ pub mod traits; mod type_names; pub use prost; -pub use prost_types::Any; +pub use prost_types::{Any, Timestamp}; pub use tendermint_proto as tendermint; /// The version (commit hash) of the Cosmos SDK used when generating this library. diff --git a/cosmos-sdk-proto/src/type_names.rs b/cosmos-sdk-proto/src/type_names.rs index 1fa24797..c00ed3b8 100644 --- a/cosmos-sdk-proto/src/type_names.rs +++ b/cosmos-sdk-proto/src/type_names.rs @@ -169,6 +169,77 @@ impl_name!( "AllowedMsgAllowance" ); +impl_name!( + cosmos::slashing::v1beta1::GenesisState, + "cosmos.slashing.v1beta1", + "MissedBlocks" +); +impl_name!( + cosmos::slashing::v1beta1::MissedBlock, + "cosmos.slashing.v1beta1", + "MissedBlock" +); +impl_name!( + cosmos::slashing::v1beta1::MsgUnjail, + "cosmos.slashing.v1beta1", + "MsgUnjail" +); +impl_name!( + cosmos::slashing::v1beta1::MsgUnjailResponse, + "cosmos.slashing.v1beta1", + "MsgUnjailResponse" +); +impl_name!( + cosmos::slashing::v1beta1::Params, + "cosmos.slashing.v1beta1", + "Params" +); +impl_name!( + cosmos::slashing::v1beta1::QueryParamsRequest, + "cosmos.slashing.v1beta1", + "QueryParamsRequest" +); +impl_name!( + cosmos::slashing::v1beta1::QueryParamsResponse, + "cosmos.slashing.v1beta1", + "QueryParamsResponse" +); +impl_name!( + cosmos::slashing::v1beta1::QuerySigningInfoRequest, + "cosmos.slashing.v1beta1", + "QuerySigningInfoRequest" +); +impl_name!( + cosmos::slashing::v1beta1::QuerySigningInfoResponse, + "cosmos.slashing.v1beta1", + "QuerySigningInfoResponse" +); +impl_name!( + cosmos::slashing::v1beta1::QuerySigningInfosRequest, + "cosmos.slashing.v1beta1", + "QuerySigningInfosRequest" +); +impl_name!( + cosmos::slashing::v1beta1::QuerySigningInfosResponse, + "cosmos.slashing.v1beta1", + "QuerySigningInfosResponse" +); +impl_name!( + cosmos::slashing::v1beta1::SigningInfo, + "cosmos.slashing.v1beta1", + "SigningInfo" +); +impl_name!( + cosmos::slashing::v1beta1::ValidatorMissedBlocks, + "cosmos.slashing.v1beta1", + "ValidatorMissedBlocks" +); +impl_name!( + cosmos::slashing::v1beta1::ValidatorSigningInfo, + "cosmos.slashing.v1beta1", + "ValidatorSigningInfo" +); + impl_name!( cosmos::staking::v1beta1::MsgEditValidatorResponse, "cosmos.staking.v1beta1", diff --git a/cosmrs/src/base.rs b/cosmrs/src/base.rs index 7602c3c8..1c3fc125 100644 --- a/cosmrs/src/base.rs +++ b/cosmrs/src/base.rs @@ -4,6 +4,8 @@ mod account_id; mod coin; mod denom; +pub mod query; + pub use self::{account_id::AccountId, coin::Coin, denom::Denom}; /// Amounts. diff --git a/cosmrs/src/base/query.rs b/cosmrs/src/base/query.rs new file mode 100644 index 00000000..9551b644 --- /dev/null +++ b/cosmrs/src/base/query.rs @@ -0,0 +1,3 @@ +mod pagination; + +pub use pagination::{PageRequest, PageResponse}; diff --git a/cosmrs/src/base/query/pagination.rs b/cosmrs/src/base/query/pagination.rs new file mode 100644 index 00000000..c24b13e4 --- /dev/null +++ b/cosmrs/src/base/query/pagination.rs @@ -0,0 +1,85 @@ +use crate::proto; + +/// PageRequest is to be embedded in gRPC request messages for efficient +/// pagination. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PageRequest { + /// key is a value returned in PageResponse.next_key to begin + /// querying the next page most efficiently. Only one of offset or key + /// should be set. + pub key: Vec, + + /// offset is a numeric offset that can be used when key is unavailable. + /// It is less efficient than using key. Only one of offset or key should + /// be set. + pub offset: u64, + /// limit is the total number of results to be returned in the result page. + /// If left empty it will default to a value to be set by each app. + pub limit: u64, + /// count_total is set to true to indicate that the result set should include + /// a count of the total number of items available for pagination in UIs. + /// count_total is only respected when offset is used. It is ignored when key + /// is set. + pub count_total: bool, + + /// reverse is set to true if results are to be returned in the descending order. + /// + /// Since: cosmos-sdk 0.43 + pub reverse: bool, +} + +impl From for PageRequest { + fn from(proto: cosmos_sdk_proto::cosmos::base::query::v1beta1::PageRequest) -> Self { + PageRequest { + key: proto.key, + offset: proto.offset, + limit: proto.limit, + count_total: proto.count_total, + reverse: proto.reverse, + } + } +} + +impl From for proto::cosmos::base::query::v1beta1::PageRequest { + fn from(page_request: PageRequest) -> Self { + proto::cosmos::base::query::v1beta1::PageRequest { + key: page_request.key, + offset: page_request.offset, + limit: page_request.limit, + count_total: page_request.count_total, + reverse: page_request.reverse, + } + } +} + +/// PageResponse is to be embedded in gRPC response messages where the +/// corresponding request message has used PageRequest. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PageResponse { + /// next_key is the key to be passed to PageRequest.key to + /// query the next page most efficiently. It will be empty if + /// there are no more results. + pub next_key: Vec, + + /// total is total number of results available if PageRequest.count_total + /// was set, its value is undefined otherwise + pub total: u64, +} + +impl From for PageResponse { + fn from(proto: cosmos_sdk_proto::cosmos::base::query::v1beta1::PageResponse) -> Self { + PageResponse { + next_key: proto.next_key, + total: proto.total, + } + } +} + +impl From for proto::cosmos::base::query::v1beta1::PageResponse { + fn from(page_response: PageResponse) -> Self { + proto::cosmos::base::query::v1beta1::PageResponse { + next_key: page_response.next_key, + total: page_response.total, + } + } +} diff --git a/cosmrs/src/lib.rs b/cosmrs/src/lib.rs index 9b4a27bc..6eec0fec 100644 --- a/cosmrs/src/lib.rs +++ b/cosmrs/src/lib.rs @@ -32,6 +32,7 @@ pub mod bank; pub mod crypto; pub mod distribution; pub mod feegrant; +pub mod slashing; pub mod staking; pub mod tx; pub mod vesting; diff --git a/cosmrs/src/signing_info.rs b/cosmrs/src/signing_info.rs new file mode 100644 index 00000000..4bb51e81 --- /dev/null +++ b/cosmrs/src/signing_info.rs @@ -0,0 +1,35 @@ +use crate::slashing::validator_signing_info::ValidatorSigningInfo; +use crate::{proto, AccountId, ErrorReport, Result}; + +/// SigningInfo stores validator signing info of corresponding address. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SigningInfo { + /// address is the validator address. + pub address: AccountId, + + /// validator_signing_info represents the signing info of this validator. + pub validator_signing_info: Option, +} + +impl TryFrom for SigningInfo { + type Error = ErrorReport; + + fn try_from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::SigningInfo) -> Result { + Ok(SigningInfo { + address: proto.address.parse()?, + validator_signing_info: proto + .validator_signing_info + .map(TryInto::try_into) + .transpose()?, + }) + } +} + +impl From for cosmos_sdk_proto::cosmos::slashing::v1beta1::SigningInfo { + fn from(signing_info: SigningInfo) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::SigningInfo { + address: signing_info.address.to_string(), + validator_signing_info: signing_info.validator_signing_info.map(Into::into), + } + } +} diff --git a/cosmrs/src/slashing.rs b/cosmrs/src/slashing.rs new file mode 100644 index 00000000..1e74aff4 --- /dev/null +++ b/cosmrs/src/slashing.rs @@ -0,0 +1,33 @@ +//! Slashing module support +//! +//! + +mod genesis_state; +mod missed_block; +mod msg_unjail; +mod params; +mod query_params_request; +mod query_params_response; +mod query_signing_info_request; +mod query_signing_info_response; +mod query_signing_infos_request; +mod query_signing_infos_response; +mod signing_info; +mod validator_missed_blocks; +mod validator_signing_info; + +pub use self::{ + genesis_state::GenesisState, + missed_block::MissedBlock, + msg_unjail::{MsgUnjail, MsgUnjailResponse}, + params::Params, + query_params_request::QueryParamsRequest, + query_params_response::QueryParamsResponse, + query_signing_info_request::QuerySigningInfoRequest, + query_signing_info_response::QuerySigningInfoResponse, + query_signing_infos_request::QuerySigningInfosRequest, + query_signing_infos_response::QuerySigningInfosResponse, + signing_info::SigningInfo, + validator_missed_blocks::ValidatorMissedBlocks, + validator_signing_info::ValidatorSigningInfo, +}; diff --git a/cosmrs/src/slashing/genesis_state.rs b/cosmrs/src/slashing/genesis_state.rs new file mode 100644 index 00000000..ea406f10 --- /dev/null +++ b/cosmrs/src/slashing/genesis_state.rs @@ -0,0 +1,51 @@ +use crate::slashing::{Params, SigningInfo, ValidatorMissedBlocks}; +use crate::{proto, ErrorReport, Result}; + +/// GenesisState defines the slashing module's genesis state. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct GenesisState { + /// params defines all the paramaters of related to deposit. + pub params: Option, + + /// signing_infos represents a map between validator addresses and their + /// signing infos. + pub signing_infos: Vec, + + /// missed_blocks represents a map between validator addresses and their + /// missed blocks. + pub missed_blocks: Vec, +} + +impl TryFrom for GenesisState { + type Error = ErrorReport; + + fn try_from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::GenesisState) -> Result { + Ok(GenesisState { + params: proto.params.map(TryInto::try_into).transpose()?, + signing_infos: proto + .signing_infos + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + missed_blocks: proto.missed_blocks.into_iter().map(Into::into).collect(), + }) + } +} + +impl From for cosmos_sdk_proto::cosmos::slashing::v1beta1::GenesisState { + fn from(genesis_state: GenesisState) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::GenesisState { + params: genesis_state.params.map(Into::into), + signing_infos: genesis_state + .signing_infos + .into_iter() + .map(Into::into) + .collect(), + missed_blocks: genesis_state + .missed_blocks + .into_iter() + .map(Into::into) + .collect(), + } + } +} diff --git a/cosmrs/src/slashing/missed_block.rs b/cosmrs/src/slashing/missed_block.rs new file mode 100644 index 00000000..6bb4aeb8 --- /dev/null +++ b/cosmrs/src/slashing/missed_block.rs @@ -0,0 +1,29 @@ +use crate::proto; + +/// MissedBlock contains height and missed status as boolean. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct MissedBlock { + /// index is the height at which the block was missed. + pub index: i64, + + /// missed is the missed status. + pub missed: bool, +} + +impl From for MissedBlock { + fn from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::MissedBlock) -> MissedBlock { + MissedBlock { + index: proto.index, + missed: proto.missed, + } + } +} + +impl From for cosmos_sdk_proto::cosmos::slashing::v1beta1::MissedBlock { + fn from(missed_block: MissedBlock) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::MissedBlock { + index: missed_block.index, + missed: missed_block.missed, + } + } +} diff --git a/cosmrs/src/slashing/msg_unjail.rs b/cosmrs/src/slashing/msg_unjail.rs new file mode 100644 index 00000000..5139edc0 --- /dev/null +++ b/cosmrs/src/slashing/msg_unjail.rs @@ -0,0 +1,54 @@ +use crate::{proto, tx::Msg, AccountId, ErrorReport, Result}; + +/// MsgUnjail defines the Msg/Unjail request type +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct MsgUnjail { + /// Address of the validator to unjail. + pub validator_addr: AccountId, +} + +impl Msg for MsgUnjail { + type Proto = proto::cosmos::slashing::v1beta1::MsgUnjail; +} + +impl TryFrom for MsgUnjail { + type Error = ErrorReport; + + fn try_from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::MsgUnjail) -> Result { + Ok(MsgUnjail { + validator_addr: proto.validator_addr.parse()?, + }) + } +} + +impl From for cosmos_sdk_proto::cosmos::slashing::v1beta1::MsgUnjail { + fn from(msg_unjail: MsgUnjail) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::MsgUnjail { + validator_addr: msg_unjail.validator_addr.to_string(), + } + } +} + +/// MsgUnjailResponse defines the Msg/Unjail response type +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct MsgUnjailResponse {} + +impl Msg for MsgUnjailResponse { + type Proto = proto::cosmos::slashing::v1beta1::MsgUnjailResponse; +} + +impl TryFrom for MsgUnjailResponse { + type Error = ErrorReport; + + fn try_from( + _proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::MsgUnjailResponse, + ) -> Result { + Ok(MsgUnjailResponse {}) + } +} + +impl From for cosmos_sdk_proto::cosmos::slashing::v1beta1::MsgUnjailResponse { + fn from(_: MsgUnjailResponse) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::MsgUnjailResponse {} + } +} diff --git a/cosmrs/src/slashing/params.rs b/cosmrs/src/slashing/params.rs new file mode 100644 index 00000000..dc5ad47c --- /dev/null +++ b/cosmrs/src/slashing/params.rs @@ -0,0 +1,54 @@ +use crate::{proto, ErrorReport, Result}; +use std::time::Duration; + +/// Params represents the parameters used for by the slashing module. +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +pub struct Params { + /// Signed blocks window + pub signed_blocks_window: i64, + + /// Minimum signed per window + pub min_signed_per_window: Vec, + + /// Downtime jail duration + pub downtime_jail_duration: Option, + + /// Slash fraction for double sign + pub slash_fraction_double_sign: Vec, + + /// Slash fraction for downtime + pub slash_fraction_downtime: Vec, +} + +impl TryFrom for Params { + type Error = ErrorReport; + + fn try_from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::Params) -> Result { + Ok(Params { + signed_blocks_window: proto.signed_blocks_window, + min_signed_per_window: proto.min_signed_per_window, + downtime_jail_duration: proto + .downtime_jail_duration + .map(TryFrom::try_from) + .transpose()?, + slash_fraction_double_sign: proto.slash_fraction_double_sign, + slash_fraction_downtime: proto.slash_fraction_downtime, + }) + } +} + +impl From for proto::cosmos::slashing::v1beta1::Params { + fn from(params: Params) -> Self { + proto::cosmos::slashing::v1beta1::Params { + signed_blocks_window: params.signed_blocks_window, + min_signed_per_window: params.min_signed_per_window, + downtime_jail_duration: params + .downtime_jail_duration + .map(TryInto::try_into) + .transpose() + .expect("invalid downtime jail duration"), // same fallible serialisation concern as with feegrant::PeriodicAllowance + slash_fraction_double_sign: params.slash_fraction_double_sign, + slash_fraction_downtime: params.slash_fraction_downtime, + } + } +} diff --git a/cosmrs/src/slashing/query_params_request.rs b/cosmrs/src/slashing/query_params_request.rs new file mode 100644 index 00000000..506225b4 --- /dev/null +++ b/cosmrs/src/slashing/query_params_request.rs @@ -0,0 +1,16 @@ +use crate::proto; + +/// QueryParamsRequest is the request type for the Query/Params RPC method +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct QueryParamsRequest {} + +impl From for QueryParamsRequest { + fn from(_proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::QueryParamsRequest) -> Self { + QueryParamsRequest {} + } +} +impl From for proto::cosmos::slashing::v1beta1::QueryParamsRequest { + fn from(_request: QueryParamsRequest) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::QueryParamsRequest {} + } +} diff --git a/cosmrs/src/slashing/query_params_response.rs b/cosmrs/src/slashing/query_params_response.rs new file mode 100644 index 00000000..cf913c3e --- /dev/null +++ b/cosmrs/src/slashing/query_params_response.rs @@ -0,0 +1,29 @@ +use crate::slashing::Params; +use crate::{proto, ErrorReport, Result}; + +/// QueryParamsResponse is the response type for the Query/Params RPC method +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct QueryParamsResponse { + /// Parameters of the slashing module + pub params: Option, +} + +impl TryFrom for QueryParamsResponse { + type Error = ErrorReport; + + fn try_from( + proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::QueryParamsResponse, + ) -> Result { + Ok(QueryParamsResponse { + params: proto.params.map(TryInto::try_into).transpose()?, + }) + } +} + +impl From for proto::cosmos::slashing::v1beta1::QueryParamsResponse { + fn from(params_response: QueryParamsResponse) -> Self { + proto::cosmos::slashing::v1beta1::QueryParamsResponse { + params: params_response.params.map(Into::into), + } + } +} diff --git a/cosmrs/src/slashing/query_signing_info_request.rs b/cosmrs/src/slashing/query_signing_info_request.rs new file mode 100644 index 00000000..419be532 --- /dev/null +++ b/cosmrs/src/slashing/query_signing_info_request.rs @@ -0,0 +1,31 @@ +use crate::{proto, AccountId, ErrorReport, Result}; + +/// QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC +/// method +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct QuerySigningInfoRequest { + /// cons_address is the address to query signing info of + pub cons_address: AccountId, +} + +impl TryFrom + for QuerySigningInfoRequest +{ + type Error = ErrorReport; + + fn try_from( + proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::QuerySigningInfoRequest, + ) -> Result { + Ok(QuerySigningInfoRequest { + cons_address: proto.cons_address.parse()?, + }) + } +} + +impl From for proto::cosmos::slashing::v1beta1::QuerySigningInfoRequest { + fn from(signing_info_response: QuerySigningInfoRequest) -> Self { + proto::cosmos::slashing::v1beta1::QuerySigningInfoRequest { + cons_address: signing_info_response.cons_address.to_string(), + } + } +} diff --git a/cosmrs/src/slashing/query_signing_info_response.rs b/cosmrs/src/slashing/query_signing_info_response.rs new file mode 100644 index 00000000..7279002b --- /dev/null +++ b/cosmrs/src/slashing/query_signing_info_response.rs @@ -0,0 +1,32 @@ +use crate::slashing::ValidatorSigningInfo; +use crate::{proto, ErrorReport, Result}; + +/// QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC +/// method +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct QuerySigningInfoResponse { + /// val_signing_info is the signing info of requested val cons address + pub val_signing_info: Option, +} + +impl TryFrom + for QuerySigningInfoResponse +{ + type Error = ErrorReport; + + fn try_from( + proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::QuerySigningInfoResponse, + ) -> Result { + Ok(QuerySigningInfoResponse { + val_signing_info: proto.val_signing_info.map(TryFrom::try_from).transpose()?, + }) + } +} + +impl From for proto::cosmos::slashing::v1beta1::QuerySigningInfoResponse { + fn from(signing_info_response: QuerySigningInfoResponse) -> Self { + proto::cosmos::slashing::v1beta1::QuerySigningInfoResponse { + val_signing_info: signing_info_response.val_signing_info.map(Into::into), + } + } +} diff --git a/cosmrs/src/slashing/query_signing_infos_request.rs b/cosmrs/src/slashing/query_signing_infos_request.rs new file mode 100644 index 00000000..8ad36d75 --- /dev/null +++ b/cosmrs/src/slashing/query_signing_infos_request.rs @@ -0,0 +1,26 @@ +use crate::base::query::PageRequest; +use crate::proto; + +/// QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC +/// method +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct QuerySigningInfosRequest { + /// Pagination control of the request + pub pagination: Option, +} + +impl From for QuerySigningInfosRequest { + fn from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::QuerySigningInfosRequest) -> Self { + QuerySigningInfosRequest { + pagination: proto.pagination.map(Into::into), + } + } +} + +impl From for proto::cosmos::slashing::v1beta1::QuerySigningInfosRequest { + fn from(signing_infos_request: QuerySigningInfosRequest) -> Self { + proto::cosmos::slashing::v1beta1::QuerySigningInfosRequest { + pagination: signing_infos_request.pagination.map(Into::into), + } + } +} diff --git a/cosmrs/src/slashing/query_signing_infos_response.rs b/cosmrs/src/slashing/query_signing_infos_response.rs new file mode 100644 index 00000000..936cc9d7 --- /dev/null +++ b/cosmrs/src/slashing/query_signing_infos_response.rs @@ -0,0 +1,48 @@ +use crate::base::query::PageResponse; +use crate::slashing::ValidatorSigningInfo; +use crate::{proto, ErrorReport, Result}; + +/// QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC +/// method +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct QuerySigningInfosResponse { + /// info is the signing info of all validators + pub info: Vec, + + /// pagination information + pub pagination: Option, +} + +impl TryFrom + for QuerySigningInfosResponse +{ + type Error = ErrorReport; + + fn try_from( + proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::QuerySigningInfosResponse, + ) -> Result { + Ok(QuerySigningInfosResponse { + info: proto + .info + .into_iter() + .map(TryInto::try_into) + .collect::>()?, + pagination: proto.pagination.map(Into::into), + }) + } +} + +impl From + for proto::cosmos::slashing::v1beta1::QuerySigningInfosResponse +{ + fn from(signing_infos_response: QuerySigningInfosResponse) -> Self { + proto::cosmos::slashing::v1beta1::QuerySigningInfosResponse { + info: signing_infos_response + .info + .into_iter() + .map(Into::into) + .collect(), + pagination: signing_infos_response.pagination.map(Into::into), + } + } +} diff --git a/cosmrs/src/slashing/signing_info.rs b/cosmrs/src/slashing/signing_info.rs new file mode 100644 index 00000000..4bb51e81 --- /dev/null +++ b/cosmrs/src/slashing/signing_info.rs @@ -0,0 +1,35 @@ +use crate::slashing::validator_signing_info::ValidatorSigningInfo; +use crate::{proto, AccountId, ErrorReport, Result}; + +/// SigningInfo stores validator signing info of corresponding address. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SigningInfo { + /// address is the validator address. + pub address: AccountId, + + /// validator_signing_info represents the signing info of this validator. + pub validator_signing_info: Option, +} + +impl TryFrom for SigningInfo { + type Error = ErrorReport; + + fn try_from(proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::SigningInfo) -> Result { + Ok(SigningInfo { + address: proto.address.parse()?, + validator_signing_info: proto + .validator_signing_info + .map(TryInto::try_into) + .transpose()?, + }) + } +} + +impl From for cosmos_sdk_proto::cosmos::slashing::v1beta1::SigningInfo { + fn from(signing_info: SigningInfo) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::SigningInfo { + address: signing_info.address.to_string(), + validator_signing_info: signing_info.validator_signing_info.map(Into::into), + } + } +} diff --git a/cosmrs/src/slashing/validator_missed_blocks.rs b/cosmrs/src/slashing/validator_missed_blocks.rs new file mode 100644 index 00000000..f6dcd62e --- /dev/null +++ b/cosmrs/src/slashing/validator_missed_blocks.rs @@ -0,0 +1,39 @@ +use crate::proto; +use crate::slashing::MissedBlock; + +/// ValidatorMissedBlocks contains array of missed blocks of corresponding +/// address. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ValidatorMissedBlocks { + /// address is the validator address. + pub address: String, + + /// missed_blocks is an array of missed blocks by the validator. + pub missed_blocks: Vec, +} + +impl From for ValidatorMissedBlocks { + fn from( + proto: cosmos_sdk_proto::cosmos::slashing::v1beta1::ValidatorMissedBlocks, + ) -> ValidatorMissedBlocks { + ValidatorMissedBlocks { + address: proto.address, + missed_blocks: proto.missed_blocks.into_iter().map(Into::into).collect(), + } + } +} + +impl From + for cosmos_sdk_proto::cosmos::slashing::v1beta1::ValidatorMissedBlocks +{ + fn from(missed_blocks: ValidatorMissedBlocks) -> Self { + cosmos_sdk_proto::cosmos::slashing::v1beta1::ValidatorMissedBlocks { + address: missed_blocks.address, + missed_blocks: missed_blocks + .missed_blocks + .into_iter() + .map(Into::into) + .collect(), + } + } +} diff --git a/cosmrs/src/slashing/validator_signing_info.rs b/cosmrs/src/slashing/validator_signing_info.rs new file mode 100644 index 00000000..c79aa6cf --- /dev/null +++ b/cosmrs/src/slashing/validator_signing_info.rs @@ -0,0 +1,77 @@ +use crate::{proto, AccountId, ErrorReport, Result}; +use cosmos_sdk_proto::Timestamp; +use tendermint::time::Time; + +/// ValidatorSigningInfo defines a validator's signing info for monitoring their +/// liveness activity. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ValidatorSigningInfo { + /// Address of the validator + pub address: AccountId, + + /// Height at which validator was first a candidate OR was unjailed + pub start_height: i64, + + /// Index which is incremented each time the validator was a bonded + /// in a block and may have signed a precommit or not. This in conjunction with the + /// `SignedBlocksWindow` param determines the index in the `MissedBlocksBitArray`. + pub index_offset: i64, + + /// Timestamp until which the validator is jailed due to liveness downtime. + pub jailed_until: Option