Skip to content
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
12 changes: 12 additions & 0 deletions prdoc/pr_9454.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
title: '[pallet-revive] Migrate `blake2_128` from host function to pre-compile'
doc:
- audience: Runtime Dev
description: Moves the unstable host function `hash_blake2_128` to the
`System` pre-compile.
crates:
- name: pallet-revive
bump: minor
- name: pallet-revive-fixtures
bump: major
- name: pallet-revive-uapi
bump: major
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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.

#![no_std]
#![no_main]
include!("../panic_handler.rs");

use uapi::{input, HostFn, HostFnImpl as api};

#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn deploy() {}

/// Called by the tests.
///
/// The input bytes encode the data that is directly fed into the Keccak-256 bit
/// crypto hash function. The result is put into the output buffer.
///
/// After contract execution the test driver then asserts that the returned
/// values are equal to the expected bytes for the input and hash function.

#[no_mangle]
#[polkavm_derive::polkavm_export]
pub extern "C" fn call() {
input!(
256,
input: [u8],
);

let mut output = [0u8; 32];
api::hash_keccak_256(input, &mut output);
api::return_value(uapi::ReturnFlags::empty(), &output);
}
72 changes: 0 additions & 72 deletions substrate/frame/revive/fixtures/contracts/crypto_hashes.rs

This file was deleted.

