diff --git a/Cargo.lock b/Cargo.lock index c6bd6ddf0126..cd4c772945a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5973,6 +5973,7 @@ name = "frame-metadata-hash-extension" version = "0.1.0" dependencies = [ "array-bytes", + "const-hex", "docify", "frame-metadata", "frame-support", diff --git a/Cargo.toml b/Cargo.toml index 7ae7c3bd1811..f6794de9e458 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -668,6 +668,7 @@ codec = { version = "3.6.12", default-features = false, package = "parity-scale- collectives-westend-emulated-chain = { path = "cumulus/parachains/integration-tests/emulated/chains/parachains/collectives/collectives-westend" } collectives-westend-runtime = { path = "cumulus/parachains/runtimes/collectives/collectives-westend" } color-eyre = { version = "0.6.1", default-features = false } +const-hex = { version = "1.10.0", default-features = false } color-print = { version = "0.3.4" } colored = { version = "2.0.4" } comfy-table = { version = "7.1.0", default-features = false } diff --git a/substrate/frame/metadata-hash-extension/Cargo.toml b/substrate/frame/metadata-hash-extension/Cargo.toml index 10d90bba0911..f1934fed9ada 100644 --- a/substrate/frame/metadata-hash-extension/Cargo.toml +++ b/substrate/frame/metadata-hash-extension/Cargo.toml @@ -17,6 +17,7 @@ frame-support = { workspace = true } frame-system = { workspace = true } log = { workspace = true } docify = { workspace = true } +const-hex = { workspace = true } [dev-dependencies] substrate-wasm-builder = { features = ["metadata-hash"], workspace = true, default-features = true } @@ -36,4 +37,5 @@ std = [ "log/std", "scale-info/std", "sp-runtime/std", + "const-hex/std", ] diff --git a/substrate/frame/metadata-hash-extension/src/lib.rs b/substrate/frame/metadata-hash-extension/src/lib.rs index 4a75e00e73f7..de9e5d617e59 100644 --- a/substrate/frame/metadata-hash-extension/src/lib.rs +++ b/substrate/frame/metadata-hash-extension/src/lib.rs @@ -50,7 +50,6 @@ use sp_runtime::{ #[cfg(test)] mod tests; -mod utils; /// The mode of [`CheckMetadataHash`]. #[derive(Decode, Encode, PartialEq, Debug, TypeInfo, Clone, Copy, Eq)] @@ -69,9 +68,13 @@ enum MetadataHash { Custom([u8; 32]), } -const RUNTIME_METADATA: Option<[u8; 32]> = match option_env!("RUNTIME_METADATA_HASH") { - Some(hex) => utils::hex_str_to_32_bytes(hex), - None => None, +const RUNTIME_METADATA: Option<[u8; 32]> = if let Some(hex) = option_env!("RUNTIME_METADATA_HASH") { + match const_hex::const_decode_to_array(hex.as_bytes()) { + Ok(hex) => Some(hex), + Err(_) => None, + } +} else { + None }; impl MetadataHash { diff --git a/substrate/frame/metadata-hash-extension/src/utils.rs b/substrate/frame/metadata-hash-extension/src/utils.rs deleted file mode 100644 index ecbe133a2391..000000000000 --- a/substrate/frame/metadata-hash-extension/src/utils.rs +++ /dev/null @@ -1,143 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -const HASH_LEN: usize = 32; - -/// Function to convert hex string to Option<[u8; 32]> in a const context. -/// Returns `None` if fails to decode. -pub const fn hex_str_to_32_bytes(hex_str: &str) -> Option<[u8; HASH_LEN]> { - let len = hex_str.len(); - - let start = if len == HASH_LEN * 2 { - 0 - } else if len == HASH_LEN * 2 + 2 && - hex_str.as_bytes()[0] == b'0' && - hex_str.as_bytes()[1] == b'x' - { - 2 - } else { - return None; - }; - - let mut bytes = [0u8; HASH_LEN]; - let mut i = 0; - - while i < HASH_LEN { - let high = from_hex_digit(hex_str.as_bytes()[start + i * 2]); - let low = from_hex_digit(hex_str.as_bytes()[start + i * 2 + 1]); - - let (Some(high), Some(low)) = (high, low) else { return None }; - - bytes[i] = (high << 4) | low; - i += 1; - } - - Some(bytes) -} - -// Helper function to convert a single hex character to a byte -const fn from_hex_digit(digit: u8) -> Option { - match digit { - b'0'..=b'9' => Some(digit - b'0'), - b'a'..=b'f' => Some(digit - b'a' + 10), - b'A'..=b'F' => Some(digit - b'A' + 10), - _ => None, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_from_hex_digit() { - assert_eq!(from_hex_digit(b'0').unwrap(), 0); - assert_eq!(from_hex_digit(b'1').unwrap(), 1); - assert_eq!(from_hex_digit(b'2').unwrap(), 2); - assert_eq!(from_hex_digit(b'3').unwrap(), 3); - assert_eq!(from_hex_digit(b'4').unwrap(), 4); - assert_eq!(from_hex_digit(b'5').unwrap(), 5); - assert_eq!(from_hex_digit(b'6').unwrap(), 6); - assert_eq!(from_hex_digit(b'7').unwrap(), 7); - assert_eq!(from_hex_digit(b'8').unwrap(), 8); - assert_eq!(from_hex_digit(b'9').unwrap(), 9); - assert_eq!(from_hex_digit(b'a').unwrap(), 10); - assert_eq!(from_hex_digit(b'b').unwrap(), 11); - assert_eq!(from_hex_digit(b'c').unwrap(), 12); - assert_eq!(from_hex_digit(b'd').unwrap(), 13); - assert_eq!(from_hex_digit(b'e').unwrap(), 14); - assert_eq!(from_hex_digit(b'f').unwrap(), 15); - assert_eq!(from_hex_digit(b'A').unwrap(), 10); - assert_eq!(from_hex_digit(b'B').unwrap(), 11); - assert_eq!(from_hex_digit(b'C').unwrap(), 12); - assert_eq!(from_hex_digit(b'D').unwrap(), 13); - assert_eq!(from_hex_digit(b'E').unwrap(), 14); - assert_eq!(from_hex_digit(b'F').unwrap(), 15); - - assert_eq!(from_hex_digit(b'g'), None); - } - - #[test] - fn test_hex_str_to_32_bytes() { - assert_eq!( - hex_str_to_32_bytes( - "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - ) - .unwrap(), - [ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, - 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, - 0x90, 0xab, 0xcd, 0xef, - ] - ); - assert_eq!( - hex_str_to_32_bytes( - "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - ) - .unwrap(), - [ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, - 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, - 0x90, 0xab, 0xcd, 0xef, - ] - ); - assert_eq!( - hex_str_to_32_bytes( - "0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF", - ) - .unwrap(), - [ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, - 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, - 0x90, 0xab, 0xcd, 0xef, - ] - ); - assert_eq!( - hex_str_to_32_bytes( - "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF", - ) - .unwrap(), - [ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, - 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, - 0x90, 0xab, 0xcd, 0xef, - ] - ); - - assert_eq!(hex_str_to_32_bytes("0x1234"), None); - } -}