Skip to content

Commit fe1b40c

Browse files
authored
Make it possible to calculate the storage root as often as you want (#7714)
* Make it possible to calculate the storage as often as you want So, until now each Substrate based blockchain has calculated the storage root once, at the end of the block. Now there is Frontier that wants to calculate some intermediate storage root. However this failed on block import. The problem with that was the extrinsics root. When building the block we stored `Default::default()` as extrinsics root, because yeah, we don't know the extrinsics root before finishing the block. At the end this extrinsics root was then calculated. But on block import we passed the already known extrinsics root. This was no problem, as we removed this value at the end of the block. However when you all the storage root in between, that changes the storage root between block building and block import. This pr changes this behavior. It removes the `ExtrinsicsRoot` storage entry and also doesn't pass it anymore to `System::initialize`. By doing it, we remove the difference in the storage and fix the storage root mismatch. * Fix bug with incorrectly calculating the extrinscs root * Review feedback
1 parent a564ff3 commit fe1b40c

File tree

2 files changed

+39
-34
lines changed

2 files changed

+39
-34
lines changed

src/lib.rs

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ use sp_runtime::{
107107
self, CheckEqual, AtLeast32Bit, Zero, Lookup, LookupError,
108108
SimpleBitOps, Hash, Member, MaybeDisplay, BadOrigin,
109109
MaybeSerialize, MaybeSerializeDeserialize, MaybeMallocSizeOf, StaticLookup, One, Bounded,
110-
Dispatchable, AtLeast32BitUnsigned
110+
Dispatchable, AtLeast32BitUnsigned, Saturating,
111111
},
112112
offchain::storage_lock::BlockNumberProvider,
113113
};
@@ -405,9 +405,6 @@ decl_storage! {
405405
/// Hash of the previous block.
406406
ParentHash get(fn parent_hash) build(|_| hash69()): T::Hash;
407407

408-
/// Extrinsics root of the current block, also part of the block header.
409-
ExtrinsicsRoot get(fn extrinsics_root): T::Hash;
410-
411408
/// Digest of the current block, also part of the block header.
412409
Digest get(fn digest): DigestOf<T>;
413410

@@ -989,7 +986,6 @@ impl<T: Config> Module<T> {
989986
pub fn initialize(
990987
number: &T::BlockNumber,
991988
parent_hash: &T::Hash,
992-
txs_root: &T::Hash,
993989
digest: &DigestOf<T>,
994990
kind: InitKind,
995991
) {
@@ -1000,7 +996,6 @@ impl<T: Config> Module<T> {
1000996
<Digest<T>>::put(digest);
1001997
<ParentHash<T>>::put(parent_hash);
1002998
<BlockHash<T>>::insert(*number - One::one(), parent_hash);
1003-
<ExtrinsicsRoot<T>>::put(txs_root);
1004999

10051000
// Remove previous block data from storage
10061001
BlockWeight::kill();
@@ -1017,7 +1012,6 @@ impl<T: Config> Module<T> {
10171012
/// resulting header for this block.
10181013
pub fn finalize() -> T::Header {
10191014
ExecutionPhase::kill();
1020-
ExtrinsicCount::kill();
10211015
AllExtrinsicsLen::kill();
10221016

10231017
// The following fields
@@ -1034,17 +1028,18 @@ impl<T: Config> Module<T> {
10341028
let parent_hash = <ParentHash<T>>::get();
10351029
let mut digest = <Digest<T>>::get();
10361030

1037-
let extrinsics_root = <ExtrinsicsRoot<T>>::take();
1031+
let extrinsics = (0..ExtrinsicCount::take().unwrap_or_default())
1032+
.map(ExtrinsicData::take)
1033+
.collect();
1034+
let extrinsics_root = extrinsics_data_root::<T::Hashing>(extrinsics);
10381035

10391036
// move block hash pruning window by one block
1040-
let block_hash_count = <T::BlockHashCount>::get();
1041-
if number > block_hash_count {
1042-
let to_remove = number - block_hash_count - One::one();
1037+
let block_hash_count = T::BlockHashCount::get();
1038+
let to_remove = number.saturating_sub(block_hash_count).saturating_sub(One::one());
10431039

1044-
// keep genesis hash
1045-
if to_remove != Zero::zero() {
1046-
<BlockHash<T>>::remove(to_remove);
1047-
}
1040+
// keep genesis hash
1041+
if !to_remove.is_zero() {
1042+
<BlockHash<T>>::remove(to_remove);
10481043
}
10491044

10501045
let storage_root = T::Hash::decode(&mut &sp_io::storage::root()[..])
@@ -1138,12 +1133,10 @@ impl<T: Config> Module<T> {
11381133
Account::<T>::mutate(who, |a| a.nonce += T::Index::one());
11391134
}
11401135

1141-
/// Note what the extrinsic data of the current extrinsic index is. If this
1142-
/// is called, then ensure `derive_extrinsics` is also called before
1143-
/// block-building is completed.
1136+
/// Note what the extrinsic data of the current extrinsic index is.
11441137
///
1145-
/// NOTE: This function is called only when the block is being constructed locally.
1146-
/// `execute_block` doesn't note any extrinsics.
1138+
/// This is required to be called before applying an extrinsic. The data will used
1139+
/// in [`Self::finalize`] to calculate the correct extrinsics root.
11471140
pub fn note_extrinsic(encoded_xt: Vec<u8>) {
11481141
ExtrinsicData::insert(Self::extrinsic_index().unwrap_or_default(), encoded_xt);
11491142
}
@@ -1182,14 +1175,6 @@ impl<T: Config> Module<T> {
11821175
ExecutionPhase::put(Phase::ApplyExtrinsic(0))
11831176
}
11841177

1185-
/// Remove all extrinsic data and save the extrinsics trie root.
1186-
pub fn derive_extrinsics() {
1187-
let extrinsics = (0..ExtrinsicCount::get().unwrap_or_default())
1188-
.map(ExtrinsicData::take).collect();
1189-
let xts_root = extrinsics_data_root::<T::Hashing>(extrinsics);
1190-
<ExtrinsicsRoot<T>>::put(xts_root);
1191-
}
1192-
11931178
/// An account is being created.
11941179
pub fn on_created_account(who: T::AccountId) {
11951180
T::OnNewAccount::on_new_account(&who);

src/tests.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use crate::*;
1919
use mock::{*, Origin};
2020
use sp_core::H256;
21-
use sp_runtime::DispatchError;
21+
use sp_runtime::{DispatchError, traits::{Header, BlakeTwo256}};
2222
use frame_support::weights::WithPostDispatchInfo;
2323

2424
#[test]
@@ -55,7 +55,6 @@ fn deposit_event_should_work() {
5555
System::initialize(
5656
&1,
5757
&[0u8; 32].into(),
58-
&[0u8; 32].into(),
5958
&Default::default(),
6059
InitKind::Full,
6160
);
@@ -76,7 +75,6 @@ fn deposit_event_should_work() {
7675
System::initialize(
7776
&2,
7877
&[0u8; 32].into(),
79-
&[0u8; 32].into(),
8078
&Default::default(),
8179
InitKind::Full,
8280
);
@@ -133,7 +131,6 @@ fn deposit_event_uses_actual_weight() {
133131
System::initialize(
134132
&1,
135133
&[0u8; 32].into(),
136-
&[0u8; 32].into(),
137134
&Default::default(),
138135
InitKind::Full,
139136
);
@@ -218,7 +215,6 @@ fn deposit_event_topics() {
218215
System::initialize(
219216
&BLOCK_NUMBER,
220217
&[0u8; 32].into(),
221-
&[0u8; 32].into(),
222218
&Default::default(),
223219
InitKind::Full,
224220
);
@@ -284,7 +280,6 @@ fn prunes_block_hash_mappings() {
284280
System::initialize(
285281
&n,
286282
&[n as u8 - 1; 32].into(),
287-
&[0u8; 32].into(),
288283
&Default::default(),
289284
InitKind::Full,
290285
);
@@ -422,3 +417,28 @@ fn ensure_one_of_works() {
422417
assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0));
423418
assert!(ensure_root_or_signed(RawOrigin::None).is_err())
424419
}
420+
421+
#[test]
422+
fn extrinsics_root_is_calculated_correctly() {
423+
new_test_ext().execute_with(|| {
424+
System::initialize(
425+
&1,
426+
&[0u8; 32].into(),
427+
&Default::default(),
428+
InitKind::Full,
429+
);
430+
System::note_finished_initialize();
431+
System::note_extrinsic(vec![1]);
432+
System::note_applied_extrinsic(&Ok(().into()), Default::default());
433+
System::note_extrinsic(vec![2]);
434+
System::note_applied_extrinsic(
435+
&Err(DispatchError::BadOrigin.into()),
436+
Default::default()
437+
);
438+
System::note_finished_extrinsics();
439+
let header = System::finalize();
440+
441+
let ext_root = extrinsics_data_root::<BlakeTwo256>(vec![vec![1], vec![2]]);
442+
assert_eq!(ext_root, *header.extrinsics_root());
443+
});
444+
}

0 commit comments

Comments
 (0)