Skip to content

Commit 7e0b1d9

Browse files
committed
Replicate the state root when constructing the trace merkle tree from the root list
1 parent 7e66fee commit 7e0b1d9

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cumulus/client/cirrus-executor/src/aux_schema.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,7 @@ pub(super) fn load_execution_receipt<Backend: AuxStore, Block: BlockT>(
105105
backend: &Backend,
106106
block_hash: Block::Hash,
107107
) -> ClientResult<Option<ExecutionReceipt<Block::Hash>>> {
108-
let key = (EXECUTION_RECEIPT_KEY, block_hash).encode();
109-
load_decode(backend, key.as_slice())
108+
load_decode(backend, execution_receipt_key(block_hash).as_slice())
110109
}
111110

112111
pub(super) fn target_receipt_is_pruned<Block: BlockT>(

cumulus/client/cirrus-executor/src/merkle_tree.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,26 @@ pub(super) type MerkleTree = merkletree::merkle::MerkleTree<
4141
Sha256Algorithm,
4242
merkletree::store::VecStore<Sha256Hash>,
4343
>;
44+
45+
pub(super) fn construct_trace_merkle_tree(
46+
roots: Vec<[u8; 32]>,
47+
) -> Result<MerkleTree, sp_blockchain::Error> {
48+
let mut roots = roots;
49+
50+
let roots_len = roots.len();
51+
assert!(roots_len >= 2, "Execution trace should at least contain 2 storage roots");
52+
53+
let ideal_len = merkletree::merkle::next_pow2(roots_len);
54+
55+
if ideal_len > roots_len {
56+
// The last element of trace is state_root.
57+
if let Some(state_root) = roots.last().copied() {
58+
roots.resize(ideal_len, state_root);
59+
}
60+
}
61+
62+
MerkleTree::new(roots).map_err(|e| {
63+
tracing::error!(target: crate::LOG_TARGET, error = ?e, "Failed to construct a trace Merkle tree");
64+
sp_blockchain::Error::Application(e.into())
65+
})
66+
}

cumulus/client/cirrus-executor/src/processor.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,21 @@ where
193193

194194
let mut roots =
195195
self.client.runtime_api().intermediate_roots(&BlockId::Hash(parent_hash))?;
196-
roots.push(
197-
state_root.encode().try_into().expect(
198-
"State root uses the same Block hash type which can fit into [u8; 32]; qed",
199-
),
200-
);
201196

202-
let trace_root = crate::merkle_tree::MerkleTree::new(roots.clone())
203-
.map_err(|e| sp_blockchain::Error::Application(e.into()))?
204-
.root();
197+
if roots.is_empty() {
198+
panic!(
199+
"FIXME: runtime intermediate_roots is empty, uncovered by running the sync node!!!"
200+
);
201+
}
202+
203+
let state_root = state_root
204+
.encode()
205+
.try_into()
206+
.expect("State root uses the same Block hash type which can fit into [u8; 32]; qed");
207+
208+
roots.push(state_root);
205209

210+
let trace_root = crate::merkle_tree::construct_trace_merkle_tree(roots.clone())?.root();
206211
let trace = roots
207212
.into_iter()
208213
.map(|r| {
@@ -299,4 +304,17 @@ mod tests {
299304

300305
assert_eq!(shuffled_extrinsics, vec![100, 30, 10, 1, 11, 101, 31, 12, 102, 2]);
301306
}
307+
308+
#[test]
309+
fn construct_trace_merkle_tree_should_work() {
310+
let root1 = [1u8; 32];
311+
let root2 = [2u8; 32];
312+
let root3 = [3u8; 32];
313+
314+
let roots = vec![root1, root2];
315+
crate::merkle_tree::construct_trace_merkle_tree(roots).unwrap();
316+
317+
let roots = vec![root1, root2, root3];
318+
crate::merkle_tree::construct_trace_merkle_tree(roots).unwrap();
319+
}
302320
}

0 commit comments

Comments
 (0)