use cid::Cid;
use fvm_shared::{
address::Address, clock::ChainEpoch, crypto::signature::Signature, econ::TokenAmount, MethodNum,
};
use iroh_base::hash::Hash;
use iroh_base::key::NodeId;
use recall_fendermint_actor_blobs_shared::state::SubscriptionId;
use recall_ipc_api::subnet_id::SubnetID;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[allow(clippy::large_enum_variant)]
pub enum IpcMessage {
BottomUpResolve(SignedRelayedMessage<CertifiedMessage<BottomUpCheckpoint>>),
BottomUpExec(CertifiedMessage<BottomUpCheckpoint>),
TopDownExec(ParentFinality),
DebitCreditAccounts,
BlobPending(PendingBlob),
BlobFinalized(FinalizedBlob),
ReadRequestPending(PendingReadRequest),
ReadRequestClosed(ClosedReadRequest),
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct RelayedMessage<T> {
pub message: T,
pub relayer: Address,
pub sequence: u64,
pub gas_limit: u64,
pub gas_fee_cap: TokenAmount,
pub gas_premium: TokenAmount,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct SignedRelayedMessage<T> {
pub message: RelayedMessage<T>,
pub signature: Signature,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct CertifiedMessage<T> {
pub message: T,
pub certificate: MultiSig,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct MultiSig {
pub signatures: Vec<ValidatorSignature>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct ValidatorSignature {
pub validator: Address,
pub signature: Signature,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct BottomUpCheckpoint {
pub subnet_id: SubnetID,
pub height: ChainEpoch,
pub next_validator_set_id: u64,
pub bottom_up_messages: Cid, }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct ParentFinality {
pub height: ChainEpoch,
pub block_hash: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct FinalizedBlob {
pub subscriber: Address,
pub hash: Hash,
pub size: u64,
pub id: SubscriptionId,
pub source: NodeId,
pub succeeded: bool,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct PendingBlob {
pub subscriber: Address,
pub hash: Hash,
pub size: u64,
pub id: SubscriptionId,
pub source: NodeId,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct ClosedReadRequest {
pub id: Hash,
pub blob_hash: Hash,
pub offset: u32,
pub len: u32,
pub callback: (Address, MethodNum),
pub response: Vec<u8>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct PendingReadRequest {
pub id: Hash,
pub blob_hash: Hash,
pub offset: u32,
pub len: u32,
pub callback: (Address, MethodNum),
}
#[cfg(feature = "arb")]
mod arb {
use crate::ipc::ParentFinality;
use fvm_shared::crypto::signature::Signature;
use quickcheck::{Arbitrary, Gen};
use recall_fendermint_testing::arb::{ArbAddress, ArbCid, ArbSubnetID, ArbTokenAmount};
use super::{
BottomUpCheckpoint, CertifiedMessage, IpcMessage, MultiSig, RelayedMessage,
SignedRelayedMessage, ValidatorSignature,
};
impl Arbitrary for IpcMessage {
fn arbitrary(g: &mut Gen) -> Self {
match u8::arbitrary(g) % 3 {
0 => IpcMessage::BottomUpResolve(Arbitrary::arbitrary(g)),
1 => IpcMessage::BottomUpExec(Arbitrary::arbitrary(g)),
_ => IpcMessage::TopDownExec(Arbitrary::arbitrary(g)),
}
}
}
impl<T: Arbitrary> Arbitrary for SignedRelayedMessage<T> {
fn arbitrary(g: &mut Gen) -> Self {
Self {
message: RelayedMessage::arbitrary(g),
signature: Signature::arbitrary(g),
}
}
}
impl<T: Arbitrary> Arbitrary for RelayedMessage<T> {
fn arbitrary(g: &mut Gen) -> Self {
Self {
message: T::arbitrary(g),
relayer: ArbAddress::arbitrary(g).0,
sequence: u64::arbitrary(g),
gas_limit: u64::arbitrary(g),
gas_fee_cap: ArbTokenAmount::arbitrary(g).0,
gas_premium: ArbTokenAmount::arbitrary(g).0,
}
}
}
impl<T: Arbitrary> Arbitrary for CertifiedMessage<T> {
fn arbitrary(g: &mut Gen) -> Self {
Self {
message: T::arbitrary(g),
certificate: Arbitrary::arbitrary(g),
}
}
}
impl Arbitrary for ValidatorSignature {
fn arbitrary(g: &mut Gen) -> Self {
Self {
validator: ArbAddress::arbitrary(g).0,
signature: Signature::arbitrary(g),
}
}
}
impl Arbitrary for MultiSig {
fn arbitrary(g: &mut Gen) -> Self {
let mut signatures = Vec::new();
for _ in 0..*g.choose(&[1, 3, 5]).unwrap() {
signatures.push(ValidatorSignature::arbitrary(g));
}
Self { signatures }
}
}
impl Arbitrary for BottomUpCheckpoint {
fn arbitrary(g: &mut Gen) -> Self {
Self {
subnet_id: ArbSubnetID::arbitrary(g).0,
height: u32::arbitrary(g).into(),
next_validator_set_id: Arbitrary::arbitrary(g),
bottom_up_messages: ArbCid::arbitrary(g).0,
}
}
}
impl Arbitrary for ParentFinality {
fn arbitrary(g: &mut Gen) -> Self {
Self {
height: u32::arbitrary(g).into(),
block_hash: Vec::arbitrary(g),
}
}
}
}