reth_trie_sparse/
debug_recorder.rs1use alloc::{string::String, vec::Vec};
8use alloy_primitives::{hex, Bytes, B256};
9use alloy_trie::nodes::TrieNode;
10use reth_trie_common::Nibbles;
11use serde::Serialize;
12
13#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
15pub struct TrieDebugRecorder {
16 ops: Vec<RecordedOp>,
17}
18
19impl TrieDebugRecorder {
20 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn reset(&mut self) {
27 self.ops.clear();
28 }
29
30 pub fn record(&mut self, op: RecordedOp) {
32 self.ops.push(op);
33 }
34
35 pub fn ops(&self) -> &[RecordedOp] {
37 &self.ops
38 }
39
40 pub fn take_ops(&mut self) -> Vec<RecordedOp> {
42 core::mem::take(&mut self.ops)
43 }
44
45 pub const fn is_empty(&self) -> bool {
47 self.ops.is_empty()
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
53pub enum RecordedOp {
54 RevealNodes {
56 nodes: Vec<ProofTrieNodeRecord>,
58 },
59 UpdateLeaves {
61 updates: Vec<(B256, LeafUpdateRecord)>,
63 remaining_keys: Vec<B256>,
66 proof_targets: Vec<(B256, u8)>,
68 },
69 UpdateSubtrieHashes,
71 Root,
73 SetRoot {
75 node: ProofTrieNodeRecord,
77 },
78}
79
80#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
82pub struct ProofTrieNodeRecord {
83 pub path: Nibbles,
85 pub node: TrieNodeRecord,
87 pub masks: Option<(u16, u16)>,
89}
90
91impl ProofTrieNodeRecord {
92 pub fn from_proof_trie_node(node: &reth_trie_common::ProofTrieNode) -> Self {
94 Self {
95 path: node.path,
96 node: TrieNodeRecord(node.node.clone()),
97 masks: node.masks.map(|masks| (masks.hash_mask.get(), masks.tree_mask.get())),
98 }
99 }
100
101 pub fn from_proof_trie_node_v2(node: &reth_trie_common::ProofTrieNodeV2) -> Self {
103 use reth_trie_common::TrieNodeV2;
104 let trie_node = match &node.node {
105 TrieNodeV2::EmptyRoot => TrieNode::EmptyRoot,
106 TrieNodeV2::Leaf(leaf) => TrieNode::Leaf(leaf.clone()),
107 TrieNodeV2::Extension(ext) => TrieNode::Extension(ext.clone()),
108 TrieNodeV2::Branch(branch) => TrieNode::Branch(alloy_trie::nodes::BranchNode::new(
109 branch.stack.clone(),
110 branch.state_mask,
111 )),
112 };
113 Self {
114 path: node.path,
115 node: TrieNodeRecord(trie_node),
116 masks: node.masks.map(|masks| (masks.hash_mask.get(), masks.tree_mask.get())),
117 }
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
125pub struct TrieNodeRecord(pub TrieNode);
126
127impl From<TrieNode> for TrieNodeRecord {
128 fn from(node: TrieNode) -> Self {
129 Self(node)
130 }
131}
132
133impl Serialize for TrieNodeRecord {
134 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
135 use serde::ser::SerializeStructVariant;
136 match &self.0 {
137 TrieNode::EmptyRoot => serializer.serialize_unit_variant("TrieNode", 0, "EmptyRoot"),
138 TrieNode::Branch(branch) => {
139 let stack_hex: Vec<String> =
140 branch.stack.iter().map(|n| hex::encode(n.as_ref())).collect();
141 let mut sv = serializer.serialize_struct_variant("TrieNode", 1, "Branch", 2)?;
142 sv.serialize_field("stack", &stack_hex)?;
143 sv.serialize_field("state_mask", &branch.state_mask.get())?;
144 sv.end()
145 }
146 TrieNode::Extension(ext) => {
147 let mut sv = serializer.serialize_struct_variant("TrieNode", 2, "Extension", 2)?;
148 sv.serialize_field("key", &ext.key)?;
149 sv.serialize_field("child", &hex::encode(ext.child.as_ref()))?;
150 sv.end()
151 }
152 TrieNode::Leaf(leaf) => {
153 let mut sv = serializer.serialize_struct_variant("TrieNode", 3, "Leaf", 2)?;
154 sv.serialize_field("key", &leaf.key)?;
155 sv.serialize_field("value", &hex::encode(&leaf.value))?;
156 sv.end()
157 }
158 }
159 }
160}
161
162#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
164pub enum LeafUpdateRecord {
165 Changed(Bytes),
167 Touched,
169}
170
171impl From<&crate::LeafUpdate> for LeafUpdateRecord {
172 fn from(update: &crate::LeafUpdate) -> Self {
173 match update {
174 crate::LeafUpdate::Changed(value) => Self::Changed(value.clone().into()),
175 crate::LeafUpdate::Touched => Self::Touched,
176 }
177 }
178}