use crate::cross::IpcEnvelope;
use crate::subnet_id::SubnetID;
use crate::HumanReadable;
use cid::multihash::Code;
use cid::multihash::MultihashDigest;
use cid::Cid;
use ethers::utils::hex;
use fvm_ipld_encoding::DAG_CBOR;
use fvm_shared::address::Address;
use fvm_shared::clock::ChainEpoch;
use fvm_shared::econ::TokenAmount;
use lazy_static::lazy_static;
use serde::ser::SerializeSeq;
use serde::{Deserialize, Serialize, Serializer};
use serde_with::serde_as;
use std::fmt::{Display, Formatter};
lazy_static! {
pub static ref CHECKPOINT_GENESIS_CID: Cid =
Cid::new_v1(DAG_CBOR, Code::Blake2b256.digest("genesis".as_bytes()));
pub static ref VALIDATOR_REWARD_FIELDS: Vec<String> = vec!["address".to_owned(), "uint64".to_owned()];
}
pub type Signature = Vec<u8>;
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct QuorumReachedEvent {
pub obj_kind: u8,
pub height: ChainEpoch,
pub obj_hash: Vec<u8>,
pub quorum_weight: TokenAmount,
}
impl Display for QuorumReachedEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"QuorumReachedEvent<height: {}, checkpoint: {}, quorum_weight: {}>",
self.height,
hex::encode(&self.obj_hash),
self.quorum_weight
)
}
}
#[serde_as]
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct BottomUpCheckpointBundle {
pub checkpoint: BottomUpCheckpoint,
#[serde_as(as = "Vec<HumanReadable>")]
pub signatures: Vec<Signature>,
pub signatories: Vec<Address>,
}
#[serde_as]
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct BottomUpMsgBatch {
#[serde_as(as = "HumanReadable")]
pub subnet_id: SubnetID,
pub block_height: ChainEpoch,
pub msgs: Vec<IpcEnvelope>,
}
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct CompressedActivityRollup {
pub consensus: consensus::CompressedSummary,
}
pub mod consensus {
use fvm_shared::address::Address;
use serde::{Deserialize, Serialize};
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct AggregatedStats {
pub total_active_validators: u64,
pub total_num_blocks_committed: u64,
}
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct ValidatorData {
pub validator: Address,
pub blocks_committed: u64,
}
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct FullSummary {
pub stats: AggregatedStats,
pub data: Vec<ValidatorData>,
}
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct CompressedSummary {
pub stats: AggregatedStats,
pub data_root_commitment: Vec<u8>,
}
}
#[serde_as]
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct BottomUpCheckpoint {
pub subnet_id: SubnetID,
pub block_height: ChainEpoch,
#[serde_as(as = "HumanReadable")]
pub block_hash: Vec<u8>,
pub next_configuration_number: u64,
pub msgs: Vec<IpcEnvelope>,
pub activity_rollup: CompressedActivityRollup,
}
pub fn serialize_vec_bytes_to_vec_hex<T: AsRef<[u8]>, S>(
data: &[T],
s: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = s.serialize_seq(Some(data.len()))?;
for element in data {
seq.serialize_element(&hex::encode(element))?;
}
seq.end()
}
#[cfg(test)]
mod tests {
use crate::address::IPCAddress;
use crate::checkpoint::Signature;
use crate::subnet_id::SubnetID;
use crate::HumanReadable;
use fvm_shared::address::Address;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use std::str::FromStr;
#[test]
fn test_serialization_vec_vec_u8() {
#[serde_as]
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct T {
#[serde_as(as = "Vec<HumanReadable>")]
d: Vec<Signature>,
#[serde_as(as = "HumanReadable")]
subnet_id: SubnetID,
#[serde_as(as = "HumanReadable")]
ipc_address: IPCAddress,
}
let subnet_id =
SubnetID::from_str("/r31415926/f2xwzbdu7z5sam6hc57xxwkctciuaz7oe5omipwbq").unwrap();
let ipc_address = IPCAddress::new(&subnet_id, &Address::new_id(101)).unwrap();
let t = T {
d: vec![vec![1; 30], vec![2; 30]],
subnet_id,
ipc_address,
};
let s = serde_json::to_string(&t).unwrap();
assert_eq!(
s,
r#"{"d":["010101010101010101010101010101010101010101010101010101010101","020202020202020202020202020202020202020202020202020202020202"],"subnet_id":"/r31415926/f2xwzbdu7z5sam6hc57xxwkctciuaz7oe5omipwbq","ipc_address":"/r31415926/f2xwzbdu7z5sam6hc57xxwkctciuaz7oe5omipwbq:f0101"}"#
);
let r: T = serde_json::from_str(&s).unwrap();
assert_eq!(r, t);
}
}