-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* draft of `InhrerentInternal::genesis_utxos` * make it build * transactions list in `GenesisConfig` imported in block 0 by `TuxedoGenesisBlockBuilder` * added `genesis_builder.rs` * make clippy happy * fixed genesis tests * beautify GenesisConfig * moved `genesis_builder.rs` from `node` to `tuxedo-core` * make it build * move `assimilate_storage` in `tuxedo-core` * forgot a file * let's make toml-sort happy * update wallet to apply extrinsics for genesis blocks * clear extrinsics list from storage in `build_genesis_block` * improved comments, check genesis transactions inputs and peeks length * removed superfluous Box, ran `cargo clippy --fix` * removed "first block hack" references and consequences, fmt --------- Signed-off-by: muraca <mmuraca247@gmail.com>
- Loading branch information
Showing
23 changed files
with
432 additions
and
256 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
//! Custom GenesisBlockBuilder for Tuxedo, to allow extrinsics to be added to the genesis block. | ||
use crate::{ | ||
ensure, | ||
types::{OutputRef, Transaction}, | ||
EXTRINSIC_KEY, | ||
}; | ||
use parity_scale_codec::{Decode, Encode}; | ||
use sc_chain_spec::BuildGenesisBlock; | ||
use sc_client_api::backend::{Backend, BlockImportOperation}; | ||
use sc_executor::RuntimeVersionOf; | ||
use scale_info::TypeInfo; | ||
use sp_core::{storage::Storage, traits::CodeExecutor}; | ||
use sp_runtime::{ | ||
traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT, Zero}, | ||
BuildStorage, | ||
}; | ||
use std::sync::Arc; | ||
|
||
pub struct TuxedoGenesisBlockBuilder< | ||
'a, | ||
Block: BlockT, | ||
B: Backend<Block>, | ||
E: RuntimeVersionOf + CodeExecutor, | ||
> { | ||
build_genesis_storage: &'a dyn BuildStorage, | ||
commit_genesis_state: bool, | ||
backend: Arc<B>, | ||
executor: E, | ||
_phantom: std::marker::PhantomData<Block>, | ||
} | ||
|
||
impl<'a, Block: BlockT, B: Backend<Block>, E: RuntimeVersionOf + CodeExecutor> | ||
TuxedoGenesisBlockBuilder<'a, Block, B, E> | ||
{ | ||
pub fn new( | ||
build_genesis_storage: &'a dyn BuildStorage, | ||
commit_genesis_state: bool, | ||
backend: Arc<B>, | ||
executor: E, | ||
) -> sp_blockchain::Result<Self> { | ||
Ok(Self { | ||
build_genesis_storage, | ||
commit_genesis_state, | ||
backend, | ||
executor, | ||
_phantom: Default::default(), | ||
}) | ||
} | ||
} | ||
|
||
impl<'a, Block: BlockT, B: Backend<Block>, E: RuntimeVersionOf + CodeExecutor> | ||
BuildGenesisBlock<Block> for TuxedoGenesisBlockBuilder<'a, Block, B, E> | ||
{ | ||
type BlockImportOperation = <B as Backend<Block>>::BlockImportOperation; | ||
|
||
/// Build the genesis block, including the extrinsics found in storage at EXTRINSIC_KEY. | ||
/// The extrinsics are not checked for validity, nor executed, so the values in storage must be placed manually. | ||
/// This can be done by using the `assimilate_storage` function. | ||
fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)> { | ||
// We build it here to gain mutable access to the storage. | ||
let mut genesis_storage = self | ||
.build_genesis_storage | ||
.build_storage() | ||
.map_err(sp_blockchain::Error::Storage)?; | ||
|
||
let state_version = | ||
sc_chain_spec::resolve_state_version_from_wasm(&genesis_storage, &self.executor)?; | ||
|
||
let extrinsics = match genesis_storage.top.remove(crate::EXTRINSIC_KEY) { | ||
Some(v) => <Vec<<Block as BlockT>::Extrinsic>>::decode(&mut &v[..]).unwrap_or_default(), | ||
None => Vec::new(), | ||
}; | ||
|
||
let extrinsics_root = | ||
<<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::ordered_trie_root( | ||
extrinsics.iter().map(Encode::encode).collect(), | ||
state_version, | ||
); | ||
|
||
let mut op = self.backend.begin_operation()?; | ||
let state_root = | ||
op.set_genesis_state(genesis_storage, self.commit_genesis_state, state_version)?; | ||
|
||
let block = Block::new( | ||
HeaderT::new( | ||
Zero::zero(), | ||
extrinsics_root, | ||
state_root, | ||
Default::default(), | ||
Default::default(), | ||
), | ||
extrinsics, | ||
); | ||
|
||
Ok((block, op)) | ||
} | ||
} | ||
|
||
/// Assimilate the storage into the genesis block. | ||
/// This is done by inserting the genesis extrinsics into the genesis block, along with their outputs. | ||
/// Make sure to pass the transactions in order: the inherents should be first, then the extrinsics. | ||
pub fn assimilate_storage<V: Encode + TypeInfo, C: Encode + TypeInfo>( | ||
storage: &mut Storage, | ||
genesis_transactions: Vec<Transaction<V, C>>, | ||
) -> Result<(), String> { | ||
storage | ||
.top | ||
.insert(EXTRINSIC_KEY.to_vec(), genesis_transactions.encode()); | ||
|
||
for tx in genesis_transactions { | ||
ensure!( | ||
tx.inputs.is_empty() && tx.peeks.is_empty(), | ||
"Genesis transactions must not have any inputs or peeks." | ||
); | ||
let tx_hash = BlakeTwo256::hash_of(&tx.encode()); | ||
for (index, utxo) in tx.outputs.iter().enumerate() { | ||
let output_ref = OutputRef { | ||
tx_hash, | ||
index: index as u32, | ||
}; | ||
storage.top.insert(output_ref.encode(), utxo.encode()); | ||
} | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.