diff --git a/blockchain/blocks/Cargo.toml b/blockchain/blocks/Cargo.toml index 23c7666799ff..c9c8b5374b96 100644 --- a/blockchain/blocks/Cargo.toml +++ b/blockchain/blocks/Cargo.toml @@ -10,4 +10,5 @@ crypto = {path = "../../crypto"} message = {path = "../../vm/message"} clock = {path = "../../node/clock"} cid = "0.3.1" -multihash = "0.8.0" \ No newline at end of file +multihash = "0.8.0" +derive_builder = "0.9" diff --git a/blockchain/blocks/src/block.rs b/blockchain/blocks/src/block.rs index 9ea315fb2fad..ebc5665ed058 100644 --- a/blockchain/blocks/src/block.rs +++ b/blockchain/blocks/src/block.rs @@ -9,6 +9,7 @@ use address::Address; use cid::{Cid, Codec, Prefix, Version}; use clock::ChainEpoch; use crypto::Signature; +use derive_builder::Builder; use message::{SignedMessage, UnsignedMessage}; use multihash::Hash; @@ -21,52 +22,94 @@ struct PoStCandidate {} struct PoStRandomness {} struct PoStProof {} +fn template_cid() -> Cid { + Cid::new(Codec::DagCBOR, Version::V1, &[]) +} + /// BlockHeader defines header of a block in the Filecoin blockchain -#[derive(Clone, Debug, PartialEq)] +/// +/// Usage: +/// ``` +/// use blocks::{BlockHeader, TipSetKeys, Ticket, TxMeta}; +/// use address::Address; +/// use cid::{Cid, Codec, Prefix, Version}; +/// use clock::ChainEpoch; +/// +/// BlockHeader::builder() +/// .parents(TipSetKeys::default()) +/// .miner_address(Address::new_id(0).unwrap()) +/// .bls_aggregate(vec![]) +/// .weight(0) //optional +/// .epoch(ChainEpoch::default()) //optional +/// .messages(TxMeta::default()) //optional +/// .message_receipts(Cid::new(Codec::DagCBOR, Version::V1, &[])) //optional +/// .state_root(Cid::new(Codec::DagCBOR, Version::V1, &[])) //optional +/// .timestamp(0) //optional +/// .ticket(Ticket::default()) //optional +/// .build() +/// .unwrap(); +/// ``` +#[derive(Clone, Debug, PartialEq, Builder)] +#[builder(name = "BlockHeaderBuilder")] pub struct BlockHeader { - /// CHAIN LINKING - /// + // CHAIN LINKING /// Parents is the set of parents this block was based on. Typically one, /// but can be several in the case where there were multiple winning ticket- /// holders for an epoch pub parents: TipSetKeys, + /// weight is the aggregate chain weight of the parent set + #[builder(default)] pub weight: u64, + /// epoch is the period in which a new block is generated. There may be multiple rounds in an epoch + #[builder(default)] pub epoch: ChainEpoch, - /// MINER INFO - /// + // MINER INFO /// miner_address is the address of the miner actor that mined this block pub miner_address: Address, - /// STATE - /// + // STATE /// messages contains the merkle links for bls_messages and secp_messages + #[builder(default)] pub messages: TxMeta, + /// message_receipts is the Cid of the root of an array of MessageReceipts + #[builder(default = "template_cid()")] pub message_receipts: Cid, + /// state_root is a cid pointer to the state tree after application of the transactions state transitions + #[builder(default = "template_cid()")] pub state_root: Cid, - /// CONSENSUS - /// + // CONSENSUS /// timestamp, in seconds since the Unix epoch, at which this block was created + #[builder(default)] pub timestamp: u64, + /// ticket is the ticket submitted with this block + #[builder(default)] pub ticket: Ticket, // SIGNATURES - // + /// aggregate signature of miner in block pub bls_aggregate: Signature, - /// CACHE - /// + // CACHE + #[builder(default = "template_cid()")] pub cached_cid: Cid, + #[builder(default)] pub cached_bytes: u8, } +impl BlockHeader { + pub fn builder() -> BlockHeaderBuilder { + BlockHeaderBuilder::default() + } +} + /// Block defines a full block pub struct Block { header: BlockHeader, @@ -82,6 +125,15 @@ pub struct TxMeta { pub secp_messages: Cid, } +impl Default for TxMeta { + fn default() -> Self { + Self { + bls_messages: template_cid(), + secp_messages: template_cid(), + } + } +} + /// ElectionPoStVerifyInfo seems to be connected to VRF /// see https://github.com/filecoin-project/lotus/blob/master/chain/sync.go#L1099 struct ElectionPoStVerifyInfo { diff --git a/blockchain/blocks/src/ticket.rs b/blockchain/blocks/src/ticket.rs index 3a48eefd3776..47d0494faf4a 100644 --- a/blockchain/blocks/src/ticket.rs +++ b/blockchain/blocks/src/ticket.rs @@ -6,8 +6,15 @@ use crypto::VRFResult; /// A Ticket is a marker of a tick of the blockchain's clock. It is the source /// of randomness for proofs of storage and leader election. It is generated /// by the miner of a block using a VRF and a VDF. -#[derive(Clone, Debug, PartialEq, PartialOrd, Eq)] +#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Default)] pub struct Ticket { /// A proof output by running a VRF on the VDFResult of the parent ticket pub vrfproof: VRFResult, } + +impl Ticket { + /// Ticket constructor + pub fn new(vrfproof: VRFResult) -> Self { + Self { vrfproof } + } +} diff --git a/blockchain/blocks/src/tipset.rs b/blockchain/blocks/src/tipset.rs index 307c62041c0a..fef94ee1f919 100644 --- a/blockchain/blocks/src/tipset.rs +++ b/blockchain/blocks/src/tipset.rs @@ -9,22 +9,38 @@ use super::errors::Error; use super::ticket::Ticket; use cid::Cid; use clock::ChainEpoch; -/// TipSet is an immutable set of blocks at the same height with the same parent set -/// Blocks in a tipset are canonically ordered by ticket size -#[derive(Clone, PartialEq, Debug)] -pub struct Tipset { - blocks: Vec, - key: TipSetKeys, -} /// TipSetKeys is a set of CIDs forming a unique key for a TipSet /// Equal keys will have equivalent iteration order, but note that the CIDs are *not* maintained in /// the same order as the canonical iteration order of blocks in a tipset (which is by ticket) -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct TipSetKeys { pub cids: Vec, } +impl TipSetKeys { + /// equals checks whether the set contains exactly the same CIDs as another. + fn equals(&self, key: TipSetKeys) -> bool { + if self.cids.len() != key.cids.len() { + return false; + } + for i in 0..key.cids.len() { + if self.cids[i] != key.cids[i] { + return false; + } + } + true + } +} + +/// TipSet is an immutable set of blocks at the same height with the same parent set +/// Blocks in a tipset are canonically ordered by ticket size +#[derive(Clone, PartialEq, Debug)] +pub struct Tipset { + blocks: Vec, + key: TipSetKeys, +} + impl Tipset { /// blocks returns vec of blocks from tipset pub fn blocks(&self) -> Vec { @@ -145,7 +161,7 @@ impl Tipset { self.blocks[0].parents.clone() } /// weight returns the tipset's calculated weight - fn weight(&self) -> u64 { + pub fn weight(&self) -> u64 { self.blocks[0].weight } /// tip_epoch returns the tipset's epoch @@ -154,21 +170,6 @@ impl Tipset { } } -impl TipSetKeys { - /// equals checks whether the set contains exactly the same CIDs as another. - fn equals(&self, key: TipSetKeys) -> bool { - if self.cids.len() != key.cids.len() { - return false; - } - for i in 0..key.cids.len() { - if self.cids[i] != key.cids[i] { - return false; - } - } - true - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crypto/src/vrf.rs b/crypto/src/vrf.rs index eba2b8b6722e..7ac717d4fdf1 100644 --- a/crypto/src/vrf.rs +++ b/crypto/src/vrf.rs @@ -13,7 +13,7 @@ impl VRFPublicKey { } /// VRFResult is the output from running a VRF -#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] +#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Default)] pub struct VRFResult(Vec); impl VRFResult { diff --git a/node/clock/src/lib.rs b/node/clock/src/lib.rs index 0010a1479622..461373cbeb4e 100644 --- a/node/clock/src/lib.rs +++ b/node/clock/src/lib.rs @@ -6,7 +6,7 @@ use chrono::{DateTime, NaiveDateTime, SecondsFormat, Utc}; const _ISO_FORMAT: &str = "%FT%X.%.9F"; const EPOCH_DURATION: i32 = 15; -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct ChainEpoch(i64); /// ChainEpochClock is used by the system node to assume weak clock synchrony amongst the other