1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
//! Custom GenesisConfigBuilder for Tuxedo, to allow extrinsics to be added to the genesis block.
use crate::{
ensure,
types::{OutputRef, Transaction},
ConstraintChecker, Verifier, EXTRINSIC_KEY, HEIGHT_KEY,
};
use parity_scale_codec::Encode;
use sp_runtime::traits::Hash as HashT;
use sp_std::vec::Vec;
pub struct TuxedoGenesisConfigBuilder<V, C>(sp_std::marker::PhantomData<(V, C)>);
impl<V, C> TuxedoGenesisConfigBuilder<V, C>
where
V: Verifier,
C: ConstraintChecker,
Transaction<V, C>: Encode,
{
/// This function expects a list of transactions to be included in the genesis block,
/// and stored along with their outputs. They must not contain any inputs or peeks.
/// The input transactions must be ordered: inherents first, then extrinsics.
/// The genesis transactions will not be validated by the corresponding ConstraintChecker or Verifier.
pub fn build(genesis_transactions: Vec<Transaction<V, C>>) -> sp_genesis_builder::Result {
// The transactions are stored under a special key.
sp_io::storage::set(EXTRINSIC_KEY, &genesis_transactions.encode());
//TODO This was added in during merge conflicts. Make sure inherents are working even in real parachains.
// Initialize the stored block number to 0
sp_io::storage::set(HEIGHT_KEY, &0u32.encode());
let mut finished_with_opening_inherents = false;
for tx in genesis_transactions.into_iter() {
// Enforce that inherents are in the right place
let current_tx_is_inherent = tx.checker.is_inherent();
if current_tx_is_inherent && finished_with_opening_inherents {
return Err(
"Tried to execute opening inherent after switching to non-inherents.".into(),
);
}
if !current_tx_is_inherent && !finished_with_opening_inherents {
// This is the first non-inherent, so we update our flag and continue.
finished_with_opening_inherents = true;
}
// Enforce that transactions do not have any inputs or peeks.
ensure!(
tx.inputs.is_empty() && tx.peeks.is_empty(),
"Genesis transactions must not have any inputs or peeks."
);
// Insert the outputs into the storage.
let tx_hash = sp_runtime::traits::BlakeTwo256::hash_of(&tx.encode());
for (index, utxo) in tx.outputs.iter().enumerate() {
let output_ref = OutputRef {
tx_hash,
index: index as u32,
};
sp_io::storage::set(&output_ref.encode(), &utxo.encode());
}
}
Ok(())
}
}