1use crate::cross::IpcEnvelope;
6use crate::subnet_id::SubnetID;
7use crate::HumanReadable;
8use cid::multihash::Code;
9use cid::multihash::MultihashDigest;
10use cid::Cid;
11use ethers::utils::hex;
12use fvm_ipld_encoding::DAG_CBOR;
13use fvm_shared::address::Address;
14use fvm_shared::clock::ChainEpoch;
15use fvm_shared::econ::TokenAmount;
16use lazy_static::lazy_static;
17use serde::ser::SerializeSeq;
18use serde::{Deserialize, Serialize, Serializer};
19use serde_with::serde_as;
20use std::fmt::{Display, Formatter};
21
22lazy_static! {
23 pub static ref CHECKPOINT_GENESIS_CID: Cid =
27 Cid::new_v1(DAG_CBOR, Code::Blake2b256.digest("genesis".as_bytes()));
28 pub static ref VALIDATOR_REWARD_FIELDS: Vec<String> = vec!["address".to_owned(), "uint64".to_owned()];
30}
31
32pub type Signature = Vec<u8>;
33
34#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
36pub struct QuorumReachedEvent {
37 pub obj_kind: u8,
38 pub height: ChainEpoch,
39 pub obj_hash: Vec<u8>,
41 pub quorum_weight: TokenAmount,
42}
43
44impl Display for QuorumReachedEvent {
45 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46 write!(
47 f,
48 "QuorumReachedEvent<height: {}, checkpoint: {}, quorum_weight: {}>",
49 self.height,
50 hex::encode(&self.obj_hash),
51 self.quorum_weight
52 )
53 }
54}
55
56#[serde_as]
58#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
59pub struct BottomUpCheckpointBundle {
60 pub checkpoint: BottomUpCheckpoint,
61 #[serde_as(as = "Vec<HumanReadable>")]
63 pub signatures: Vec<Signature>,
64 pub signatories: Vec<Address>,
66}
67
68#[serde_as]
70#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
71pub struct BottomUpMsgBatch {
72 #[serde_as(as = "HumanReadable")]
74 pub subnet_id: SubnetID,
75 pub block_height: ChainEpoch,
77 pub msgs: Vec<IpcEnvelope>,
79}
80
81#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
83pub struct CompressedActivityRollup {
84 pub consensus: consensus::CompressedSummary,
85}
86
87pub mod consensus {
90 use fvm_shared::address::Address;
91 use serde::{Deserialize, Serialize};
92
93 #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
95 pub struct AggregatedStats {
96 pub total_active_validators: u64,
98 pub total_num_blocks_committed: u64,
100 }
101
102 #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
105 pub struct ValidatorData {
106 pub validator: Address,
108 pub blocks_committed: u64,
110 }
111
112 #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
114 pub struct FullSummary {
115 pub stats: AggregatedStats,
116 pub data: Vec<ValidatorData>,
118 }
119
120 #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
122 pub struct CompressedSummary {
123 pub stats: AggregatedStats,
124 pub data_root_commitment: Vec<u8>,
126 }
127}
128
129#[serde_as]
130#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
131pub struct BottomUpCheckpoint {
132 pub subnet_id: SubnetID,
135 pub block_height: ChainEpoch,
138 #[serde_as(as = "HumanReadable")]
140 pub block_hash: Vec<u8>,
141 pub next_configuration_number: u64,
145 pub msgs: Vec<IpcEnvelope>,
147 pub activity_rollup: CompressedActivityRollup,
149}
150
151pub fn serialize_vec_bytes_to_vec_hex<T: AsRef<[u8]>, S>(
152 data: &[T],
153 s: S,
154) -> Result<S::Ok, S::Error>
155where
156 S: Serializer,
157{
158 let mut seq = s.serialize_seq(Some(data.len()))?;
159 for element in data {
160 seq.serialize_element(&hex::encode(element))?;
161 }
162 seq.end()
163}
164
165#[cfg(test)]
166mod tests {
167 use crate::address::IPCAddress;
168 use crate::checkpoint::Signature;
169 use crate::subnet_id::SubnetID;
170 use crate::HumanReadable;
171 use fvm_shared::address::Address;
172 use serde::{Deserialize, Serialize};
173 use serde_with::serde_as;
174 use std::str::FromStr;
175
176 #[test]
177 fn test_serialization_vec_vec_u8() {
178 #[serde_as]
179 #[derive(Debug, Serialize, Deserialize, PartialEq)]
180 struct T {
181 #[serde_as(as = "Vec<HumanReadable>")]
182 d: Vec<Signature>,
183 #[serde_as(as = "HumanReadable")]
184 subnet_id: SubnetID,
185 #[serde_as(as = "HumanReadable")]
186 ipc_address: IPCAddress,
187 }
188
189 let subnet_id =
190 SubnetID::from_str("/r31415926/f2xwzbdu7z5sam6hc57xxwkctciuaz7oe5omipwbq").unwrap();
191 let ipc_address = IPCAddress::new(&subnet_id, &Address::new_id(101)).unwrap();
192
193 let t = T {
194 d: vec![vec![1; 30], vec![2; 30]],
195 subnet_id,
196 ipc_address,
197 };
198 let s = serde_json::to_string(&t).unwrap();
199 assert_eq!(
200 s,
201 r#"{"d":["010101010101010101010101010101010101010101010101010101010101","020202020202020202020202020202020202020202020202020202020202"],"subnet_id":"/r31415926/f2xwzbdu7z5sam6hc57xxwkctciuaz7oe5omipwbq","ipc_address":"/r31415926/f2xwzbdu7z5sam6hc57xxwkctciuaz7oe5omipwbq:f0101"}"#
202 );
203
204 let r: T = serde_json::from_str(&s).unwrap();
205
206 assert_eq!(r, t);
207 }
208}