-
Notifications
You must be signed in to change notification settings - Fork 99
/
Copy pathconsensus_state.rs
127 lines (107 loc) · 3.82 KB
/
consensus_state.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::convert::TryFrom;
use std::time::SystemTime;
use chrono::{TimeZone, Utc};
use prost_types::Timestamp;
use serde::Serialize;
use tendermint::{hash::Algorithm, time::Time, Hash};
use tendermint_proto::Protobuf;
use ibc_proto::ibc::lightclients::tendermint::v1::ConsensusState as RawConsensusState;
use crate::ics02_client::client_consensus::AnyConsensusState;
use crate::ics02_client::client_type::ClientType;
use crate::ics07_tendermint::error::{Error, Kind};
use crate::ics07_tendermint::header::Header;
use crate::ics23_commitment::commitment::CommitmentRoot;
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct ConsensusState {
pub timestamp: Time,
pub root: CommitmentRoot,
pub next_validators_hash: Hash,
}
impl ConsensusState {
pub fn new(root: CommitmentRoot, timestamp: Time, next_validators_hash: Hash) -> Self {
Self {
root,
timestamp,
next_validators_hash,
}
}
}
impl crate::ics02_client::client_consensus::ConsensusState for ConsensusState {
fn client_type(&self) -> ClientType {
ClientType::Tendermint
}
fn root(&self) -> &CommitmentRoot {
&self.root
}
fn validate_basic(&self) -> Result<(), Box<dyn std::error::Error>> {
unimplemented!()
}
fn wrap_any(self) -> AnyConsensusState {
AnyConsensusState::Tendermint(self)
}
}
impl Protobuf<RawConsensusState> for ConsensusState {}
impl TryFrom<RawConsensusState> for ConsensusState {
type Error = Error;
fn try_from(raw: RawConsensusState) -> Result<Self, Self::Error> {
let proto_timestamp = raw
.timestamp
.ok_or_else(|| Kind::InvalidRawConsensusState.context("missing timestamp"))?;
Ok(Self {
root: raw
.root
.ok_or_else(|| Kind::InvalidRawConsensusState.context("missing commitment root"))?
.hash
.into(),
timestamp: Utc
.timestamp(proto_timestamp.seconds, proto_timestamp.nanos as u32)
.into(),
next_validators_hash: Hash::from_bytes(Algorithm::Sha256, &raw.next_validators_hash)
.map_err(|e| Kind::InvalidRawConsensusState.context(e.to_string()))?,
})
}
}
impl From<ConsensusState> for RawConsensusState {
fn from(value: ConsensusState) -> Self {
RawConsensusState {
timestamp: Some(Timestamp::from(SystemTime::from(value.timestamp))),
root: Some(ibc_proto::ibc::core::commitment::v1::MerkleRoot {
hash: value.root.into_vec(),
}),
next_validators_hash: value.next_validators_hash.as_bytes().to_vec(),
}
}
}
impl From<tendermint::block::Header> for ConsensusState {
fn from(header: tendermint::block::Header) -> Self {
Self {
root: CommitmentRoot::from_bytes(header.app_hash.as_ref()),
timestamp: header.time,
next_validators_hash: header.next_validators_hash,
}
}
}
impl From<Header> for ConsensusState {
fn from(header: Header) -> Self {
Self::from(header.signed_header.header)
}
}
#[cfg(test)]
mod tests {
use tendermint_rpc::endpoint::abci_query::AbciQuery;
use crate::test::test_serialization_roundtrip;
#[test]
fn serialization_roundtrip_no_proof() {
let json_data =
include_str!("../../tests/support/query/serialization/consensus_state.json");
println!("json_data: {:?}", json_data);
test_serialization_roundtrip::<AbciQuery>(json_data);
}
#[test]
fn serialization_roundtrip_with_proof() {
let json_data =
include_str!("../../tests/support/query/serialization/consensus_state_proof.json");
println!("json_data: {:?}", json_data);
test_serialization_roundtrip::<AbciQuery>(json_data);
}
}