diff --git a/griffin-core/src/executive.rs b/griffin-core/src/executive.rs index 5594668..afa19ab 100644 --- a/griffin-core/src/executive.rs +++ b/griffin-core/src/executive.rs @@ -31,9 +31,10 @@ use crate::{ conway_minted_tx_from_cbor, mk_utxo_for_babbage_tx, }, ensure, + header::ExtendedHeader, types::{Block, BlockNumber, DispatchResult, Header, Input, Output, Transaction, UTxOError}, utxo_set::TransparentUtxoSet, - EXTRINSIC_KEY, HEADER_KEY, HEIGHT_KEY, LOG_TARGET, + DATA_KEY, EXTRINSIC_KEY, HEADER_KEY, HEIGHT_KEY, LOG_TARGET, }; use crate::{SLOT_LENGTH, ZERO_SLOT, ZERO_TIME}; use alloc::{collections::btree_set::BTreeSet, string::String, vec::Vec}; @@ -345,6 +346,11 @@ where // performing pool validations and other off-chain runtime calls. sp_io::storage::set(HEIGHT_KEY, &header.number().encode()); + if let Some(mut data) = ExtendedHeader::get_pcdata_storage() { + data.count += 1; + sp_io::storage::set(DATA_KEY, &(data).encode()); + } + // griffin blocks always allow user transactions. ExtrinsicInclusionMode::AllExtrinsics } @@ -396,6 +402,9 @@ where let raw_state_root = &sp_io::storage::root(StateVersion::V1)[..]; let state_root =
::Hash::decode(&mut &raw_state_root[..]).unwrap(); header.set_state_root(state_root); + if let Some(data) = ExtendedHeader::get_pcdata_storage() { + header.set_pcdata(data); + } debug!(target: LOG_TARGET, "finalizing block {:?}", header); header diff --git a/griffin-core/src/genesis/config_builder.rs b/griffin-core/src/genesis/config_builder.rs index 79ab3f7..aa397e2 100644 --- a/griffin-core/src/genesis/config_builder.rs +++ b/griffin-core/src/genesis/config_builder.rs @@ -3,14 +3,19 @@ use crate::{ ensure, h224::H224, + header::PCData, pallas_crypto::hash::Hash, types::{ address_from_hex, AssetName, Coin, EncapBTree, Input, Multiasset, Output, Transaction, }, - EXTRINSIC_KEY, SLOT_LENGTH, UTXO_SET, ZERO_SLOT, ZERO_TIME, + DATA_KEY, EXTRINSIC_KEY, SLOT_LENGTH, UTXO_SET, ZERO_SLOT, ZERO_TIME, +}; +use alloc::{ + collections::BTreeMap, + string::{String, ToString}, + vec, + vec::Vec, }; - -use alloc::{collections::BTreeMap, string::String, vec, vec::Vec}; use core::str::FromStr; use hex::FromHex; use parity_scale_codec::Encode; @@ -62,11 +67,17 @@ where .collect(), ))]; + let pc_data: PCData = PCData { + name: "hola".to_string(), + count: 0, + }; + // The transactions, zero slot and zero time are stored under special keys. sp_io::storage::set(EXTRINSIC_KEY, &transactions.encode()); sp_io::storage::set(ZERO_SLOT, &genesis_config.zero_slot.encode()); sp_io::storage::set(ZERO_TIME, &genesis_config.zero_time.encode()); sp_io::storage::set(SLOT_LENGTH, &genesis_config.slot_length.encode()); + sp_io::storage::set(DATA_KEY, &pc_data.encode()); for tx in transactions.into_iter() { // Enforce that transactions do not have any inputs. diff --git a/griffin-core/src/header.rs b/griffin-core/src/header.rs new file mode 100644 index 0000000..5ac9249 --- /dev/null +++ b/griffin-core/src/header.rs @@ -0,0 +1,137 @@ +use crate::DATA_KEY; +use alloc::string::String; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; +use sp_runtime::{ + generic::Digest, + traits::{BlakeTwo256, Hash as HashT, Header as HeaderT}, +}; + +pub type Hash = BlakeTwo256; +pub type OpaqueHash = ::Output; +pub type BlockNumber = u32; + +#[derive( + Encode, + Decode, + DecodeWithMemTracking, + Debug, + PartialEq, + Eq, + Clone, + TypeInfo, + Serialize, + Deserialize, +)] +pub struct PCData { + pub name: String, + pub count: u32, +} + +#[derive( + Encode, + Decode, + DecodeWithMemTracking, + Debug, + PartialEq, + Eq, + Clone, + TypeInfo, + Serialize, + Deserialize, +)] +pub struct ExtendedHeader { + pub parent_hash: OpaqueHash, + pub number: BlockNumber, + pub state_root: OpaqueHash, + pub extrinsics_root: OpaqueHash, + pub digest: Digest, + pub data: Option, +} + +impl ExtendedHeader { + pub fn new( + number: BlockNumber, + extrinsics_root: OpaqueHash, + state_root: OpaqueHash, + parent_hash: OpaqueHash, + digest: Digest, + ) -> Self { + Self { + number, + extrinsics_root, + state_root, + parent_hash, + digest, + data: None, + } + } + + pub fn get_pcdata(&self) -> &Option { + &self.data + } + + pub fn get_pcdata_storage() -> Option { + sp_io::storage::get(DATA_KEY).and_then(|d| PCData::decode(&mut &*d).ok()) + } + + pub fn set_pcdata(&mut self, data: PCData) { + sp_io::storage::set(DATA_KEY, &data.encode()); + self.data = Some(data) + } +} + +impl HeaderT for ExtendedHeader { + type Number = BlockNumber; + type Hash = OpaqueHash; + type Hashing = Hash; + + fn new( + number: Self::Number, + extrinsics_root: Self::Hash, + state_root: Self::Hash, + parent_hash: Self::Hash, + digest: Digest, + ) -> Self { + Self::new(number, extrinsics_root, state_root, parent_hash, digest) + } + fn number(&self) -> &Self::Number { + &self.number + } + + fn set_number(&mut self, num: Self::Number) { + self.number = num + } + fn extrinsics_root(&self) -> &Self::Hash { + &self.extrinsics_root + } + + fn set_extrinsics_root(&mut self, root: Self::Hash) { + self.extrinsics_root = root + } + fn state_root(&self) -> &Self::Hash { + &self.state_root + } + + fn set_state_root(&mut self, root: Self::Hash) { + self.state_root = root + } + fn parent_hash(&self) -> &Self::Hash { + &self.parent_hash + } + + fn set_parent_hash(&mut self, hash: Self::Hash) { + self.parent_hash = hash + } + + fn digest(&self) -> &Digest { + &self.digest + } + + fn digest_mut(&mut self) -> &mut Digest { + #[cfg(feature = "std")] + log::debug!(target: "header", "Retrieving mutable reference to digest"); + &mut self.digest + } +} diff --git a/griffin-core/src/lib.rs b/griffin-core/src/lib.rs index fcc1b67..6a6d683 100644 --- a/griffin-core/src/lib.rs +++ b/griffin-core/src/lib.rs @@ -22,6 +22,7 @@ mod executive; pub mod checks_interface; pub mod genesis; pub mod h224; +pub mod header; pub mod pallas_addresses; pub mod pallas_applying; pub mod pallas_codec; @@ -56,6 +57,10 @@ const HEADER_KEY: &[u8] = b"header"; /// This allows the block number to be available in the runtime even during off-chain api calls. pub const HEIGHT_KEY: &[u8] = b"height"; +/// A storage key that will store the block's partner chain data during and after +/// execution. This allows the information to be available in the runtime. +pub const DATA_KEY: &[u8] = b"pcdata"; + /// A transient storage key that will hold the list of extrinsics that have been applied so far. /// This key is cleared before the end of the block. pub const EXTRINSIC_KEY: &[u8] = b"extrinsics"; diff --git a/griffin-core/src/types.rs b/griffin-core/src/types.rs index 259c9a7..39278e9 100644 --- a/griffin-core/src/types.rs +++ b/griffin-core/src/types.rs @@ -1,5 +1,6 @@ //! Types used to construct Griffin transactions. use crate::h224::H224; +use crate::header::ExtendedHeader; use crate::pallas_applying::utils::BabbageError; use crate::pallas_codec::minicbor::{ self, decode::Error as MiniDecError, encode::Error as MiniEncError, encode::Write as MiniWrite, @@ -34,7 +35,7 @@ pub type OpaqueHash = ::Output; pub type BlockNumber = u32; /// Because all griffin chains use the same Blocknumber and Hash types, /// they also use the same concrete header type. -pub type Header = sp_runtime::generic::Header; +pub type Header = ExtendedHeader; pub type Block = sp_runtime::generic::Block; /// Opaque block type. It has a Griffin header, and opaque transactions.