use cid::{Cid, Version};
use fil_actor_verifreg_state::v10::AllocationID;
use fvm_ipld_encoding::tuple::*;
use fvm_ipld_encoding::BytesSer;
use fvm_shared3::address::Address;
use fvm_shared3::clock::ChainEpoch;
use fvm_shared3::commcid::{FIL_COMMITMENT_UNSEALED, SHA2_256_TRUNC254_PADDED};
use fvm_shared3::crypto::signature::Signature;
use fvm_shared3::econ::TokenAmount;
use fvm_shared3::piece::PaddedPieceSize;
use libipld_core::ipld::Ipld;
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::convert::{TryFrom, TryInto};
pub fn is_piece_cid(c: &Cid) -> bool {
c.version() == Version::V1
&& c.codec() == FIL_COMMITMENT_UNSEALED
&& c.hash().code() == SHA2_256_TRUNC254_PADDED
&& c.hash().size() == 32
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Label {
String(String),
Bytes(Vec<u8>),
}
impl Serialize for Label {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Label::String(v) => v.serialize(serializer),
Label::Bytes(v) => BytesSer(v).serialize(serializer),
}
}
}
impl TryFrom<Ipld> for Label {
type Error = String;
fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
match ipld {
Ipld::String(s) => Ok(Label::String(s)),
Ipld::Bytes(b) => Ok(Label::Bytes(b)),
other => Err(format!(
"Expected `Ipld::String` or `Ipld::Bytes`, got {:#?}",
other
)),
}
}
}
impl<'de> Deserialize<'de> for Label {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ipld::deserialize(deserializer).and_then(|ipld| ipld.try_into().map_err(de::Error::custom))
}
}
impl Label {
pub fn len(&self) -> usize {
match self {
Label::String(s) => s.len(),
Label::Bytes(b) => b.len(),
}
}
pub fn is_empty(&self) -> bool {
match self {
Label::String(s) => s.is_empty(),
Label::Bytes(b) => b.is_empty(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
pub struct DealProposal {
pub piece_cid: Cid,
pub piece_size: PaddedPieceSize,
pub verified_deal: bool,
pub client: Address,
pub provider: Address,
pub label: Label,
pub start_epoch: ChainEpoch,
pub end_epoch: ChainEpoch,
pub storage_price_per_epoch: TokenAmount,
pub provider_collateral: TokenAmount,
pub client_collateral: TokenAmount,
}
impl DealProposal {
pub fn duration(&self) -> ChainEpoch {
self.end_epoch - self.start_epoch
}
pub fn total_storage_fee(&self) -> TokenAmount {
self.storage_price_per_epoch.clone() * self.duration() as u64
}
pub fn client_balance_requirement(&self) -> TokenAmount {
&self.client_collateral + self.total_storage_fee()
}
pub fn provider_balance_requirement(&self) -> &TokenAmount {
&self.provider_collateral
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
pub struct ClientDealProposal {
pub proposal: DealProposal,
pub client_signature: Signature,
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Serialize_tuple, Deserialize_tuple)]
pub struct DealState {
pub sector_start_epoch: ChainEpoch,
pub last_updated_epoch: ChainEpoch,
pub slash_epoch: ChainEpoch,
pub verified_claim: AllocationID,
}