use alloc::collections::BTreeMap;
use crate::{
consensus::{
ConsensusClientId, ConsensusStateId, StateCommitment, StateMachineHeight, StateMachineId,
},
error::Error,
host::StateMachine,
router::{GetRequest, GetResponse, PostRequest, Request},
};
use alloc::{string::ToString, vec::Vec};
use codec::{Decode, DecodeWithMemTracking, Encode};
use primitive_types::H256;
use sp_weights::Weight;
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
pub struct ConsensusMessage {
pub consensus_proof: Vec<u8>,
pub consensus_state_id: ConsensusStateId,
pub signer: Vec<u8>,
}
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
pub struct FraudProofMessage {
pub proof_1: Vec<u8>,
pub proof_2: Vec<u8>,
pub consensus_state_id: ConsensusStateId,
pub signer: Vec<u8>,
}
#[derive(
Debug,
Clone,
Encode,
Decode,
DecodeWithMemTracking,
scale_info::TypeInfo,
PartialEq,
Eq,
serde::Deserialize,
serde::Serialize,
)]
pub struct StateCommitmentHeight {
pub commitment: StateCommitment,
pub height: u64,
}
#[derive(
Debug,
Clone,
Encode,
Decode,
DecodeWithMemTracking,
scale_info::TypeInfo,
PartialEq,
Eq,
serde::Deserialize,
serde::Serialize,
)]
pub struct CreateConsensusState {
#[serde(with = "serde_hex_utils::as_hex")]
pub consensus_state: Vec<u8>,
#[serde(with = "serde_hex_utils::as_utf8_string")]
pub consensus_client_id: ConsensusClientId,
#[serde(with = "serde_hex_utils::as_utf8_string")]
pub consensus_state_id: ConsensusStateId,
pub unbonding_period: u64,
pub challenge_periods: BTreeMap<StateMachine, u64>,
pub state_machine_commitments: Vec<(StateMachineId, StateCommitmentHeight)>,
}
#[derive(
Debug, Clone, Encode, DecodeWithMemTracking, Decode, scale_info::TypeInfo, PartialEq, Eq,
)]
pub struct RequestMessage {
pub requests: Vec<PostRequest>,
pub proof: Proof,
pub signer: Vec<u8>,
}
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
pub struct ResponseMessage {
pub requests: Vec<GetRequest>,
pub proof: Proof,
pub signer: Vec<u8>,
}
impl ResponseMessage {
pub fn requests(&self) -> Vec<Request> {
self.requests.iter().cloned().map(Request::Get).collect()
}
pub fn proof(&self) -> &Proof {
&self.proof
}
}
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
pub enum TimeoutMessage {
Post {
requests: Vec<PostRequest>,
timeout_proof: Proof,
},
Get {
requests: Vec<GetRequest>,
},
}
impl TimeoutMessage {
pub fn requests(&self) -> Vec<Request> {
match self {
TimeoutMessage::Post { requests, .. } =>
requests.iter().cloned().map(Request::Post).collect(),
TimeoutMessage::Get { requests } =>
requests.iter().cloned().map(Request::Get).collect(),
}
}
pub fn timeout_proof(&self) -> Result<&Proof, Error> {
match self {
TimeoutMessage::Post { timeout_proof, .. } => Ok(timeout_proof),
_ => Err(Error::Custom("Method should not be called on Get request".to_string())),
}
}
}
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
#[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))]
pub struct Proof {
pub height: StateMachineHeight,
pub proof: Vec<u8>,
}
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
pub enum Message {
#[codec(index = 0)]
Consensus(ConsensusMessage),
#[codec(index = 1)]
FraudProof(FraudProofMessage),
#[codec(index = 2)]
Request(RequestMessage),
#[codec(index = 3)]
Response(ResponseMessage),
#[codec(index = 4)]
Timeout(TimeoutMessage),
}
#[derive(
Debug, Clone, Encode, Decode, DecodeWithMemTracking, scale_info::TypeInfo, PartialEq, Eq,
)]
pub struct MessageWithWeight {
pub message: Message,
pub weight: Weight,
}
pub trait Keccak256 {
fn keccak256(bytes: &[u8]) -> H256
where
Self: Sized;
}
pub fn hash_request<H: Keccak256>(req: &Request) -> H256 {
let encoded = req.encode();
H::keccak256(&encoded)
}
pub fn dedup_requests<H: Keccak256>(requests: &[Request]) -> Result<(), Error> {
let mut seen = alloc::collections::BTreeSet::new();
for req in requests {
if !seen.insert(hash_request::<H>(req)) {
return Err(Error::DuplicateRequest { meta: req.clone().into() });
}
}
Ok(())
}
pub fn hash_response<H: Keccak256>(res: &GetResponse) -> H256 {
hash_get_response::<H>(res)
}
pub fn hash_get_response<H: Keccak256>(res: &GetResponse) -> H256 {
H::keccak256(&res.encode())
}