Skip to content

Commit b2001ca

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 74047f4 commit b2001ca

File tree

1 file changed

+49
-29
lines changed

1 file changed

+49
-29
lines changed

src/lib.rs

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ use sp_runtime::{
130130
transaction_validity::{TransactionValidity, TransactionSource},
131131
};
132132
use codec::{Codec, Encode};
133-
use frame_system::{extrinsics_root, DigestOf};
133+
use frame_system::DigestOf;
134134

135135
/// Trait that can be used to execute a block.
136136
pub trait ExecuteBlock<Block: BlockT> {
@@ -213,7 +213,6 @@ where
213213
Self::initialize_block_impl(
214214
header.number(),
215215
header.parent_hash(),
216-
header.extrinsics_root(),
217216
&digests
218217
);
219218
}
@@ -231,7 +230,6 @@ where
231230
fn initialize_block_impl(
232231
block_number: &System::BlockNumber,
233232
parent_hash: &System::Hash,
234-
extrinsics_root: &System::Hash,
235233
digest: &Digest<System::Hash>,
236234
) {
237235
let mut weight = 0;
@@ -244,7 +242,6 @@ where
244242
<frame_system::Module<System>>::initialize(
245243
block_number,
246244
parent_hash,
247-
extrinsics_root,
248245
digest,
249246
frame_system::InitKind::Full,
250247
);
@@ -286,13 +283,8 @@ where
286283
assert!(
287284
n > System::BlockNumber::zero()
288285
&& <frame_system::Module<System>>::block_hash(n - System::BlockNumber::one()) == *header.parent_hash(),
289-
"Parent hash should be valid."
286+
"Parent hash should be valid.",
290287
);
291-
292-
// Check that transaction trie root represents the transactions.
293-
let xts_root = extrinsics_root::<System::Hashing, _>(&block.extrinsics());
294-
header.extrinsics_root().check_equal(&xts_root);
295-
assert!(header.extrinsics_root() == &xts_root, "Transaction trie root must be valid.");
296288
}
297289

298290
/// Actually execute all transitions for `block`.
@@ -322,8 +314,14 @@ where
322314
}
323315

324316
/// Execute given extrinsics and take care of post-extrinsics book-keeping.
325-
fn execute_extrinsics_with_book_keeping(extrinsics: Vec<Block::Extrinsic>, block_number: NumberFor<Block>) {
326-
extrinsics.into_iter().for_each(Self::apply_extrinsic_no_note);
317+
fn execute_extrinsics_with_book_keeping(
318+
extrinsics: Vec<Block::Extrinsic>,
319+
block_number: NumberFor<Block>,
320+
) {
321+
extrinsics.into_iter().for_each(|e| if let Err(e) = Self::apply_extrinsic(e) {
322+
let err: &'static str = e.into();
323+
panic!(err)
324+
});
327325

328326
// post-extrinsics book-keeping
329327
<frame_system::Module<System>>::note_finished_extrinsics();
@@ -341,8 +339,6 @@ where
341339
<frame_system::Module<System> as OnFinalize<System::BlockNumber>>::on_finalize(block_number);
342340
<AllModules as OnFinalize<System::BlockNumber>>::on_finalize(block_number);
343341

344-
// set up extrinsics
345-
<frame_system::Module<System>>::derive_extrinsics();
346342
<frame_system::Module<System>>::finalize()
347343
}
348344

@@ -354,23 +350,14 @@ where
354350
sp_io::init_tracing();
355351
let encoded = uxt.encode();
356352
let encoded_len = encoded.len();
357-
Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded))
358-
}
359-
360-
/// Apply an extrinsic inside the block execution function.
361-
fn apply_extrinsic_no_note(uxt: Block::Extrinsic) {
362-
let l = uxt.encode().len();
363-
match Self::apply_extrinsic_with_len(uxt, l, None) {
364-
Ok(_) => (),
365-
Err(e) => { let err: &'static str = e.into(); panic!(err) },
366-
}
353+
Self::apply_extrinsic_with_len(uxt, encoded_len, encoded)
367354
}
368355

369356
/// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash.
370357
fn apply_extrinsic_with_len(
371358
uxt: Block::Extrinsic,
372359
encoded_len: usize,
373-
to_note: Option<Vec<u8>>,
360+
to_note: Vec<u8>,
374361
) -> ApplyExtrinsicResult {
375362
sp_tracing::enter_span!(
376363
sp_tracing::info_span!("apply_extrinsic",
@@ -382,9 +369,7 @@ where
382369
// We don't need to make sure to `note_extrinsic` only after we know it's going to be
383370
// executed to prevent it from leaking in storage since at this point, it will either
384371
// execute or panic (and revert storage changes).
385-
if let Some(encoded) = to_note {
386-
<frame_system::Module<System>>::note_extrinsic(encoded);
387-
}
372+
<frame_system::Module<System>>::note_extrinsic(to_note);
388373

389374
// AUDIT: Under no circumstances may this function panic from here onwards.
390375

@@ -418,6 +403,11 @@ where
418403
let storage_root = new_header.state_root();
419404
header.state_root().check_equal(&storage_root);
420405
assert!(header.state_root() == storage_root, "Storage root must match that calculated.");
406+
407+
assert!(
408+
header.extrinsics_root() == new_header.extrinsics_root(),
409+
"Transaction trie root must be valid.",
410+
);
421411
}
422412

423413
/// Check a given signed transaction for validity. This doesn't execute any
@@ -462,7 +452,6 @@ where
462452
<frame_system::Module<System>>::initialize(
463453
header.number(),
464454
header.parent_hash(),
465-
header.extrinsics_root(),
466455
&digests,
467456
frame_system::InitKind::Inspection,
468457
);
@@ -558,6 +547,12 @@ mod tests {
558547
fn offchain_worker(n: T::BlockNumber) {
559548
assert_eq!(T::BlockNumber::from(1u32), n);
560549
}
550+
551+
#[weight = 0]
552+
fn calculate_storage_root(origin) {
553+
let root = sp_io::storage::root();
554+
sp_io::storage::set("storage_root".as_bytes(), &root);
555+
}
561556
}
562557
}
563558

@@ -1153,4 +1148,29 @@ mod tests {
11531148
assert_eq!(header.hash(), System::block_hash(1));
11541149
});
11551150
}
1151+
1152+
#[test]
1153+
fn calculating_storage_root_twice_works() {
1154+
let call = Call::Custom(custom::Call::calculate_storage_root());
1155+
let xt = TestXt::new(call, sign_extra(1, 0, 0));
1156+
1157+
let header = new_test_ext(1).execute_with(|| {
1158+
// Let's build some fake block.
1159+
Executive::initialize_block(&Header::new(
1160+
1,
1161+
H256::default(),
1162+
H256::default(),
1163+
[69u8; 32].into(),
1164+
Digest::default(),
1165+
));
1166+
1167+
Executive::apply_extrinsic(xt.clone()).unwrap().unwrap();
1168+
1169+
Executive::finalize_block()
1170+
});
1171+
1172+
new_test_ext(1).execute_with(|| {
1173+
Executive::execute_block(Block::new(header, vec![xt]));
1174+
});
1175+
}
11561176
}

0 commit comments

Comments
 (0)