From 22d5f7ce9780dc8677440680a777f7ff4804cdf2 Mon Sep 17 00:00:00 2001 From: Lola Aimar Date: Mon, 15 Dec 2025 16:56:15 -0300 Subject: [PATCH 1/3] add initial header extension --- griffin-core/src/executive.rs | 2 + griffin-core/src/header.rs | 104 ++++++++++++++++++++++++++++++++++ griffin-core/src/lib.rs | 1 + griffin-core/src/types.rs | 3 +- 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 griffin-core/src/header.rs diff --git a/griffin-core/src/executive.rs b/griffin-core/src/executive.rs index 5594668..531d664 100644 --- a/griffin-core/src/executive.rs +++ b/griffin-core/src/executive.rs @@ -5,6 +5,7 @@ //! //! It does all the reusable verification of UTXO transactions. +use crate::alloc::string::ToString; use crate::pallas_applying::{ babbage::{ check_ins_not_empty, @@ -396,6 +397,7 @@ 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); + header.set_pcdata("lol".to_string()); debug!(target: LOG_TARGET, "finalizing block {:?}", header); header diff --git a/griffin-core/src/header.rs b/griffin-core/src/header.rs new file mode 100644 index 0000000..b48feb5 --- /dev/null +++ b/griffin-core/src/header.rs @@ -0,0 +1,104 @@ +use sp_runtime::{generic::Digest, traits::{BlakeTwo256, Header as HeaderT, Hash as HashT}}; +use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; +use scale_info::{prelude::string::String, TypeInfo}; +use serde::{Deserialize, Serialize}; + +pub type Hash = BlakeTwo256; +pub type OpaqueHash = ::Output; +pub type BlockNumber = u32; + +pub type PCData = String; + +#[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 set_pcdata(&mut self, data: PCData) { + match &self.data { + Some(_d) => { + log::debug!("Partner Chain Data already set"); + }, + None => { + 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..9735b5f 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; diff --git a/griffin-core/src/types.rs b/griffin-core/src/types.rs index 259c9a7..a6b6c85 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. From dda3a5bf6989bbe90bb4af112b3ce78bcac33ce1 Mon Sep 17 00:00:00 2001 From: Lola Aimar Date: Thu, 18 Dec 2025 16:25:43 -0300 Subject: [PATCH 2/3] saves info in header and in storage --- griffin-core/src/executive.rs | 14 ++++++++--- griffin-core/src/genesis/config_builder.rs | 12 ++++++--- griffin-core/src/header.rs | 29 ++++++++++++++-------- griffin-core/src/lib.rs | 4 +++ 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/griffin-core/src/executive.rs b/griffin-core/src/executive.rs index 531d664..2fad07d 100644 --- a/griffin-core/src/executive.rs +++ b/griffin-core/src/executive.rs @@ -5,7 +5,6 @@ //! //! It does all the reusable verification of UTXO transactions. -use crate::alloc::string::ToString; use crate::pallas_applying::{ babbage::{ check_ins_not_empty, @@ -34,7 +33,8 @@ use crate::{ ensure, types::{Block, BlockNumber, DispatchResult, Header, Input, Output, Transaction, UTxOError}, utxo_set::TransparentUtxoSet, - EXTRINSIC_KEY, HEADER_KEY, HEIGHT_KEY, LOG_TARGET, + header::ExtendedHeader, + 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}; @@ -346,6 +346,12 @@ 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 = data.count + 1; + sp_io::storage::set(DATA_KEY, &(data).encode()); + } + + // griffin blocks always allow user transactions. ExtrinsicInclusionMode::AllExtrinsics } @@ -397,7 +403,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); - header.set_pcdata("lol".to_string()); + 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..9ce1955 100644 --- a/griffin-core/src/genesis/config_builder.rs +++ b/griffin-core/src/genesis/config_builder.rs @@ -7,10 +7,10 @@ use crate::{ types::{ address_from_hex, AssetName, Coin, EncapBTree, Input, Multiasset, Output, Transaction, }, - EXTRINSIC_KEY, SLOT_LENGTH, UTXO_SET, ZERO_SLOT, ZERO_TIME, + header::PCData, + DATA_KEY, EXTRINSIC_KEY, SLOT_LENGTH, UTXO_SET, ZERO_SLOT, ZERO_TIME, }; - -use alloc::{collections::BTreeMap, string::String, vec, vec::Vec}; +use alloc::{collections::BTreeMap, string::{String, ToString}, vec, vec::Vec}; use core::str::FromStr; use hex::FromHex; use parity_scale_codec::Encode; @@ -62,11 +62,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 index b48feb5..e50086a 100644 --- a/griffin-core/src/header.rs +++ b/griffin-core/src/header.rs @@ -1,13 +1,22 @@ +use crate::DATA_KEY; +use alloc::string::String; use sp_runtime::{generic::Digest, traits::{BlakeTwo256, Header as HeaderT, Hash as HashT}}; use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; -use scale_info::{prelude::string::String, TypeInfo}; +use scale_info::{TypeInfo}; use serde::{Deserialize, Serialize}; pub type Hash = BlakeTwo256; pub type OpaqueHash = ::Output; pub type BlockNumber = u32; -pub type PCData = String; + +#[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 @@ -35,16 +44,16 @@ impl ExtendedHeader { pub fn get_pcdata(&self) -> &Option { &self.data } + + pub fn get_pcdata_storage() -> Option { + let data = sp_io::storage::get(DATA_KEY) + .and_then(|d| PCData::decode(&mut &*d).ok()); + data + } pub fn set_pcdata(&mut self, data: PCData) { - match &self.data { - Some(_d) => { - log::debug!("Partner Chain Data already set"); - }, - None => { - self.data = Some(data); - }, - } + sp_io::storage::set(DATA_KEY, &data.encode()); + self.data = Some(data) } } diff --git a/griffin-core/src/lib.rs b/griffin-core/src/lib.rs index 9735b5f..cb2ac0c 100644 --- a/griffin-core/src/lib.rs +++ b/griffin-core/src/lib.rs @@ -57,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"; From 61fa4d03df2bc8b93398382e8be7d21874c2841e Mon Sep 17 00:00:00 2001 From: Lola Aimar Date: Mon, 22 Dec 2025 15:28:59 -0300 Subject: [PATCH 3/3] cargo fmt and clippy suggestions --- griffin-core/src/executive.rs | 5 +- griffin-core/src/genesis/config_builder.rs | 11 +- griffin-core/src/header.rs | 146 ++++++++++++--------- griffin-core/src/lib.rs | 2 +- griffin-core/src/types.rs | 2 +- 5 files changed, 97 insertions(+), 69 deletions(-) diff --git a/griffin-core/src/executive.rs b/griffin-core/src/executive.rs index 2fad07d..afa19ab 100644 --- a/griffin-core/src/executive.rs +++ b/griffin-core/src/executive.rs @@ -31,9 +31,9 @@ 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, - header::ExtendedHeader, DATA_KEY, EXTRINSIC_KEY, HEADER_KEY, HEIGHT_KEY, LOG_TARGET, }; use crate::{SLOT_LENGTH, ZERO_SLOT, ZERO_TIME}; @@ -347,11 +347,10 @@ where sp_io::storage::set(HEIGHT_KEY, &header.number().encode()); if let Some(mut data) = ExtendedHeader::get_pcdata_storage() { - data.count = data.count + 1; + data.count += 1; sp_io::storage::set(DATA_KEY, &(data).encode()); } - // griffin blocks always allow user transactions. ExtrinsicInclusionMode::AllExtrinsics } diff --git a/griffin-core/src/genesis/config_builder.rs b/griffin-core/src/genesis/config_builder.rs index 9ce1955..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, }, - header::PCData, 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, ToString}, + vec, + vec::Vec, +}; use core::str::FromStr; use hex::FromHex; use parity_scale_codec::Encode; @@ -64,7 +69,7 @@ where let pc_data: PCData = PCData { name: "hola".to_string(), - count: 0 + count: 0, }; // The transactions, zero slot and zero time are stored under special keys. diff --git a/griffin-core/src/header.rs b/griffin-core/src/header.rs index e50086a..5ac9249 100644 --- a/griffin-core/src/header.rs +++ b/griffin-core/src/header.rs @@ -1,25 +1,45 @@ use crate::DATA_KEY; use alloc::string::String; -use sp_runtime::{generic::Digest, traits::{BlakeTwo256, Header as HeaderT, Hash as HashT}}; use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode}; -use scale_info::{TypeInfo}; +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 + Encode, + Decode, + DecodeWithMemTracking, + Debug, + PartialEq, + Eq, + Clone, + TypeInfo, + Serialize, + Deserialize, )] pub struct PCData { - pub name: String, - pub count: u32 + pub name: String, + pub count: u32, } #[derive( - Encode, Decode, DecodeWithMemTracking, Debug, PartialEq, Eq, Clone, TypeInfo, Serialize, Deserialize + Encode, + Decode, + DecodeWithMemTracking, + Debug, + PartialEq, + Eq, + Clone, + TypeInfo, + Serialize, + Deserialize, )] pub struct ExtendedHeader { pub parent_hash: OpaqueHash, @@ -27,7 +47,7 @@ pub struct ExtendedHeader { pub state_root: OpaqueHash, pub extrinsics_root: OpaqueHash, pub digest: Digest, - pub data: Option + pub data: Option, } impl ExtendedHeader { @@ -38,76 +58,80 @@ impl ExtendedHeader { parent_hash: OpaqueHash, digest: Digest, ) -> Self { - Self { number, extrinsics_root, state_root, parent_hash, digest, data: None } + 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 { - let data = sp_io::storage::get(DATA_KEY) - .and_then(|d| PCData::decode(&mut &*d).ok()); - 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) + self.data = Some(data) } } -impl HeaderT for ExtendedHeader -{ - type Number = BlockNumber; - type Hash = OpaqueHash; - type Hashing = Hash; +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 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_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_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_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 set_parent_hash(&mut self, hash: Self::Hash) { + self.parent_hash = hash + } - fn digest(&self) -> &Digest { - &self.digest - } + 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 - } + 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 cb2ac0c..6a6d683 100644 --- a/griffin-core/src/lib.rs +++ b/griffin-core/src/lib.rs @@ -59,7 +59,7 @@ 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"; +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. diff --git a/griffin-core/src/types.rs b/griffin-core/src/types.rs index a6b6c85..39278e9 100644 --- a/griffin-core/src/types.rs +++ b/griffin-core/src/types.rs @@ -1,6 +1,6 @@ //! Types used to construct Griffin transactions. use crate::h224::H224; -use crate::header::{ExtendedHeader}; +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,