#![cfg(test)]
use super::{
Config, ConfigTy, DatabaseOpen, InsertTrieNode, InsertTrieNodeStorageValue, StorageAccessError,
open,
};
use crate::{header, trie};
use alloc::borrow::Cow;
use core::{array, iter};
use rand::distributions::{Distribution as _, Uniform};
#[test]
fn empty_database_fill_then_query() {
for _ in 0..1024 {
let DatabaseOpen::Empty(empty_db) = open(Config {
block_number_bytes: 4,
cache_size: 2 * 1024 * 1024,
ty: ConfigTy::Memory,
})
.unwrap() else {
panic!()
};
fn uniform_sample(min: u8, max: u8) -> u8 {
Uniform::new_inclusive(min, max).sample(&mut rand::thread_rng())
}
let mut trie = trie::trie_structure::TrieStructure::<(
Option<Vec<u8>>,
Option<trie::trie_node::MerkleValueOutput>,
)>::new();
let mut list = vec![Vec::new()];
for elem in list.clone().into_iter() {
for _ in 0..uniform_sample(0, 4) {
let mut elem = elem.clone();
for _ in 0..uniform_sample(0, 3) {
elem.push(uniform_sample(0, 255));
}
list.push(elem);
}
}
for elem in list {
let mut storage_value = Vec::new();
for _ in 0..uniform_sample(0, 24) {
storage_value.push(uniform_sample(0, 255));
}
match trie.node(trie::bytes_to_nibbles(elem.iter().copied())) {
trie::trie_structure::Entry::Vacant(e) => {
e.insert_storage_value()
.insert((Some(storage_value), None), (None, None));
}
trie::trie_structure::Entry::Occupied(
trie::trie_structure::NodeAccess::Branch(mut e),
) => {
*e.user_data() = (Some(storage_value), None);
e.insert_storage_value();
}
trie::trie_structure::Entry::Occupied(
trie::trie_structure::NodeAccess::Storage(_),
) => {}
}
}
for node_index in trie.iter_ordered().collect::<Vec<_>>().into_iter().rev() {
let mut node_access = trie.node_by_index(node_index).unwrap();
let children = core::array::from_fn::<_, 16, _>(|n| {
node_access
.child(trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap())
.map(|mut child| child.user_data().1.as_ref().unwrap().clone())
});
let is_root_node = node_access.is_root_node();
let partial_key = node_access.partial_key().collect::<Vec<_>>().into_iter();
let storage_value = match node_access.user_data().0.as_ref() {
Some(v) => trie::trie_node::StorageValue::Unhashed(&v[..]),
None => trie::trie_node::StorageValue::None,
};
let merkle_value = trie::trie_node::calculate_merkle_value(
trie::trie_node::Decoded {
children,
partial_key,
storage_value,
},
trie::HashFunction::Blake2,
is_root_node,
)
.unwrap();
node_access.into_user_data().1 = Some(merkle_value);
}
let open_db = {
let state_root = &trie
.root_user_data()
.map(|n| *<&[u8; 32]>::try_from(n.1.as_ref().unwrap().as_ref()).unwrap())
.unwrap_or(trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE);
let trie_entries_linear =
trie.iter_unordered()
.collect::<Vec<_>>()
.into_iter()
.map(|node_index| {
let (storage_value, Some(merkle_value)) = &trie[node_index] else {
unreachable!()
};
let storage_value = if let Some(storage_value) = storage_value {
InsertTrieNodeStorageValue::Value {
value: Cow::Owned(storage_value.to_vec()),
references_merkle_value: false, }
} else {
InsertTrieNodeStorageValue::NoValue
};
let merkle_value = merkle_value.as_ref().to_owned();
let mut node_access = trie.node_by_index(node_index).unwrap();
InsertTrieNode {
storage_value,
merkle_value: Cow::Owned(merkle_value),
children_merkle_values: array::from_fn::<_, 16, _>(|n| {
let child_index =
trie::Nibble::try_from(u8::try_from(n).unwrap()).unwrap();
if let Some(mut child) = node_access.child(child_index) {
Some(Cow::Owned(
child.user_data().1.as_ref().unwrap().as_ref().to_vec(),
))
} else {
None
}
}),
partial_key_nibbles: Cow::Owned(
node_access.partial_key().map(u8::from).collect::<Vec<_>>(),
),
}
});
let db = empty_db
.initialize(
&header::HeaderRef {
number: 0,
extrinsics_root: &[0; 32],
parent_hash: &[0; 32],
state_root,
digest: header::DigestRef::empty(),
}
.scale_encoding_vec(4),
iter::empty(),
None,
)
.unwrap();
db.insert_trie_nodes(trie_entries_linear, 0).unwrap();
db
};
let block0_hash = open_db.finalized_block_hash().unwrap();
for _ in 0..1024 {
let key = (0..uniform_sample(0, 4))
.map(|_| uniform_sample(0, 255))
.collect::<Vec<_>>();
let actual = open_db
.block_storage_get(
&block0_hash,
iter::empty::<iter::Empty<_>>(),
trie::bytes_to_nibbles(key.iter().copied()).map(u8::from),
)
.unwrap();
let expected = trie
.node_by_full_key(trie::bytes_to_nibbles(key.iter().copied()))
.and_then(|n| Some((trie[n].0.as_ref()?.clone(), 0u8)));
assert_eq!(
actual,
expected,
"\nkey = {:?}\ntrie = {:?}",
key.iter().map(|n| format!("{:x}", n)).collect::<String>(),
trie
);
}
for _ in 0..1024 {
let key = (0..uniform_sample(0, 8))
.map(|_| trie::Nibble::try_from(uniform_sample(0u8, 15)).unwrap())
.collect::<Vec<_>>();
let prefix = (0..uniform_sample(0, 8))
.map(|_| trie::Nibble::try_from(uniform_sample(0u8, 15)).unwrap())
.collect::<Vec<_>>();
let branch_nodes = rand::random::<bool>();
let actual = open_db
.block_storage_next_key(
&block0_hash,
iter::empty::<iter::Empty<_>>(),
key.iter().copied().map(u8::from),
prefix.iter().copied().map(u8::from),
branch_nodes,
)
.unwrap();
let expected = trie
.iter_ordered()
.filter(|n| branch_nodes || trie[*n].0.is_some())
.map(|n| trie.node_full_key_by_index(n).unwrap().collect::<Vec<_>>())
.find(|n| *n >= key)
.filter(|n| n.starts_with(&prefix))
.map(|k| k.iter().copied().map(u8::from).collect::<Vec<_>>());
assert_eq!(
actual,
expected,
"\nkey = {:?}\nprefix = {:?}\nbranch_nodes = {:?}\ntrie = {:?}",
key.iter().map(|n| format!("{:x}", n)).collect::<String>(),
prefix
.iter()
.map(|n| format!("{:x}", n))
.collect::<String>(),
branch_nodes,
trie
);
}
for _ in 0..1024 {
let key = (0..uniform_sample(0, 8))
.map(|_| trie::Nibble::try_from(uniform_sample(0u8, 15)).unwrap())
.collect::<Vec<_>>();
let actual = open_db
.block_storage_closest_descendant_merkle_value(
&block0_hash,
iter::empty::<iter::Empty<_>>(),
key.iter().copied().map(u8::from),
)
.unwrap();
let expected = trie
.iter_ordered()
.find(|n| {
let full_key = trie.node_full_key_by_index(*n).unwrap().collect::<Vec<_>>();
full_key >= key && full_key.starts_with(&key)
})
.map(|n| trie[n].1.as_ref().unwrap().as_ref().to_vec());
assert_eq!(
actual,
expected,
"\nkey = {:?}\ntrie = {:?}",
key.iter().map(|n| format!("{:x}", n)).collect::<String>(),
trie
);
}
}
}
#[test]
fn unknown_block() {
let DatabaseOpen::Empty(empty_db) = open(Config {
block_number_bytes: 4,
cache_size: 2 * 1024 * 1024,
ty: ConfigTy::Memory,
})
.unwrap() else {
panic!()
};
let db = empty_db
.initialize(
&header::HeaderRef {
number: 0,
extrinsics_root: &[0; 32],
parent_hash: &[0; 32],
state_root: &[1; 32],
digest: header::DigestRef::empty(),
}
.scale_encoding_vec(4),
iter::empty(),
None,
)
.unwrap();
assert!(matches!(
db.block_storage_get(&[0xff; 32], iter::empty::<iter::Empty<_>>(), [].into_iter()),
Err(StorageAccessError::UnknownBlock)
));
assert!(matches!(
db.block_storage_next_key(
&[0xff; 32],
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
[].into_iter(),
true
),
Err(StorageAccessError::UnknownBlock)
));
assert!(matches!(
db.block_storage_next_key(
&[0xff; 32],
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
[].into_iter(),
false
),
Err(StorageAccessError::UnknownBlock)
));
assert!(matches!(
db.block_storage_closest_descendant_merkle_value(
&[0xff; 32],
iter::empty::<iter::Empty<_>>(),
[].into_iter()
),
Err(StorageAccessError::UnknownBlock)
));
}
#[test]
fn storage_get_partial() {
let DatabaseOpen::Empty(empty_db) = open(Config {
block_number_bytes: 4,
cache_size: 2 * 1024 * 1024,
ty: ConfigTy::Memory,
})
.unwrap() else {
panic!()
};
let db = empty_db
.initialize(
&header::HeaderRef {
number: 0,
extrinsics_root: &[0; 32],
parent_hash: &[0; 32],
state_root: &[1; 32],
digest: header::DigestRef::empty(),
}
.scale_encoding_vec(4),
iter::empty(),
None,
)
.unwrap();
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1, 1].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 2].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[1; 32]),
partial_key_nibbles: Cow::Borrowed(&[1, 1]),
children_merkle_values: [
None,
Some(Cow::Borrowed(&[2; 32])),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
storage_value: InsertTrieNodeStorageValue::Value {
value: Cow::Borrowed(b"hello"),
references_merkle_value: false,
},
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
)
.unwrap()
.unwrap()
.0,
b"hello"
);
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1, 1].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
)
.unwrap()
.is_none()
);
assert!(matches!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 2].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[2; 32]),
partial_key_nibbles: Cow::Borrowed(&[1, 1]),
children_merkle_values: [
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None,
],
storage_value: InsertTrieNodeStorageValue::Value {
value: Cow::Borrowed(b"world"),
references_merkle_value: false,
},
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
)
.unwrap()
.unwrap()
.0,
b"hello"
);
assert_eq!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1, 1].into_iter(),
)
.unwrap()
.unwrap()
.0,
b"world"
);
assert!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
)
.unwrap()
.is_none()
);
assert!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 2].into_iter(),
)
.unwrap()
.is_none()
);
assert!(
db.block_storage_get(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
)
.unwrap()
.is_none()
);
}
#[test]
fn storage_next_key_partial() {
let DatabaseOpen::Empty(empty_db) = open(Config {
block_number_bytes: 4,
cache_size: 2 * 1024 * 1024,
ty: ConfigTy::Memory,
})
.unwrap() else {
panic!()
};
let db = empty_db
.initialize(
&header::HeaderRef {
number: 0,
extrinsics_root: &[0; 32],
parent_hash: &[0; 32],
state_root: &[1; 32],
digest: header::DigestRef::empty(),
}
.scale_encoding_vec(4),
iter::empty(),
None,
)
.unwrap();
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
iter::empty(),
true
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
iter::empty(),
true
),
Err(StorageAccessError::IncompleteStorage)
));
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[1; 32]),
partial_key_nibbles: Cow::Borrowed(&[1, 1]),
children_merkle_values: [
None,
Some(Cow::Borrowed(&[2; 32])),
Some(Cow::Borrowed(&[3; 32])),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
storage_value: InsertTrieNodeStorageValue::NoValue,
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 0].into_iter(),
iter::empty(),
true
)
.unwrap()
.unwrap(),
vec![1, 1]
);
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
iter::empty(),
true
)
.unwrap()
.unwrap(),
vec![1, 1]
);
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
iter::empty(),
false
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 0].into_iter(),
iter::empty(),
true
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 0].into_iter(),
[1, 1, 0].into_iter(),
true
),
Ok(None)
));
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
iter::empty(),
true
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 3].into_iter(),
iter::empty(),
true
),
Ok(None)
));
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[3; 32]),
partial_key_nibbles: Cow::Borrowed(&[2]),
children_merkle_values: [
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None,
],
storage_value: InsertTrieNodeStorageValue::Value {
value: Cow::Borrowed(b"hello"),
references_merkle_value: false,
},
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
iter::empty(),
true
)
.unwrap()
.unwrap(),
vec![1, 1, 2, 2]
);
assert!(matches!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1, 1, 1, 1, 1].into_iter(),
iter::empty(),
true
),
Err(StorageAccessError::IncompleteStorage)
));
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[2; 32]),
partial_key_nibbles: Cow::Borrowed(&[1, 1]),
children_merkle_values: [
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None,
],
storage_value: InsertTrieNodeStorageValue::Value {
value: Cow::Borrowed(b"hello"),
references_merkle_value: false,
},
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
iter::empty(),
false
)
.unwrap()
.unwrap(),
vec![1, 1, 1, 1, 1]
);
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1, 1, 1, 1, 1].into_iter(),
iter::empty(),
true
)
.unwrap()
.unwrap(),
vec![1, 1, 2, 2]
);
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 3].into_iter(),
iter::empty(),
true
)
.unwrap(),
None
);
assert_eq!(
db.block_storage_next_key(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[3].into_iter(),
iter::empty(),
true
)
.unwrap(),
None
);
}
#[test]
fn storage_closest_descendant_merkle_value_partial() {
let DatabaseOpen::Empty(empty_db) = open(Config {
block_number_bytes: 4,
cache_size: 2 * 1024 * 1024,
ty: ConfigTy::Memory,
})
.unwrap() else {
panic!()
};
let db = empty_db
.initialize(
&header::HeaderRef {
number: 0,
extrinsics_root: &[0; 32],
parent_hash: &[0; 32],
state_root: &[1; 32],
digest: header::DigestRef::empty(),
}
.scale_encoding_vec(4),
iter::empty(),
None,
)
.unwrap();
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[].into_iter(),
)
.unwrap()
.unwrap(),
vec![1; 32]
);
assert!(matches!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert!(matches!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 2, 3, 4, 5].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[1; 32]),
partial_key_nibbles: Cow::Borrowed(&[1, 1]),
children_merkle_values: [
None,
Some(Cow::Borrowed(&[2; 32])),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
],
storage_value: InsertTrieNodeStorageValue::Value {
value: Cow::Borrowed(b"hello"),
references_merkle_value: false,
},
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1].into_iter(),
)
.unwrap()
.unwrap(),
vec![1; 32]
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
)
.unwrap()
.unwrap(),
vec![1; 32]
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1].into_iter(),
)
.unwrap()
.unwrap(),
vec![2; 32]
);
assert!(matches!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1].into_iter(),
),
Err(StorageAccessError::IncompleteStorage)
));
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
)
.unwrap(),
None
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[5].into_iter(),
)
.unwrap(),
None
);
db.insert_trie_nodes(
[InsertTrieNode {
merkle_value: Cow::Borrowed(&[2; 32]),
partial_key_nibbles: Cow::Borrowed(&[1, 1]),
children_merkle_values: [
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None,
],
storage_value: InsertTrieNodeStorageValue::Value {
value: Cow::Borrowed(b"world"),
references_merkle_value: false,
},
}]
.into_iter(),
0,
)
.unwrap();
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1].into_iter(),
)
.unwrap()
.unwrap(),
vec![1; 32]
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1].into_iter(),
)
.unwrap()
.unwrap(),
vec![2; 32]
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1].into_iter(),
)
.unwrap()
.unwrap(),
vec![2; 32]
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 2].into_iter(),
)
.unwrap(),
None
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 2].into_iter(),
)
.unwrap(),
None
);
assert_eq!(
db.block_storage_closest_descendant_merkle_value(
&db.block_hash_by_number(0).unwrap().next().unwrap(),
iter::empty::<iter::Empty<_>>(),
[1, 1, 1, 1, 1, 1, 1, 1].into_iter(),
)
.unwrap(),
None
);
}