Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for keccak256 trie host functions #906

Merged
merged 6 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions full-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ async fn open_database(
partial_key,
storage_value,
},
trie::HashFunction::Blake2,
is_root_node,
)
.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ schnorrkel = { version = "0.10.2", default-features = false, features = ["preaud
serde = { version = "1.0.167", default-features = false, features = ["alloc", "derive"] }
serde_json = { version = "1.0.102", default-features = false, features = ["alloc", "raw_value"] }
sha2 = { version = "0.10.7", default-features = false }
sha3 = { version = "0.10.8", default-features = false }
siphasher = { version = "0.3.10", default-features = false }
slab = { version = "0.4.8", default-features = false }
smallvec = { version = "1.11.0", default-features = false }
tiny-keccak = { version = "2.0", features = ["keccak"] }
twox-hash = { version = "1.6.3", default-features = false }
wasmi = { version = "0.30.0", default-features = false }
x25519-dalek = { version = "2.0.0-rc.3", default-features = false, features = ["alloc", "precomputed-tables", "static_secrets", "zeroize"] }
Expand Down
2 changes: 1 addition & 1 deletion lib/src/chain/chain_information/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ impl ChainInformationBuild {
parent_hash: &[0; 32],
number: 0,
state_root: &state_trie_root_hash,
extrinsics_root: &trie::EMPTY_TRIE_MERKLE_VALUE,
extrinsics_root: &trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE,
digest: header::DigestRef::empty(),
}
.scale_encoding_vec(inner.block_number_bytes);
Expand Down
3 changes: 2 additions & 1 deletion lib/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ impl ChainSpec {
match self.genesis_storage() {
GenesisStorage::TrieRootHash(hash) => *hash,
GenesisStorage::Items(genesis_storage) => {
let mut calculation = trie::calculate_root::root_merkle_value();
let mut calculation =
trie::calculate_root::root_merkle_value(trie::HashFunction::Blake2);

loop {
match calculation {
Expand Down
3 changes: 2 additions & 1 deletion lib/src/database/full_sqlite/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ fn empty_database_fill_then_query() {
partial_key,
storage_value,
},
trie::HashFunction::Blake2,
is_root_node,
)
.unwrap();
Expand All @@ -118,7 +119,7 @@ fn empty_database_fill_then_query() {
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_TRIE_MERKLE_VALUE);
.unwrap_or(trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE);

let trie_entries_linear =
trie.iter_unordered()
Expand Down
86 changes: 51 additions & 35 deletions lib/src/executor/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,6 @@ use alloc::{
vec::Vec,
};
use core::{fmt, hash::Hasher as _, iter, str};
use sha2::Digest as _;
use tiny_keccak::Hasher as _;

pub mod runtime_version;

Expand Down Expand Up @@ -1608,31 +1606,21 @@ impl ReadyToRun {
})
}
HostFunction::ext_hashing_keccak_256_version_1 => {
let mut keccak = tiny_keccak::Keccak::v256();
keccak.update(expect_pointer_size!(0).as_ref());
let mut out = [0u8; 32];
keccak.finalize(&mut out);

let hash =
<sha3::Keccak256 as sha3::Digest>::digest(expect_pointer_size!(0).as_ref());
self.inner
.alloc_write_and_return_pointer(host_fn.name(), iter::once(&out))
.alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash))
}
HostFunction::ext_hashing_keccak_512_version_1 => {
let mut keccak = tiny_keccak::Keccak::v512();
keccak.update(expect_pointer_size!(0).as_ref());
let mut out = [0u8; 64];
keccak.finalize(&mut out);

let hash =
<sha3::Keccak512 as sha3::Digest>::digest(expect_pointer_size!(0).as_ref());
self.inner
.alloc_write_and_return_pointer(host_fn.name(), iter::once(&out))
.alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash))
}
HostFunction::ext_hashing_sha2_256_version_1 => {
let mut hasher = sha2::Sha256::new();
hasher.update(expect_pointer_size!(0));

self.inner.alloc_write_and_return_pointer(
host_fn.name(),
iter::once(hasher.finalize().as_slice()),
)
let hash = <sha2::Sha256 as sha2::Digest>::digest(expect_pointer_size!(0).as_ref());
self.inner
.alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash))
}
HostFunction::ext_hashing_blake2_128_version_1 => {
let out = {
Expand Down Expand Up @@ -1815,13 +1803,18 @@ impl ReadyToRun {
host_fn_not_implemented!()
}
HostFunction::ext_trie_blake2_256_root_version_1
| HostFunction::ext_trie_blake2_256_root_version_2 => {
let state_version =
if matches!(host_fn, HostFunction::ext_trie_blake2_256_root_version_2) {
expect_state_version!(1)
} else {
TrieEntryVersion::V0
};
| HostFunction::ext_trie_blake2_256_root_version_2
| HostFunction::ext_trie_keccak_256_root_version_1
| HostFunction::ext_trie_keccak_256_root_version_2 => {
let state_version = if matches!(
host_fn,
HostFunction::ext_trie_blake2_256_root_version_2
| HostFunction::ext_trie_keccak_256_root_version_2
) {
expect_state_version!(1)
} else {
TrieEntryVersion::V0
};

let result = {
let input = expect_pointer_size!(0);
Expand All @@ -1848,7 +1841,19 @@ impl ReadyToRun {
.map(|(_, parse_result)| parse_result);

match parsing_result {
Ok(elements) => Ok(trie::trie_root(state_version, &elements[..])),
Ok(elements) => Ok(trie::trie_root(
state_version,
if matches!(
host_fn,
HostFunction::ext_trie_blake2_256_root_version_1
| HostFunction::ext_trie_blake2_256_root_version_2
) {
trie::HashFunction::Blake2
} else {
trie::HashFunction::Keccak256
},
&elements[..],
)),
Err(_) => Err(()),
}
};
Expand All @@ -1864,10 +1869,13 @@ impl ReadyToRun {
}
}
HostFunction::ext_trie_blake2_256_ordered_root_version_1
| HostFunction::ext_trie_blake2_256_ordered_root_version_2 => {
| HostFunction::ext_trie_blake2_256_ordered_root_version_2
| HostFunction::ext_trie_keccak_256_ordered_root_version_1
| HostFunction::ext_trie_keccak_256_ordered_root_version_2 => {
let state_version = if matches!(
host_fn,
HostFunction::ext_trie_blake2_256_ordered_root_version_2
| HostFunction::ext_trie_keccak_256_ordered_root_version_2
) {
expect_state_version!(1)
} else {
Expand All @@ -1893,7 +1901,19 @@ impl ReadyToRun {
.map(|(_, parse_result)| parse_result);

match parsing_result {
Ok(elements) => Ok(trie::ordered_root(state_version, &elements[..])),
Ok(elements) => Ok(trie::ordered_root(
state_version,
if matches!(
host_fn,
HostFunction::ext_trie_blake2_256_ordered_root_version_1
| HostFunction::ext_trie_blake2_256_ordered_root_version_2
) {
trie::HashFunction::Blake2
} else {
trie::HashFunction::Keccak256
},
&elements[..],
)),
Err(_) => Err(()),
}
};
Expand All @@ -1908,10 +1928,6 @@ impl ReadyToRun {
},
}
}
HostFunction::ext_trie_keccak_256_root_version_1 => host_fn_not_implemented!(),
HostFunction::ext_trie_keccak_256_root_version_2 => host_fn_not_implemented!(),
HostFunction::ext_trie_keccak_256_ordered_root_version_1 => host_fn_not_implemented!(),
HostFunction::ext_trie_keccak_256_ordered_root_version_2 => host_fn_not_implemented!(),
HostFunction::ext_trie_blake2_256_verify_proof_version_1 => host_fn_not_implemented!(),
HostFunction::ext_trie_blake2_256_verify_proof_version_2 => host_fn_not_implemented!(),
HostFunction::ext_trie_keccak_256_verify_proof_version_1 => host_fn_not_implemented!(),
Expand Down
2 changes: 1 addition & 1 deletion lib/src/executor/runtime_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,7 @@ impl Inner {
main_trie_key.extend_from_slice(DEFAULT_CHILD_STORAGE_SPECIAL_PREFIX);
main_trie_key.extend_from_slice(child_trie);

if trie_root_hash != trie::EMPTY_TRIE_MERKLE_VALUE {
if trie_root_hash != trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE {
self.pending_storage_changes
.trie_diffs
.entry(None)
Expand Down
7 changes: 4 additions & 3 deletions lib/src/executor/trie_root_calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl ClosestDescendant {
} else {
// If the element doesn't have a parent, then the trie is completely empty.
InProgress::Finished {
trie_root_hash: trie::EMPTY_TRIE_MERKLE_VALUE,
trie_root_hash: trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE,
}
};
}
Expand Down Expand Up @@ -339,7 +339,7 @@ impl StorageValue {
// This case is handled separately in order to not generate
// a `TrieNodeInsertUpdateEvent` for a node that doesn't actually exist.
InProgress::Finished {
trie_root_hash: trie::EMPTY_TRIE_MERKLE_VALUE,
trie_root_hash: trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE,
}
}

Expand Down Expand Up @@ -373,6 +373,7 @@ impl StorageValue {
(None, _) => trie::trie_node::StorageValue::None,
},
},
trie::HashFunction::Blake2,
parent_node.is_none(),
)
.unwrap_or_else(|_| panic!());
Expand Down Expand Up @@ -582,7 +583,7 @@ impl TrieNodeRemoveEvent {
self.inner.next()
} else {
InProgress::Finished {
trie_root_hash: trie::EMPTY_TRIE_MERKLE_VALUE,
trie_root_hash: trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE,
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions lib/src/executor/trie_root_calculator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn empty_trie_works() {
loop {
match calculation {
InProgress::Finished { trie_root_hash } => {
assert_eq!(trie_root_hash, trie::EMPTY_TRIE_MERKLE_VALUE);
assert_eq!(trie_root_hash, trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE);
return;
}
InProgress::ClosestDescendant(req) => {
Expand Down Expand Up @@ -72,6 +72,7 @@ fn one_inserted_node_in_diff() {
partial_key: trie::bytes_to_nibbles(vec![0xaa, 0xaa].into_iter()),
storage_value: trie::trie_node::StorageValue::Unhashed(b"foo"),
},
trie::HashFunction::Blake2,
true,
)
.unwrap();
Expand Down Expand Up @@ -263,6 +264,7 @@ fn fuzzing() {
partial_key,
storage_value,
},
trie::HashFunction::Blake2,
is_root_node,
)
.unwrap();
Expand Down Expand Up @@ -410,7 +412,7 @@ fn fuzzing() {
let expected_hash = trie_after_diff
.root_user_data()
.map(|n| *<&[u8; 32]>::try_from(n.1.as_ref().unwrap().as_ref()).unwrap())
.unwrap_or(trie::EMPTY_TRIE_MERKLE_VALUE);
.unwrap_or(trie::EMPTY_BLAKE2_TRIE_MERKLE_VALUE);
if obtained_hash != expected_hash {
panic!(
"\nexpected = {:?}\ncalculated = {:?}\ntrie_before = {:?}\ndiff = {:?}",
Expand Down
6 changes: 5 additions & 1 deletion lib/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ pub fn hash_from_scale_encoded_header_vectored(
/// transactions in that block.
pub fn extrinsics_root(transactions: &[impl AsRef<[u8]>]) -> [u8; 32] {
// The extrinsics root is always calculated with V0 of the trie.
trie::ordered_root(trie::TrieEntryVersion::V0, transactions)
trie::ordered_root(
trie::TrieEntryVersion::V0,
trie::HashFunction::Blake2,
transactions,
)
}

/// Attempt to decode the given SCALE-encoded header.
Expand Down
Loading