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

[After Transaction Extension PR] CheckMetadataHash transaction extension benchmark. #5277

Draft
wants to merge 13 commits into
base: george/restore-gav-tx-ext
Choose a base branch
from
14 changes: 11 additions & 3 deletions substrate/frame/metadata-hash-extension/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extern crate alloc;
extern crate self as frame_metadata_hash_extension;

use codec::{Decode, Encode};
use frame_support::DebugNoBound;
use frame_support::{pallet_prelude::Weight, DebugNoBound};
use frame_system::Config;
use scale_info::TypeInfo;
use sp_runtime::{
Expand All @@ -50,6 +50,7 @@ use sp_runtime::{

#[cfg(test)]
mod tests;
mod utils;

/// The mode of [`CheckMetadataHash`].
#[derive(Decode, Encode, PartialEq, Debug, TypeInfo, Clone, Copy, Eq)]
Expand All @@ -68,12 +69,16 @@ enum MetadataHash {
Custom([u8; 32]),
}

static RUNTIME_METADATA: Option<[u8; 32]> = match option_env!("RUNTIME_METADATA_HASH") {
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
Some(hex) => utils::hex_str_to_32_bytes_panic(hex),
None => None,
};

impl MetadataHash {
/// Returns the metadata hash.
fn hash(&self) -> Option<[u8; 32]> {
match self {
Self::FetchFromEnv =>
option_env!("RUNTIME_METADATA_HASH").map(array_bytes::hex2array_unchecked),
Self::FetchFromEnv => RUNTIME_METADATA,
Self::Custom(hash) => Some(*hash),
}
}
Expand Down Expand Up @@ -152,6 +157,9 @@ impl<T: Config + Send + Sync> TransactionExtensionBase for CheckMetadataHash<T>

Ok(signed)
}
fn weight() -> Weight {
Weight::default()
}
}
impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for CheckMetadataHash<T> {
type Val = ();
Expand Down
138 changes: 138 additions & 0 deletions substrate/frame/metadata-hash-extension/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// 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.

/// 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_panic(hex_str: &str) -> Option<[u8; 32]> {
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
let len = hex_str.len();

let start = if len == 64 {
0
} else if len == 66 && hex_str.as_bytes()[0] == b'0' && hex_str.as_bytes()[1] == b'x' {
2
} else {
return None;
};
gui1117 marked this conversation as resolved.
Show resolved Hide resolved

let mut bytes = [0u8; 32];
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
let mut i = 0;

while i < 32 {
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
let high = from_hex_digit_panic(hex_str.as_bytes()[start + i * 2]);
let low = from_hex_digit_panic(hex_str.as_bytes()[start + i * 2 + 1]);

let (Some(high), Some(low)) = (high, low) else { return None };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let high = from_hex_digit_panic(hex_str.as_bytes()[start + i * 2]);
let low = from_hex_digit_panic(hex_str.as_bytes()[start + i * 2 + 1]);
let (Some(high), Some(low)) = (high, low) else { return None };
let high = from_hex_digit_panic(hex_str.as_bytes()[start + i * 2])?;
let low = from_hex_digit_panic(hex_str.as_bytes()[start + i * 2 + 1])?;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? not allowed in const fn


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_panic(digit: u8) -> Option<u8> {
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_panic() {
assert_eq!(from_hex_digit_panic(b'0').unwrap(), 0);
assert_eq!(from_hex_digit_panic(b'1').unwrap(), 1);
assert_eq!(from_hex_digit_panic(b'2').unwrap(), 2);
assert_eq!(from_hex_digit_panic(b'3').unwrap(), 3);
assert_eq!(from_hex_digit_panic(b'4').unwrap(), 4);
assert_eq!(from_hex_digit_panic(b'5').unwrap(), 5);
assert_eq!(from_hex_digit_panic(b'6').unwrap(), 6);
assert_eq!(from_hex_digit_panic(b'7').unwrap(), 7);
assert_eq!(from_hex_digit_panic(b'8').unwrap(), 8);
assert_eq!(from_hex_digit_panic(b'9').unwrap(), 9);
assert_eq!(from_hex_digit_panic(b'a').unwrap(), 10);
assert_eq!(from_hex_digit_panic(b'b').unwrap(), 11);
assert_eq!(from_hex_digit_panic(b'c').unwrap(), 12);
assert_eq!(from_hex_digit_panic(b'd').unwrap(), 13);
assert_eq!(from_hex_digit_panic(b'e').unwrap(), 14);
assert_eq!(from_hex_digit_panic(b'f').unwrap(), 15);
assert_eq!(from_hex_digit_panic(b'A').unwrap(), 10);
assert_eq!(from_hex_digit_panic(b'B').unwrap(), 11);
assert_eq!(from_hex_digit_panic(b'C').unwrap(), 12);
assert_eq!(from_hex_digit_panic(b'D').unwrap(), 13);
assert_eq!(from_hex_digit_panic(b'E').unwrap(), 14);
assert_eq!(from_hex_digit_panic(b'F').unwrap(), 15);

assert_eq!(from_hex_digit_panic(b'g'), None);
}

#[test]
fn test_hex_str_to_32_bytes_panic() {
assert_eq!(
hex_str_to_32_bytes_panic(
"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_panic(
"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_panic(
"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_panic(
"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_panic("0x1234"), None);
}
}
Loading