From 469091f5605e8a0e023ccc3a9af7ede66bbbacf5 Mon Sep 17 00:00:00 2001 From: chiefbiiko <22937570+chiefbiiko@users.noreply.github.com> Date: Wed, 23 Nov 2022 16:10:45 +0100 Subject: [PATCH 1/3] feat: intro blake3 --- Cargo.lock | 24 ++++--- frame/support/Cargo.toml | 2 +- frame/support/procedural/src/lib.rs | 12 +++- frame/support/procedural/src/storage/mod.rs | 9 +++ frame/support/procedural/src/storage/parse.rs | 15 ++++ frame/support/src/hash.rs | 71 ++++++++++++++++++- frame/support/src/lib.rs | 9 +-- primitives/core/Cargo.toml | 3 + primitives/core/hashing/Cargo.toml | 2 + .../core/hashing/proc-macro/src/impls.rs | 12 ++++ primitives/core/hashing/proc-macro/src/lib.rs | 27 +++++++ primitives/core/hashing/src/lib.rs | 48 +++++++++++++ primitives/core/src/hasher.rs | 19 +++++ primitives/core/src/hashing.rs | 7 ++ primitives/core/src/lib.rs | 6 +- primitives/io/src/lib.rs | 52 ++++++++++++++ primitives/runtime/src/traits.rs | 27 +++++++ 17 files changed, 327 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8c21b9830eea..0b98f19ce5758 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -600,7 +600,7 @@ checksum = "72936ee4afc7f8f736d1c38383b56480b5497b4617b4a77bdbf1d2ababc76127" dependencies = [ "arrayref", "arrayvec 0.7.2", - "constant_time_eq", + "constant_time_eq 0.1.5", ] [[package]] @@ -611,20 +611,21 @@ checksum = "db539cc2b5f6003621f1cd9ef92d7ded8ea5232c7de0f9faa2de251cd98730d4" dependencies = [ "arrayref", "arrayvec 0.7.2", - "constant_time_eq", + "constant_time_eq 0.1.5", ] [[package]] name = "blake3" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +checksum = "895adc16c8b3273fbbc32685a7d55227705eda08c01e77704020f3491924b44b" dependencies = [ "arrayref", "arrayvec 0.7.2", "cc", "cfg-if", - "constant_time_eq", + "constant_time_eq 0.2.4", + "digest 0.10.3", ] [[package]] @@ -1059,6 +1060,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "constant_time_eq" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" + [[package]] name = "core-foundation" version = "0.9.3" @@ -2287,9 +2294,8 @@ dependencies = [ [[package]] name = "frame-metadata" -version = "15.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" +version = "15.1.0" +source = "git+https://github.com/chiefbiiko/frame-metadata?branch=blake3#85ba1c4c2ffede3cfed0db1d772c5bf2a44aa3b3" dependencies = [ "cfg-if", "parity-scale-codec", @@ -9534,6 +9540,7 @@ dependencies = [ "base58", "bitflags", "blake2", + "blake3", "byteorder", "criterion", "dyn-clonable", @@ -9579,6 +9586,7 @@ name = "sp-core-hashing" version = "5.0.0" dependencies = [ "blake2", + "blake3", "byteorder", "digest 0.10.3", "sha2 0.10.2", diff --git a/frame/support/Cargo.toml b/frame/support/Cargo.toml index b199c014d35ed..b420438934fd9 100644 --- a/frame/support/Cargo.toml +++ b/frame/support/Cargo.toml @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"] serde = { version = "1.0.136", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -frame-metadata = { version = "15.0.0", default-features = false, features = ["v14"] } +frame-metadata = { version = "15.1.0", default-features = false, features = ["v14"], git = "https://github.com/chiefbiiko/frame-metadata", branch = "blake3" } sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" } sp-std = { version = "5.0.0", default-features = false, path = "../../primitives/std" } sp-io = { version = "7.0.0", default-features = false, path = "../../primitives/io" } diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 41dbc4ee9592c..ef0041582a38a 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -114,11 +114,15 @@ fn get_cargo_env_var(version_env: &str) -> std::result::Result(version_env: &str) -> std::result::Result quote!(Blake2_256), HasherKind::Blake2_128 => quote!(Blake2_128), HasherKind::Blake2_128Concat => quote!(Blake2_128Concat), + HasherKind::Blake3_256 => quote!(Blake3_256), + HasherKind::Blake3_128 => quote!(Blake3_128), + HasherKind::Blake3_128Concat => quote!(Blake3_128Concat), HasherKind::Twox256 => quote!(Twox256), HasherKind::Twox128 => quote!(Twox128), HasherKind::Twox64Concat => quote!(Twox64Concat), @@ -457,6 +463,9 @@ impl HasherKind { HasherKind::Blake2_256 => quote!(StorageHasher::Blake2_256), HasherKind::Blake2_128 => quote!(StorageHasher::Blake2_128), HasherKind::Blake2_128Concat => quote!(StorageHasher::Blake2_128Concat), + HasherKind::Blake3_256 => quote!(StorageHasher::Blake3_256), + HasherKind::Blake3_128 => quote!(StorageHasher::Blake3_128), + HasherKind::Blake3_128Concat => quote!(StorageHasher::Blake3_128Concat), HasherKind::Twox256 => quote!(StorageHasher::Twox256), HasherKind::Twox128 => quote!(StorageHasher::Twox128), HasherKind::Twox64Concat => quote!(StorageHasher::Twox64Concat), diff --git a/frame/support/procedural/src/storage/parse.rs b/frame/support/procedural/src/storage/parse.rs index 54026b7d78b19..0181afcb62db7 100644 --- a/frame/support/procedural/src/storage/parse.rs +++ b/frame/support/procedural/src/storage/parse.rs @@ -35,6 +35,9 @@ mod keyword { syn::custom_keyword!(opaque_blake2_256); syn::custom_keyword!(opaque_blake2_128); syn::custom_keyword!(blake2_128_concat); + syn::custom_keyword!(opaque_blake3_256); + syn::custom_keyword!(opaque_blake3_128); + syn::custom_keyword!(blake3_128_concat); syn::custom_keyword!(opaque_twox_256); syn::custom_keyword!(opaque_twox_128); syn::custom_keyword!(twox_64_concat); @@ -275,6 +278,9 @@ enum Hasher { Blake2_256(keyword::opaque_blake2_256), Blake2_128(keyword::opaque_blake2_128), Blake2_128Concat(keyword::blake2_128_concat), + Blake3_256(keyword::opaque_blake3_256), + Blake3_128(keyword::opaque_blake3_128), + Blake3_128Concat(keyword::blake3_128_concat), Twox256(keyword::opaque_twox_256), Twox128(keyword::opaque_twox_128), Twox64Concat(keyword::twox_64_concat), @@ -290,6 +296,12 @@ impl syn::parse::Parse for Hasher { Ok(Self::Blake2_128(input.parse()?)) } else if lookahead.peek(keyword::blake2_128_concat) { Ok(Self::Blake2_128Concat(input.parse()?)) + } else if lookahead.peek(keyword::opaque_blake3_256) { + Ok(Self::Blake3_256(input.parse()?)) + } else if lookahead.peek(keyword::opaque_blake3_128) { + Ok(Self::Blake3_128(input.parse()?)) + } else if lookahead.peek(keyword::blake3_128_concat) { + Ok(Self::Blake3_128Concat(input.parse()?)) } else if lookahead.peek(keyword::opaque_twox_256) { Ok(Self::Twox256(input.parse()?)) } else if lookahead.peek(keyword::opaque_twox_128) { @@ -346,6 +358,9 @@ impl From for super::HasherKind { Hasher::Blake2_256(_) => super::HasherKind::Blake2_256, Hasher::Blake2_128(_) => super::HasherKind::Blake2_128, Hasher::Blake2_128Concat(_) => super::HasherKind::Blake2_128Concat, + Hasher::Blake3_256(_) => super::HasherKind::Blake3_256, + Hasher::Blake3_128(_) => super::HasherKind::Blake3_128, + Hasher::Blake3_128Concat(_) => super::HasherKind::Blake3_128Concat, Hasher::Twox256(_) => super::HasherKind::Twox256, Hasher::Twox128(_) => super::HasherKind::Twox128, Hasher::Twox64Concat(_) => super::HasherKind::Twox64Concat, diff --git a/frame/support/src/hash.rs b/frame/support/src/hash.rs index 9bdad6d9d59de..dd14881c61938 100644 --- a/frame/support/src/hash.rs +++ b/frame/support/src/hash.rs @@ -19,7 +19,7 @@ use crate::metadata; use codec::{Codec, MaxEncodedLen}; -use sp_io::hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64}; +use sp_io::hashing::{blake2_128, blake2_256, blake3_128, blake3_256, twox_128, twox_256, twox_64}; use sp_std::prelude::Vec; // This trait must be kept coherent with frame-support-procedural HasherKind usage @@ -27,6 +27,9 @@ pub trait Hashable: Sized { fn blake2_128(&self) -> [u8; 16]; fn blake2_256(&self) -> [u8; 32]; fn blake2_128_concat(&self) -> Vec; + fn blake3_128(&self) -> [u8; 16]; + fn blake3_256(&self) -> [u8; 32]; + fn blake3_128_concat(&self) -> Vec; fn twox_128(&self) -> [u8; 16]; fn twox_256(&self) -> [u8; 32]; fn twox_64_concat(&self) -> Vec; @@ -43,6 +46,15 @@ impl Hashable for T { fn blake2_128_concat(&self) -> Vec { self.using_encoded(Blake2_128Concat::hash) } + fn blake3_128(&self) -> [u8; 16] { + self.using_encoded(blake3_128) + } + fn blake3_256(&self) -> [u8; 32] { + self.using_encoded(blake3_256) + } + fn blake3_128_concat(&self) -> Vec { + self.using_encoded(Blake3_128Concat::hash) + } fn twox_128(&self) -> [u8; 16] { self.using_encoded(twox_128) } @@ -165,6 +177,54 @@ impl StorageHasher for Blake2_256 { } } +/// Hash storage keys with `concat(blake3_128(key), key)` +pub struct Blake3_128Concat; +impl StorageHasher for Blake3_128Concat { + const METADATA: metadata::StorageHasher = metadata::StorageHasher::Blake3_128Concat; + type Output = Vec; + fn hash(x: &[u8]) -> Vec { + blake3_128(x).iter().chain(x.iter()).cloned().collect::>() + } + fn max_len() -> usize { + K::max_encoded_len().saturating_add(16) + } +} +impl ReversibleStorageHasher for Blake3_128Concat { + fn reverse(x: &[u8]) -> &[u8] { + if x.len() < 16 { + log::error!("Invalid reverse: hash length too short"); + return &[] + } + &x[16..] + } +} + +/// Hash storage keys with blake3 128 +pub struct Blake3_128; +impl StorageHasher for Blake3_128 { + const METADATA: metadata::StorageHasher = metadata::StorageHasher::Blake3_128; + type Output = [u8; 16]; + fn hash(x: &[u8]) -> [u8; 16] { + blake3_128(x) + } + fn max_len() -> usize { + 16 + } +} + +/// Hash storage keys with blake3 256 +pub struct Blake3_256; +impl StorageHasher for Blake3_256 { + const METADATA: metadata::StorageHasher = metadata::StorageHasher::Blake3_256; + type Output = [u8; 32]; + fn hash(x: &[u8]) -> [u8; 32] { + blake3_256(x) + } + fn max_len() -> usize { + 32 + } +} + /// Hash storage keys with twox 128 pub struct Twox128; impl StorageHasher for Twox128 { @@ -207,6 +267,12 @@ mod tests { assert_eq!(r.split_at(16), (&blake2_128(b"foo")[..], &b"foo"[..])) } + #[test] + fn test_blake3_128_concat() { + let r = Blake3_128Concat::hash(b"foo"); + assert_eq!(r.split_at(16), (&blake3_128(b"foo")[..], &b"foo"[..])) + } + #[test] fn max_lengths() { use codec::Encode; @@ -217,6 +283,9 @@ mod tests { assert_eq!(Blake2_128::hash(encoded_0u32).len(), Blake2_128::max_len::()); assert_eq!(Blake2_128Concat::hash(encoded_0u32).len(), Blake2_128Concat::max_len::()); assert_eq!(Blake2_256::hash(encoded_0u32).len(), Blake2_256::max_len::()); + assert_eq!(Blake3_128::hash(encoded_0u32).len(), Blake3_128::max_len::()); + assert_eq!(Blake3_128Concat::hash(encoded_0u32).len(), Blake3_128Concat::max_len::()); + assert_eq!(Blake3_256::hash(encoded_0u32).len(), Blake3_256::max_len::()); assert_eq!(Identity::hash(encoded_0u32).len(), Identity::max_len::()); } } diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index efecbb75f9c62..b3af2b4e4e917 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -98,8 +98,8 @@ pub use self::storage::storage_noop_guard::StorageNoopGuard; pub use self::{ dispatch::{Callable, Parameter}, hash::{ - Blake2_128, Blake2_128Concat, Blake2_256, Hashable, Identity, ReversibleStorageHasher, - StorageHasher, Twox128, Twox256, Twox64Concat, + Blake2_128, Blake2_128Concat, Blake2_256, Blake3_128, Blake3_128Concat, Blake3_256, + Hashable, Identity, ReversibleStorageHasher, StorageHasher, Twox128, Twox256, Twox64Concat, }, storage::{ bounded_btree_map::BoundedBTreeMap, @@ -1404,8 +1404,9 @@ pub mod pallet_prelude { ConstU32, EnsureOrigin, Get, GetDefault, GetStorageVersion, Hooks, IsType, PalletInfoAccess, StorageInfoTrait, StorageVersion, TypedGet, }, - Blake2_128, Blake2_128Concat, Blake2_256, CloneNoBound, DebugNoBound, EqNoBound, Identity, - PartialEqNoBound, RuntimeDebug, RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, + Blake2_128, Blake2_128Concat, Blake2_256, Blake3_128, Blake3_128Concat, Blake3_256, + CloneNoBound, DebugNoBound, EqNoBound, Identity, PartialEqNoBound, RuntimeDebug, + RuntimeDebugNoBound, Twox128, Twox256, Twox64Concat, }; pub use codec::{Decode, Encode, MaxEncodedLen}; pub use frame_support::pallet_macros::*; diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index bfec09a13c135..4dff728d9f5e3 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -49,6 +49,7 @@ bitflags = "1.3" array-bytes = { version = "4.1", optional = true } ed25519-zebra = { version = "3.1.0", default-features = false, optional = true } blake2 = { version = "0.10.4", default-features = false, optional = true } +blake3 = { version = "1.3.2", default-features = false, optional = true } schnorrkel = { version = "0.9.1", features = [ "preaudit_deprecated", "u64_backend", @@ -96,6 +97,7 @@ std = [ "sp-std/std", "serde", "blake2/std", + "blake3/std", "array-bytes", "ed25519-zebra/std", "base58", @@ -129,6 +131,7 @@ full_crypto = [ "array-bytes", "ed25519-zebra", "blake2", + "blake3", "schnorrkel", "libsecp256k1", "secp256k1", diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index 1bb67ffff5142..2dbd6f17a7b82 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] blake2 = { version = "0.10.4", default-features = false } +blake3 = { version = "1.3.2", default-features = false } byteorder = { version = "1.3.2", default-features = false } digest = { version = "0.10.3", default-features = false } sha2 = { version = "0.10.2", default-features = false } @@ -26,6 +27,7 @@ default = ["std"] std = [ "digest/std", "blake2/std", + "blake3/std", "byteorder/std", "sha2/std", "sha3/std", diff --git a/primitives/core/hashing/proc-macro/src/impls.rs b/primitives/core/hashing/proc-macro/src/impls.rs index 3058cf019b143..84cba02003ee4 100644 --- a/primitives/core/hashing/proc-macro/src/impls.rs +++ b/primitives/core/hashing/proc-macro/src/impls.rs @@ -102,6 +102,18 @@ pub(super) fn blake2b_64(bytes: Vec) -> TokenStream { bytes_to_array(sp_core_hashing::blake2_64(bytes.as_slice())) } +pub(super) fn blake3_512(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::blake3_512(bytes.as_slice())) +} + +pub(super) fn blake3_256(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::blake3_256(bytes.as_slice())) +} + +pub(super) fn blake3_64(bytes: Vec) -> TokenStream { + bytes_to_array(sp_core_hashing::blake3_64(bytes.as_slice())) +} + pub(super) fn keccak_256(bytes: Vec) -> TokenStream { bytes_to_array(sp_core_hashing::keccak_256(bytes.as_slice())) } diff --git a/primitives/core/hashing/proc-macro/src/lib.rs b/primitives/core/hashing/proc-macro/src/lib.rs index 2db292d8dc0cb..9b539b76410f5 100644 --- a/primitives/core/hashing/proc-macro/src/lib.rs +++ b/primitives/core/hashing/proc-macro/src/lib.rs @@ -83,6 +83,33 @@ pub fn blake2b_512(input: TokenStream) -> TokenStream { impls::blake2b_512(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) } +/// Process a Blake3 64-bit hash of bytes parameter outputs a `[u8; 8]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn blake3_64(input: TokenStream) -> TokenStream { + impls::blake3_64(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a Blake3 256-bit hash of bytes parameter, outputs a `[u8; 32]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn blake3_256(input: TokenStream) -> TokenStream { + impls::blake3_256(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + +/// Apply a Blake3 512-bit hash of bytes parameter, outputs a `[u8; 64]`. +/// Multiple inputs are concatenated before hashing. +/// Input can be identifier (name of identifier as bytes is used), byte string or +/// array of bytes. +#[proc_macro] +pub fn blake3_512(input: TokenStream) -> TokenStream { + impls::blake3_512(syn::parse_macro_input!(input as MultipleInputBytes).concatenated()) +} + /// Apply a XX 64-bit hash on its bytes parameter, outputs a `[u8; 8]`. /// Multiple inputs are concatenated before hashing. /// Input can be identifier (name of identifier as bytes is used), byte string or diff --git a/primitives/core/hashing/src/lib.rs b/primitives/core/hashing/src/lib.rs index e6ccd5aaa8fb9..49de80cecd286 100644 --- a/primitives/core/hashing/src/lib.rs +++ b/primitives/core/hashing/src/lib.rs @@ -79,6 +79,54 @@ pub fn blake2_64(data: &[u8]) -> [u8; 8] { r } +/// Do a Blake3 512-bit hash and place result in `dest`. +pub fn blake3_512_into(data: &[u8], dest: &mut [u8; 64]) { + blake3::Hasher::new().update(data).finalize_xof().fill(&mut dest[..]); +} + +/// Do a Blake3 512-bit hash and return result. +pub fn blake3_512(data: &[u8]) -> [u8; 64] { + let mut r = [0; 64]; + blake3_512_into(data, &mut r); + r +} + +/// Do a Blake3 256-bit hash and place result in `dest`. +pub fn blake3_256_into(data: &[u8], dest: &mut [u8; 32]) { + blake3::Hasher::new().update(data).finalize_xof().fill(&mut dest[..]); +} + +/// Do a Blake3 256-bit hash and return result. +pub fn blake3_256(data: &[u8]) -> [u8; 32] { + let mut r = [0; 32]; + blake3_256_into(data, &mut r); + r +} + +/// Do a Blake3 128-bit hash and place result in `dest`. +pub fn blake3_128_into(data: &[u8], dest: &mut [u8; 16]) { + blake3::Hasher::new().update(data).finalize_xof().fill(&mut dest[..]); +} + +/// Do a Blake3 128-bit hash and return result. +pub fn blake3_128(data: &[u8]) -> [u8; 16] { + let mut r = [0; 16]; + blake3_128_into(data, &mut r); + r +} + +/// Do a Blake3 64-bit hash and place result in `dest`. +pub fn blake3_64_into(data: &[u8], dest: &mut [u8; 8]) { + blake3::Hasher::new().update(data).finalize_xof().fill(&mut dest[..]); +} + +/// Do a Blake3 64-bit hash and return result. +pub fn blake3_64(data: &[u8]) -> [u8; 8] { + let mut r = [0; 8]; + blake3_64_into(data, &mut r); + r +} + /// Do a XX 64-bit hash and place result in `dest`. pub fn twox_64_into(data: &[u8], dest: &mut [u8; 8]) { let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish(); diff --git a/primitives/core/src/hasher.rs b/primitives/core/src/hasher.rs index 173bd560ad1e3..f024d826b2ded 100644 --- a/primitives/core/src/hasher.rs +++ b/primitives/core/src/hasher.rs @@ -36,6 +36,25 @@ pub mod blake2 { } } } +pub mod blake3 { + use crate::hash::H256; + use hash256_std_hasher::Hash256StdHasher; + use hash_db::Hasher; + + /// Concrete implementation of Hasher using Blake3 256-bit hashes + #[derive(Debug)] + pub struct Blake3Hasher; + + impl Hasher for Blake3Hasher { + type Out = H256; + type StdHasher = Hash256StdHasher; + const LENGTH: usize = 32; + + fn hash(x: &[u8]) -> Self::Out { + crate::hashing::blake3_256(x).into() + } + } +} pub mod keccak { use crate::hash::H256; diff --git a/primitives/core/src/hashing.rs b/primitives/core/src/hashing.rs index 1c439355a33c0..037055b0b4647 100644 --- a/primitives/core/src/hashing.rs +++ b/primitives/core/src/hashing.rs @@ -35,6 +35,13 @@ mod test { assert_eq!(sp_core_hashing_proc_macro::blake2b_512!(b""), blake2_512(b"")[..]); } + #[test] + fn blake3() { + assert_eq!(sp_core_hashing_proc_macro::blake3_64!(b""), blake3_64(b"")[..]); + assert_eq!(sp_core_hashing_proc_macro::blake3_256!(b"test"), blake3_256(b"test")[..]); + assert_eq!(sp_core_hashing_proc_macro::blake3_512!(b""), blake3_512(b"")[..]); + } + #[test] fn keccak() { assert_eq!(sp_core_hashing_proc_macro::keccak_256!(b"test"), keccak_256(b"test")[..]); diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index fda7604d5337f..8c6e17b004050 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -50,7 +50,9 @@ pub use impl_serde::serialize as bytes; pub mod hashing; #[cfg(feature = "full_crypto")] -pub use hashing::{blake2_128, blake2_256, keccak_256, twox_128, twox_256, twox_64}; +pub use hashing::{ + blake2_128, blake2_256, blake3_128, blake3_256, keccak_256, twox_128, twox_256, twox_64, +}; pub mod bounded; pub mod crypto; pub mod hexdisplay; @@ -78,6 +80,8 @@ pub use crypto::{ByteArray, DeriveJunction, Pair, Public}; #[cfg(feature = "std")] pub use self::hasher::blake2::Blake2Hasher; #[cfg(feature = "std")] +pub use self::hasher::blake3::Blake3Hasher; +#[cfg(feature = "std")] pub use self::hasher::keccak::KeccakHasher; pub use hash_db::Hasher; diff --git a/primitives/io/src/lib.rs b/primitives/io/src/lib.rs index 33516bb0397f3..67c59f1ac697a 100644 --- a/primitives/io/src/lib.rs +++ b/primitives/io/src/lib.rs @@ -533,6 +533,22 @@ pub trait Trie { } } + /// A trie root formed from the iterated items. + fn blake3_256_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> H256 { + match version { + StateVersion::V0 => LayoutV0::::trie_root(input), + StateVersion::V1 => LayoutV1::::trie_root(input), + } + } + + /// A trie root formed from the enumerated items. + fn blake3_256_ordered_root(input: Vec>, version: StateVersion) -> H256 { + match version { + StateVersion::V0 => LayoutV0::::ordered_trie_root(input), + StateVersion::V1 => LayoutV1::::ordered_trie_root(input), + } + } + /// A trie root formed from the iterated items. fn keccak_256_root(input: Vec<(Vec, Vec)>) -> H256 { LayoutV0::::trie_root(input) @@ -598,6 +614,32 @@ pub trait Trie { } } + /// Verify trie proof + fn blake3_256_verify_proof( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + version: StateVersion, + ) -> bool { + match version { + StateVersion::V0 => sp_trie::verify_trie_proof::< + LayoutV0, + _, + _, + _, + >(&root, proof, &[(key, Some(value))]) + .is_ok(), + StateVersion::V1 => sp_trie::verify_trie_proof::< + LayoutV1, + _, + _, + _, + >(&root, proof, &[(key, Some(value))]) + .is_ok(), + } + } + /// Verify trie proof fn keccak_256_verify_proof(root: H256, proof: &[Vec], key: &[u8], value: &[u8]) -> bool { sp_trie::verify_trie_proof::, _, _, _>( @@ -1103,6 +1145,16 @@ pub trait Hashing { sp_core::hashing::blake2_256(data) } + /// Conduct a 128-bit Blake3 hash. + fn blake3_128(data: &[u8]) -> [u8; 16] { + sp_core::hashing::blake3_128(data) + } + + /// Conduct a 256-bit Blake3 hash. + fn blake3_256(data: &[u8]) -> [u8; 32] { + sp_core::hashing::blake3_256(data) + } + /// Conduct four XX hashes to give a 256-bit result. fn twox_256(data: &[u8]) -> [u8; 32] { sp_core::hashing::twox_256(data) diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index 1c48b1933431d..bbc24b2d48e53 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -708,6 +708,33 @@ impl Hash for BlakeTwo256 { } } +/// Blake3-256 Hash implementation. +#[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BlakeThree256; + +impl Hasher for BlakeThree256 { + type Out = sp_core::H256; + type StdHasher = hash256_std_hasher::Hash256StdHasher; + const LENGTH: usize = 32; + + fn hash(s: &[u8]) -> Self::Out { + sp_io::hashing::blake3_256(s).into() + } +} + +impl Hash for BlakeThree256 { + type Output = sp_core::H256; + + fn trie_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> Self::Output { + sp_io::trie::blake3_256_root(input, version) + } + + fn ordered_trie_root(input: Vec>, version: StateVersion) -> Self::Output { + sp_io::trie::blake3_256_ordered_root(input, version) + } +} + /// Keccak-256 Hash implementation. #[derive(PartialEq, Eq, Clone, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] From 9171aa8db66b8ac940c9804c7292c9d48b1ca7f4 Mon Sep 17 00:00:00 2001 From: chiefbiiko <22937570+chiefbiiko@users.noreply.github.com> Date: Sat, 26 Nov 2022 17:15:31 +0100 Subject: [PATCH 2/3] chore: align blake3 dep versions --- primitives/core/Cargo.toml | 2 +- primitives/core/hashing/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/primitives/core/Cargo.toml b/primitives/core/Cargo.toml index 4dff728d9f5e3..ab937328353b0 100644 --- a/primitives/core/Cargo.toml +++ b/primitives/core/Cargo.toml @@ -49,7 +49,7 @@ bitflags = "1.3" array-bytes = { version = "4.1", optional = true } ed25519-zebra = { version = "3.1.0", default-features = false, optional = true } blake2 = { version = "0.10.4", default-features = false, optional = true } -blake3 = { version = "1.3.2", default-features = false, optional = true } +blake3 = { version = "^1.3", default-features = false, optional = true } schnorrkel = { version = "0.9.1", features = [ "preaudit_deprecated", "u64_backend", diff --git a/primitives/core/hashing/Cargo.toml b/primitives/core/hashing/Cargo.toml index 2dbd6f17a7b82..0230158507013 100644 --- a/primitives/core/hashing/Cargo.toml +++ b/primitives/core/hashing/Cargo.toml @@ -14,7 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] blake2 = { version = "0.10.4", default-features = false } -blake3 = { version = "1.3.2", default-features = false } +blake3 = { version = "^1.3", default-features = false } byteorder = { version = "1.3.2", default-features = false } digest = { version = "0.10.3", default-features = false } sha2 = { version = "0.10.2", default-features = false } From 6c34175f39876c39f577c61ee6ee872cc9639945 Mon Sep 17 00:00:00 2001 From: chiefbiiko <22937570+chiefbiiko@users.noreply.github.com> Date: Sun, 27 Nov 2022 08:10:30 +0100 Subject: [PATCH 3/3] chore: update frame-support pallet_ui fixtures --- .../pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr | 2 +- .../storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr index 42ef5a34e4c30..50c6bdb3a5dbd 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen.stderr @@ -69,7 +69,7 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied (A, B, C, D) (A, B, C, D, E) (A, B, C, D, E, F) - and 161 others + and 162 others = note: required for `Bar` to implement `StaticTypeInfo` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `StorageEntryMetadataBuilder` diff --git a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr index 461d63ebb0d9c..bc7841cb56f0e 100644 --- a/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr +++ b/frame/support/test/tests/pallet_ui/storage_ensure_span_are_ok_on_wrong_gen_unnamed.stderr @@ -69,7 +69,7 @@ error[E0277]: the trait bound `Bar: TypeInfo` is not satisfied (A, B, C, D) (A, B, C, D, E) (A, B, C, D, E, F) - and 161 others + and 162 others = note: required for `Bar` to implement `StaticTypeInfo` = note: required for `frame_support::pallet_prelude::StorageValue<_GeneratedPrefixForStorageFoo, Bar>` to implement `StorageEntryMetadataBuilder`