Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Extrinsics root is calculated as part of block-building #120

Merged
merged 11 commits into from
Apr 12, 2018
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
23 changes: 14 additions & 9 deletions substrate/runtime/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,7 @@ use runtime_io::Hashing;
use runtime_support::StorageValue;
use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, Executable, MakePayment};
use codec::Slicable;

/// Compute the extrinsics root of a list of extrinsics.
pub fn extrinsics_root<H: Hashing, E: Slicable>(extrinsics: &[E]) -> H::Output {
let xts = extrinsics.iter().map(Slicable::encode).collect::<Vec<_>>();
let xts = xts.iter().map(Vec::as_slice).collect::<Vec<_>>();
H::enumerated_trie_root(&xts)
}
use system::extrinsics_root;

pub struct Executive<
System,
Expand Down Expand Up @@ -103,7 +97,7 @@ impl<

// execute transactions
let (header, extrinsics) = block.deconstruct();
extrinsics.into_iter().for_each(Self::apply_extrinsic);
extrinsics.into_iter().for_each(Self::apply_extrinsic_inner);

// post-transactional book-keeping.
Finalisation::execute();
Expand All @@ -120,15 +114,26 @@ impl<
pub fn finalise_block() -> System::Header {
Finalisation::execute();

// setup extrinsics
<system::Module<System>>::derive_extrinsics();

let header = <system::Module<System>>::finalise();
Self::post_finalise(&header);

header
}

/// Apply outside of the block execution function.
/// This doesn't attempt to validate anything regarding the block.
/// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt
/// hashes.
pub fn apply_extrinsic(uxt: Block::Extrinsic) {
<system::Module<System>>::note_extrinsic(uxt.encode());
Self::apply_extrinsic_inner(uxt);
}

/// Apply outside of the block execution function.
/// This doesn't attempt to validate anything regarding the block.
fn apply_extrinsic_inner(uxt: Block::Extrinsic) {
// Verify the signature is good.
let xt = match uxt.check() {
Ok(xt) => xt,
Expand Down
21 changes: 21 additions & 0 deletions substrate/runtime/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ use codec::Slicable;
#[cfg(any(feature = "std", test))]
use runtime_io::{twox_128, TestExternalities};

/// Compute the extrinsics root of a list of extrinsics.
pub fn extrinsics_root<H: Hashing, E: codec::Slicable>(extrinsics: &[E]) -> H::Output {
let xts = extrinsics.iter().map(codec::Slicable::encode).collect::<Vec<_>>();
let xts = xts.iter().map(Vec::as_slice).collect::<Vec<_>>();
H::enumerated_trie_root(&xts)
}

pub trait Trait {
type Index: Parameter + Default + SimpleArithmetic + Copy;
type BlockNumber: Parameter + SimpleArithmetic + Default + Bounded + Copy;
Expand All @@ -68,6 +75,7 @@ decl_storage! {
pub BlockHash get(block_hash): b"sys:old" => required map [ T::BlockNumber => T::Hash ];

pub ExtrinsicIndex get(extrinsic_index): b"sys:xti" => required u32;
pub ExtrinsicData get(extrinsic_data): b"sys:xtd" => required map [ u32 => Vec<u8> ];
Copy link
Contributor

@rphmeier rphmeier Apr 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be cleared in finalise? all the values are taken out of it in derive_extrinsics but is it possible it might leave residuals in storage?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be possible.

Copy link
Contributor

@rphmeier rphmeier Apr 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(with the current map implementation which may be subject to change). It's a bug waiting to happen IMO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's both notionally and logically impossible. furthermore there's no way of definitively clearing a mapping.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a later PR that (re-)instates an "list" type might be reasonable though.

Copy link
Contributor

@rphmeier rphmeier Apr 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's logically impossible as soon as mappings get any kind of metadata keys (for example, to enable iteration). This is something we will have to watch out for, but not a blocker for this PR.

RandomSeed get(random_seed): b"sys:rnd" => required T::Hash;
// The current block number being processed. Set by `execute_block`.
Number get(block_number): b"sys:num" => required T::BlockNumber;
Expand Down Expand Up @@ -170,6 +178,19 @@ impl<T: Trait> Module<T> {
pub fn inc_account_index(who: &T::AccountId) {
<AccountIndex<T>>::insert(who, Self::account_index(who) + T::Index::one());
}

/// Note what the extrinsic data of the current extrinsic index is. If this is called, then
/// ensure `derive_extrinsics` is also called before block-building is completed.
pub fn note_extrinsic(encoded_xt: Vec<u8>) {
<ExtrinsicData<T>>::insert(Self::extrinsic_index(), encoded_xt);
}

/// Remove all extrinsics data and save the extrinsics trie root.
pub fn derive_extrinsics() {
let extrinsics = (0..Self::extrinsic_index()).map(<ExtrinsicData<T>>::take).collect::<Vec<_>>();
let xts_root = extrinsics_root::<T::Hashing, _>(&extrinsics);
<ExtrinsicsRoot<T>>::put(xts_root);
}
}

#[cfg(any(feature = "std", test))]
Expand Down
Binary file not shown.
Binary file not shown.