// Copyright 2017 Parity Technologies (UK) Ltd. // This file is part of Polkadot. // Polkadot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Polkadot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . //! Block and header type definitions. #[cfg(feature = "std")] use primitives::bytes; use primitives::H256; use rstd::vec::Vec; use codec::{Input, Slicable}; use transaction::UncheckedTransaction; /// Used to refer to a block number. pub type Number = u64; /// Hash used to refer to a block hash. pub type HeaderHash = H256; /// Hash used to refer to a transaction hash. pub type TransactionHash = H256; /// Execution log (event) #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); impl Slicable for Log { fn decode(input: &mut I) -> Option { Vec::::decode(input).map(Log) } fn as_slice_then R>(&self, f: F) -> R { self.0.as_slice_then(f) } } impl ::codec::NonTrivialSlicable for Log { } /// The digest of a block, useful for light-clients. #[derive(Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct Digest { /// All logs that have happened in the block. pub logs: Vec, } impl Slicable for Digest { fn decode(input: &mut I) -> Option { Vec::::decode(input).map(|logs| Digest { logs }) } fn as_slice_then R>(&self, f: F) -> R { self.logs.as_slice_then(f) } } /// The block "body": A bunch of transactions. pub type Body = Vec; /// A Polkadot relay chain block. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] pub struct Block { /// The block header. pub header: Header, /// All relay-chain transactions. pub transactions: Body, } impl Slicable for Block { fn decode(input: &mut I) -> Option { let (header, transactions) = try_opt!(Slicable::decode(input)); Some(Block { header, transactions }) } fn to_vec(&self) -> Vec { let mut v = Vec::new(); v.extend(self.header.to_vec()); v.extend(self.transactions.to_vec()); v } fn as_slice_then R>(&self, f: F) -> R { f(self.to_vec().as_slice()) } } /// A relay chain block header. /// /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Header { /// Block parent's hash. pub parent_hash: HeaderHash, /// Block number. pub number: Number, /// State root after this transition. pub state_root: H256, /// The root of the trie that represents this block's transactions, indexed by a 32-byte integer. pub transaction_root: H256, /// The digest of activity on the block. pub digest: Digest, } impl Header { /// Create a new instance with default fields except `number`, which is given as an argument. pub fn from_block_number(number: Number) -> Self { Header { parent_hash: Default::default(), number, state_root: Default::default(), transaction_root: Default::default(), digest: Default::default(), } } } impl Slicable for Header { fn decode(input: &mut I) -> Option { Some(Header { parent_hash: try_opt!(Slicable::decode(input)), number: try_opt!(Slicable::decode(input)), state_root: try_opt!(Slicable::decode(input)), transaction_root: try_opt!(Slicable::decode(input)), digest: try_opt!(Slicable::decode(input)), }) } fn to_vec(&self) -> Vec { let mut v = Vec::new(); self.parent_hash.as_slice_then(|s| v.extend(s)); self.number.as_slice_then(|s| v.extend(s)); self.state_root.as_slice_then(|s| v.extend(s)); self.transaction_root.as_slice_then(|s| v.extend(s)); self.digest.as_slice_then(|s| v.extend(s)); v } fn as_slice_then R>(&self, f: F) -> R { f(self.to_vec().as_slice()) } } #[cfg(test)] mod tests { use super::*; use codec::Slicable; use substrate_serializer as ser; #[test] fn test_header_serialization() { let header = Header { parent_hash: 5.into(), number: 67, state_root: 3.into(), transaction_root: 6.into(), digest: Digest { logs: vec![Log(vec![1])] }, }; assert_eq!(ser::to_string_pretty(&header), r#"{ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005", "number": 67, "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", "transactionRoot": "0x0000000000000000000000000000000000000000000000000000000000000006", "digest": { "logs": [ "0x01" ] } }"#); let v = header.to_vec(); assert_eq!(Header::decode(&mut &v[..]).unwrap(), header); } }