20 changes: 15 additions & 5 deletions substrate/frame/revive/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,16 +2000,26 @@ mod benchmarks {

// `n`: Input to hash in bytes
#[benchmark(pov_mode = Measured)]
fn seal_hash_blake2_128(n: Linear<0, { limits::code::BLOB_BYTES }>) {
build_runtime!(runtime, memory: [[0u8; 16], vec![0u8; n as usize], ]);
fn hash_blake2_128(n: Linear<0, { limits::code::BLOB_BYTES }>) {
let input = vec![0u8; n as usize];
let input_bytes = ISystem::ISystemCalls::hashBlake128(ISystem::hashBlake128Call {
input: input.clone().into(),
})
.abi_encode();

let mut call_setup = CallSetup::<T>::default();
let (mut ext, _) = call_setup.ext();

let result;
#[block]
{
result = runtime.bench_hash_blake2_128(memory.as_mut_slice(), 16, n, 0);
result = run_builtin_precompile(
&mut ext,
H160(BenchmarkSystem::<T>::MATCHER.base_address()).as_fixed_bytes(),
input_bytes,
);
}
assert_eq!(sp_io::hashing::blake2_128(&memory[16..]), &memory[0..16]);
assert_ok!(result);
assert_eq!(sp_io::hashing::blake2_128(&input).to_vec(), result.unwrap().data);
}

// `n`: Message input length to verify in bytes.
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/revive/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl<T: Into<DispatchError>> From<T> for ExecError {
}
}

/// The type of origins supported by the contracts pallet.
/// The type of origins supported by the revive pallet.
#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
pub enum Origin<T: Config> {
Root,
Expand Down
4 changes: 2 additions & 2 deletions substrate/frame/revive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ pub mod pallet {
ReturnDataTooLarge = 0x31,
}

/// A reason for the pallet contracts placing a hold on funds.
/// A reason for the pallet revive placing a hold on funds.
#[pallet::composite_enum]
pub enum HoldReason {
/// The Pallet has reserved it for storing code on-chain.
Expand Down Expand Up @@ -1585,7 +1585,7 @@ impl<T: Config> Pallet<T> {
<T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
}

/// Deposit a pallet contracts event.
/// Deposit a pallet revive event.
fn deposit_event(event: Event<T>) {
<frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
}
Expand Down
8 changes: 8 additions & 0 deletions substrate/frame/revive/src/precompiles/builtin/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ sol! {
interface ISystem {
/// Computes the BLAKE2 256-bit hash on the given input.
function hashBlake256(bytes memory input) external pure returns (bytes32 digest);
/// Computes the BLAKE2 128-bit hash on the given input.
function hashBlake128(bytes memory input) external pure returns (bytes32 digest);
/// Retrieve the account id for a specified `H160` address.
///
/// Calling this function on a native `H160` chain (`type AccountId = H160`)
Expand Down Expand Up @@ -63,6 +65,11 @@ impl<T: Config> BuiltinPrecompile for System<T> {
let output = sp_io::hashing::blake2_256(input.as_bytes_ref());
Ok(output.to_vec())
},
ISystemCalls::hashBlake128(ISystem::hashBlake128Call { input }) => {
env.gas_meter_mut().charge(RuntimeCosts::HashBlake128(input.len() as u32))?;
let output = sp_io::hashing::blake2_128(input.as_bytes_ref());
Ok(output.to_vec())
},
ISystemCalls::toAccountId(ISystem::toAccountIdCall { input }) => {
use crate::address::AddressMapper;
use codec::Encode;
Expand Down Expand Up @@ -92,6 +99,7 @@ mod tests {
#[test]
fn test_system_precompile() {
run_test_vectors::<System<Test>>(include_str!("testdata/900-blake2_256.json"));
run_test_vectors::<System<Test>>(include_str!("testdata/900-blake2_128.json"));
run_test_vectors::<System<Test>>(include_str!("testdata/900-to_account_id.json"));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"Input": "c7dff68600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
"Expected": "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314",
"Name": "vector 1",
"Gas": 8000000,
"NoBenchmark": false
}
]
28 changes: 12 additions & 16 deletions substrate/frame/revive/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1518,13 +1518,13 @@ fn cannot_self_destruct_in_constructor() {
}

#[test]
fn crypto_hashes() {
let (binary, _code_hash) = compile_module("crypto_hashes").unwrap();
fn crypto_hash_keccak_256() {
let (binary, _code_hash) = compile_module("crypto_hash_keccak_256").unwrap();

ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000);

// Instantiate the CRYPTO_HASHES contract.
// Instantiate the CRYPTO_HASH_KECCAK_256 contract.
let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary))
.native_value(100_000)
.build_and_unwrap_contract();
Expand All @@ -1537,18 +1537,14 @@ fn crypto_hashes() {
Box::new(|input| $name(input).as_ref().to_vec().into_boxed_slice())
};
}
// All hash functions and their associated output byte lengths.
let test_cases: &[(u8, Box<dyn Fn(&[u8]) -> Box<[u8]>>, usize)] =
&[(2, dyn_hash_fn!(keccak_256), 32), (4, dyn_hash_fn!(blake2_128), 16)];
// Test the given hash functions for the input: "_DEAD_BEEF"
for (n, hash_fn, expected_size) in test_cases.iter() {
let mut params = vec![*n];
params.extend_from_slice(input);
let result = builder::bare_call(addr).data(params).build_and_unwrap_result();
assert!(!result.did_revert());
let expected = hash_fn(input.as_ref());
assert_eq!(&result.data[..*expected_size], &*expected);
}
// The hash function and its associated output byte lengths.
let hash_fn: Box<dyn Fn(&[u8]) -> Box<[u8]>> = dyn_hash_fn!(keccak_256);
let expected_size: usize = 32;
// Test the hash function for the input: "_DEAD_BEEF"
let result = builder::bare_call(addr).data(input.to_vec()).build_and_unwrap_result();
assert!(!result.did_revert());
let expected = hash_fn(input.as_ref());
assert_eq!(&result.data[..expected_size], &*expected);
})
}

Expand Down Expand Up @@ -2719,7 +2715,7 @@ fn storage_deposit_callee_works() {
#[test]
fn set_code_extrinsic() {
let (binary, code_hash) = compile_module("dummy").unwrap();
let (new_binary, new_code_hash) = compile_module("crypto_hashes").unwrap();
let (new_binary, new_code_hash) = compile_module("crypto_hash_keccak_256").unwrap();

assert_ne!(code_hash, new_code_hash);

Expand Down
23 changes: 4 additions & 19 deletions substrate/frame/revive/src/vm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use frame_support::{ensure, traits::Get, weights::Weight};
use pallet_revive_proc_macro::define_env;
use pallet_revive_uapi::{CallFlags, ReturnErrorCode, ReturnFlags, StorageFlags};
use sp_core::{H160, H256, U256};
use sp_io::hashing::{blake2_128, keccak_256};
use sp_io::hashing::keccak_256;
use sp_runtime::{DispatchError, RuntimeDebug};

/// Abstraction over the memory access within syscalls.
Expand Down Expand Up @@ -366,10 +366,10 @@ pub enum RuntimeCosts {
HashSha256(u32),
/// Weight of calling `seal_hash_keccak_256` for the given input size.
HashKeccak256(u32),
/// Weight of calling the `System::hash_blake2_256` precompile function for the given input
/// Weight of calling the `System::hashBlake256` precompile function for the given input
/// size.
HashBlake256(u32),
/// Weight of calling `seal_hash_blake2_128` for the given input size.
/// Weight of calling `System::hashBlake128` precompile function for the given input size.
HashBlake128(u32),
/// Weight of calling `ECERecover` precompile.
EcdsaRecovery,
Expand Down Expand Up @@ -523,7 +523,7 @@ impl<T: Config> Token<T> for RuntimeCosts {
Ripemd160(len) => T::WeightInfo::ripemd_160(len),
HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len),
HashBlake256(len) => T::WeightInfo::hash_blake2_256(len),
HashBlake128(len) => T::WeightInfo::seal_hash_blake2_128(len),
HashBlake128(len) => T::WeightInfo::hash_blake2_128(len),
EcdsaRecovery => T::WeightInfo::ecdsa_recover(),
Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len),
Precompile(weight) => weight,
Expand Down Expand Up @@ -1997,21 +1997,6 @@ pub mod env {
}
}

/// Computes the BLAKE2 128-bit hash on the given input buffer.
/// See [`pallet_revive_uapi::HostFn::hash_blake2_128`].
fn hash_blake2_128(
&mut self,
memory: &mut M,
input_ptr: u32,
input_len: u32,
output_ptr: u32,
) -> Result<(), TrapReason> {
self.charge_gas(RuntimeCosts::HashBlake128(input_len))?;
Ok(self.compute_hash_on_intermediate_buffer(
memory, blake2_128, input_ptr, input_len, output_ptr,
)?)
}

/// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer.
/// See [`pallet_revive_uapi::HostFn::minimum_balance`].
fn minimum_balance(&mut self, memory: &mut M, out_ptr: u32) -> Result<(), TrapReason> {
Expand Down
12 changes: 6 additions & 6 deletions substrate/frame/revive/src/weights.rs

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

13 changes: 0 additions & 13 deletions substrate/frame/revive/uapi/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,19 +526,6 @@ pub trait HostFn: private::Sealed {
#[unstable_hostfn]
fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result;

/// Computes the blake2_128 16-bit hash on the given input buffer.
///
/// - The `input` and `output` buffer may overlap.
/// - The output buffer is expected to hold at least 16 bits.
/// - It is the callers responsibility to provide an output buffer that is large enough to hold
/// the expected amount of bytes returned by the hash function.
/// # Parameters
///
/// - `input`: The input data buffer.
/// - `output`: The output buffer to write the hash result to.
#[unstable_hostfn]
fn hash_blake2_128(input: &[u8], output: &mut [u8; 16]);

/// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer.
///
/// # Parameters
Expand Down
Loading
Loading