mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(trie): convert vec to Bytes in Nibbles (#3120)
This commit is contained in:
@ -54,7 +54,7 @@ pub struct HashBuilder {
|
||||
impl From<HashBuilderState> for HashBuilder {
|
||||
fn from(state: HashBuilderState) -> Self {
|
||||
Self {
|
||||
key: Nibbles::from(state.key),
|
||||
key: Nibbles::from_hex(state.key),
|
||||
stack: state.stack,
|
||||
value: state.value,
|
||||
groups: state.groups,
|
||||
@ -70,7 +70,7 @@ impl From<HashBuilderState> for HashBuilder {
|
||||
impl From<HashBuilder> for HashBuilderState {
|
||||
fn from(state: HashBuilder) -> Self {
|
||||
Self {
|
||||
key: state.key.hex_data,
|
||||
key: state.key.hex_data.to_vec(),
|
||||
stack: state.stack,
|
||||
value: state.value,
|
||||
groups: state.groups,
|
||||
@ -153,7 +153,7 @@ impl HashBuilder {
|
||||
// Clears the internal state
|
||||
if !self.key.is_empty() {
|
||||
self.update(&Nibbles::default());
|
||||
self.key.clear();
|
||||
self.key.hex_data.0.clear();
|
||||
self.value = HashBuilderValue::Bytes(vec![]);
|
||||
}
|
||||
self.current_root()
|
||||
|
||||
@ -78,7 +78,7 @@ impl Compact for StoredNibblesSubKey {
|
||||
)]
|
||||
pub struct Nibbles {
|
||||
/// The inner representation of the nibble sequence.
|
||||
pub hex_data: Vec<u8>,
|
||||
pub hex_data: Bytes,
|
||||
}
|
||||
|
||||
impl From<&[u8]> for Nibbles {
|
||||
@ -102,13 +102,20 @@ impl std::fmt::Debug for Nibbles {
|
||||
impl Nibbles {
|
||||
/// Creates a new [Nibbles] instance from bytes.
|
||||
pub fn from_hex(hex: Vec<u8>) -> Self {
|
||||
Nibbles { hex_data: hex }
|
||||
Nibbles { hex_data: Bytes::from(hex) }
|
||||
}
|
||||
|
||||
/// Take a byte array (slice or vector) as input and convert it into a [Nibbles] struct
|
||||
/// containing the nibbles (half-bytes or 4 bits) that make up the input byte data.
|
||||
pub fn unpack<T: AsRef<[u8]>>(data: T) -> Self {
|
||||
Nibbles { hex_data: data.as_ref().iter().flat_map(|item| [item / 16, item % 16]).collect() }
|
||||
Nibbles {
|
||||
hex_data: Bytes::from(
|
||||
data.as_ref()
|
||||
.iter()
|
||||
.flat_map(|item| vec![item / 16, item % 16])
|
||||
.collect::<Vec<u8>>(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Packs the nibbles stored in the struct into a byte vector.
|
||||
@ -202,13 +209,13 @@ impl Nibbles {
|
||||
|
||||
/// Increments the nibble sequence by one.
|
||||
pub fn increment(&self) -> Option<Nibbles> {
|
||||
let mut incremented = self.hex_data.clone();
|
||||
let mut incremented = self.hex_data.to_vec();
|
||||
|
||||
for nibble in incremented.iter_mut().rev() {
|
||||
assert!(*nibble < 0x10);
|
||||
if *nibble < 0xf {
|
||||
*nibble += 1;
|
||||
return Some(Nibbles::from(incremented))
|
||||
return Some(Nibbles::from_hex(incremented))
|
||||
} else {
|
||||
*nibble = 0;
|
||||
}
|
||||
@ -269,12 +276,16 @@ impl Nibbles {
|
||||
|
||||
/// Extend the current nibbles with another nibbles.
|
||||
pub fn extend(&mut self, b: impl AsRef<[u8]>) {
|
||||
self.hex_data.extend_from_slice(b.as_ref());
|
||||
// self.hex_data.extend_from_slice(b.as_ref());
|
||||
|
||||
let mut bytes = self.hex_data.to_vec();
|
||||
bytes.extend_from_slice(b.as_ref());
|
||||
self.hex_data = bytes.into();
|
||||
}
|
||||
|
||||
/// Truncate the current nibbles to the given length.
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
self.hex_data.truncate(len)
|
||||
self.hex_data.0.truncate(len)
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,7 +297,7 @@ mod tests {
|
||||
#[test]
|
||||
fn hashed_regression() {
|
||||
let nibbles = hex::decode("05010406040a040203030f010805020b050c04070003070e0909070f010b0a0805020301070c0a0902040b0f000f0006040a04050f020b090701000a0a040b").unwrap();
|
||||
let nibbles = Nibbles::from(nibbles);
|
||||
let nibbles = Nibbles::from_hex(nibbles);
|
||||
let path = nibbles.encode_path_leaf(true);
|
||||
let expected =
|
||||
hex::decode("351464a4233f1852b5c47037e997f1ba852317ca924bf0f064a45f2b9710aa4b")
|
||||
@ -304,7 +315,7 @@ mod tests {
|
||||
(vec![0xa, 0xb, 0x2, 0x0], vec![0xab, 0x20]),
|
||||
(vec![0xa, 0xb, 0x2, 0x7], vec![0xab, 0x27]),
|
||||
] {
|
||||
let nibbles = Nibbles::from(input);
|
||||
let nibbles = Nibbles::from_hex(input);
|
||||
let encoded = nibbles.pack();
|
||||
assert_eq!(encoded, expected);
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ mod tests {
|
||||
// From manual regression test
|
||||
#[test]
|
||||
fn encode_leaf_node_nibble() {
|
||||
let nibble = Nibbles { hex_data: hex!("0604060f").to_vec() };
|
||||
let nibble = Nibbles { hex_data: hex!("0604060f").into() };
|
||||
let encoded = nibble.encode_path_leaf(true);
|
||||
let expected = hex!("20646f").to_vec();
|
||||
assert_eq!(encoded, expected);
|
||||
@ -67,7 +67,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn rlp_leaf_node_roundtrip() {
|
||||
let nibble = Nibbles { hex_data: hex!("0604060f").to_vec() };
|
||||
let nibble = Nibbles { hex_data: hex!("0604060f").into() };
|
||||
let val = hex!("76657262").to_vec();
|
||||
let leaf = LeafNode::new(&nibble, &val);
|
||||
let rlp = leaf.rlp(&mut vec![]);
|
||||
|
||||
@ -214,7 +214,7 @@ impl<DB: Database> Stage<DB> for MerkleStage {
|
||||
let checkpoint = MerkleCheckpoint::new(
|
||||
to_block,
|
||||
state.last_account_key,
|
||||
state.last_walker_key.hex_data,
|
||||
state.last_walker_key.hex_data.to_vec(),
|
||||
state.walker_stack.into_iter().map(StoredSubNode::from).collect(),
|
||||
state.hash_builder.into(),
|
||||
);
|
||||
|
||||
@ -34,7 +34,7 @@ impl From<MerkleCheckpoint> for IntermediateStateRootState {
|
||||
hash_builder: HashBuilder::from(value.state),
|
||||
walker_stack: value.walker_stack.into_iter().map(CursorSubNode::from).collect(),
|
||||
last_account_key: value.last_account_key,
|
||||
last_walker_key: Nibbles::from(value.last_walker_key),
|
||||
last_walker_key: Nibbles::from_hex(value.last_walker_key),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1331,11 +1331,11 @@ mod tests {
|
||||
fn assert_trie_updates(account_updates: &HashMap<Nibbles, BranchNodeCompact>) {
|
||||
assert_eq!(account_updates.len(), 2);
|
||||
|
||||
let node = account_updates.get(&vec![0x3].into()).unwrap();
|
||||
let node = account_updates.get(&vec![0x3].as_slice().into()).unwrap();
|
||||
let expected = BranchNodeCompact::new(0b0011, 0b0001, 0b0000, vec![], None);
|
||||
assert_eq!(node, &expected);
|
||||
|
||||
let node = account_updates.get(&vec![0x3, 0x0, 0xA, 0xF].into()).unwrap();
|
||||
let node = account_updates.get(&vec![0x3, 0x0, 0xA, 0xF].as_slice().into()).unwrap();
|
||||
assert_eq!(node.state_mask, TrieMask::new(0b101100000));
|
||||
assert_eq!(node.tree_mask, TrieMask::new(0b000000000));
|
||||
assert_eq!(node.hash_mask, TrieMask::new(0b001000000));
|
||||
|
||||
@ -39,14 +39,14 @@ impl From<StoredSubNode> for CursorSubNode {
|
||||
Some(n) => n as i8,
|
||||
None => -1,
|
||||
};
|
||||
Self { key: Nibbles::from(value.key), nibble, node: value.node }
|
||||
Self { key: Nibbles::from_hex(value.key), nibble, node: value.node }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CursorSubNode> for StoredSubNode {
|
||||
fn from(value: CursorSubNode) -> Self {
|
||||
let nibble = if value.nibble >= 0 { Some(value.nibble as u8) } else { None };
|
||||
Self { key: value.key.hex_data, nibble, node: value.node }
|
||||
Self { key: value.key.hex_data.to_vec(), nibble, node: value.node }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -77,20 +77,25 @@ impl TrieUpdates {
|
||||
}
|
||||
|
||||
/// Extend the updates with account trie updates.
|
||||
#[allow(clippy::mutable_key_type)]
|
||||
pub fn extend_with_account_updates(&mut self, updates: HashMap<Nibbles, BranchNodeCompact>) {
|
||||
self.extend(updates.into_iter().map(|(nibbles, node)| {
|
||||
(TrieKey::AccountNode(nibbles.hex_data.into()), TrieOp::Update(node))
|
||||
(TrieKey::AccountNode(nibbles.hex_data.to_vec().into()), TrieOp::Update(node))
|
||||
}));
|
||||
}
|
||||
|
||||
/// Extend the updates with storage trie updates.
|
||||
#[allow(clippy::mutable_key_type)]
|
||||
pub fn extend_with_storage_updates(
|
||||
&mut self,
|
||||
hashed_address: H256,
|
||||
updates: HashMap<Nibbles, BranchNodeCompact>,
|
||||
) {
|
||||
self.extend(updates.into_iter().map(|(nibbles, node)| {
|
||||
(TrieKey::StorageNode(hashed_address, nibbles.hex_data.into()), TrieOp::Update(node))
|
||||
(
|
||||
TrieKey::StorageNode(hashed_address, nibbles.hex_data.to_vec().into()),
|
||||
TrieOp::Update(node),
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@ -129,16 +129,16 @@ impl<'a, K: Key + From<Vec<u8>>, C: TrieCursor<K>> TrieWalker<'a, K, C> {
|
||||
fn node(&mut self, exact: bool) -> Result<Option<(Nibbles, BranchNodeCompact)>, DatabaseError> {
|
||||
let key = self.key().expect("key must exist");
|
||||
let entry = if exact {
|
||||
self.cursor.seek_exact(key.hex_data.into())?
|
||||
self.cursor.seek_exact(key.hex_data.to_vec().into())?
|
||||
} else {
|
||||
self.cursor.seek(key.hex_data.into())?
|
||||
self.cursor.seek(key.hex_data.to_vec().into())?
|
||||
};
|
||||
|
||||
if let Some((_, node)) = &entry {
|
||||
assert!(!node.state_mask.is_empty());
|
||||
}
|
||||
|
||||
Ok(entry.map(|(k, v)| (Nibbles::from(k), v)))
|
||||
Ok(entry.map(|(k, v)| (Nibbles::from_hex(k), v)))
|
||||
}
|
||||
|
||||
/// Consumes the next node in the trie, updating the stack.
|
||||
@ -374,7 +374,7 @@ mod tests {
|
||||
|
||||
// No changes
|
||||
let mut cursor = TrieWalker::new(&mut trie, Default::default());
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from(vec![]))); // root
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from_hex(vec![]))); // root
|
||||
assert!(cursor.can_skip_current_node); // due to root_hash
|
||||
cursor.advance().unwrap(); // skips to the end of trie
|
||||
assert_eq!(cursor.key(), None);
|
||||
@ -385,15 +385,15 @@ mod tests {
|
||||
let mut cursor = TrieWalker::new(&mut trie, changed);
|
||||
|
||||
// Root node
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from(vec![])));
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from_hex(vec![])));
|
||||
// Should not be able to skip state due to the changed values
|
||||
assert!(!cursor.can_skip_current_node);
|
||||
cursor.advance().unwrap();
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from(vec![0x2])));
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from_hex(vec![0x2])));
|
||||
cursor.advance().unwrap();
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from(vec![0x2, 0x1])));
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from_hex(vec![0x2, 0x1])));
|
||||
cursor.advance().unwrap();
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from(vec![0x4])));
|
||||
assert_eq!(cursor.key(), Some(Nibbles::from_hex(vec![0x4])));
|
||||
|
||||
cursor.advance().unwrap();
|
||||
assert_eq!(cursor.key(), None); // the end of trie
|
||||
|
||||
Reference in New Issue
Block a user