diff --git a/prdoc/pr_10635.prdoc b/prdoc/pr_10635.prdoc new file mode 100644 index 0000000000000..4bd527985a816 --- /dev/null +++ b/prdoc/pr_10635.prdoc @@ -0,0 +1,11 @@ +title: '[pallet-revive] remove unstable host function sr25519_verify' +doc: +- audience: Runtime Dev + description: fixes part of https://github.com/paritytech/polkadot-sdk/issues/8572 +crates: +- name: pallet-revive-fixtures + bump: patch +- name: pallet-revive + bump: patch +- name: pallet-revive-uapi + bump: patch diff --git a/substrate/frame/revive/fixtures/contracts/sr25519_verify.rs b/substrate/frame/revive/fixtures/contracts/sr25519_verify.rs deleted file mode 100644 index 8ef39848c53fe..0000000000000 --- a/substrate/frame/revive/fixtures/contracts/sr25519_verify.rs +++ /dev/null @@ -1,48 +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. - -#![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() {} - -#[no_mangle] -#[polkavm_derive::polkavm_export] -pub extern "C" fn call() { - input!( - signature: [u8; 64], - pub_key: [u8; 32], - msg: [u8; 11], - ); - - let exit_status = match api::sr25519_verify( - &signature.try_into().unwrap(), - msg, - &pub_key.try_into().unwrap(), - ) { - Ok(_) => 0u32, - Err(code) => code as u32, - }; - - // Exit with success and take transfer return code to the output buffer. - api::return_value(uapi::ReturnFlags::empty(), &exit_status.to_le_bytes()); -} diff --git a/substrate/frame/revive/src/precompiles/builtin/system.rs b/substrate/frame/revive/src/precompiles/builtin/system.rs index e465fcbfadf12..7a3e92d72a8b6 100644 --- a/substrate/frame/revive/src/precompiles/builtin/system.rs +++ b/substrate/frame/revive/src/precompiles/builtin/system.rs @@ -100,6 +100,14 @@ impl BuiltinPrecompile for System { env.terminate_caller(&h160).map_err(Error::try_to_revert::)?; Ok(Vec::new()) }, + ISystemCalls::sr25519Verify(ISystem::sr25519VerifyCall { + signature, + message, + publicKey, + }) => { + let ok = env.sr25519_verify(signature, message, publicKey); + Ok(ok.abi_encode()) + }, } } } @@ -190,4 +198,44 @@ mod tests { ); }) } + #[test] + fn sr25519_verify() { + use crate::{precompiles::alloy::sol_types::sol_data::Bool, test_utils::ALICE}; + ExtBuilder::default().build().execute_with(|| { + let _ = ::Currency::set_balance(&ALICE, 100_000_000_000); + + let mut call_setup = CallSetup::::default(); + let (mut ext, _) = call_setup.ext(); + + let mut call_with = |message: &[u8; 11]| { + // Alice's signature for "hello world" + #[rustfmt::skip] + let signature: [u8; 64] = [ + 184, 49, 74, 238, 78, 165, 102, 252, 22, 92, 156, 176, 124, 118, 168, 116, 247, + 99, 0, 94, 2, 45, 9, 170, 73, 222, 182, 74, 60, 32, 75, 64, 98, 174, 69, 55, 83, + 85, 180, 98, 208, 75, 231, 57, 205, 62, 4, 105, 26, 136, 172, 17, 123, 99, 90, 255, + 228, 54, 115, 63, 30, 207, 205, 131, + ]; + + // Alice's public key + #[rustfmt::skip] + let public_key: [u8; 32] = [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, + 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, + ]; + + let input = ISystem::ISystemCalls::sr25519Verify(ISystem::sr25519VerifyCall { + signature, + message: (*message).into(), + publicKey: public_key.into(), + }); + >::call(&>::MATCHER.base_address(), &input, &mut ext) + .unwrap() + }; + let result = Bool::abi_decode(&call_with(&b"hello world")).expect("decoding failed"); + assert!(result); + let result = Bool::abi_decode(&call_with(&b"hello worlD")).expect("decoding failed"); + assert!(!result); + }); + } } diff --git a/substrate/frame/revive/src/tests/pvm.rs b/substrate/frame/revive/src/tests/pvm.rs index d3a1545a46330..14c1367a9e9ba 100644 --- a/substrate/frame/revive/src/tests/pvm.rs +++ b/substrate/frame/revive/src/tests/pvm.rs @@ -1916,51 +1916,6 @@ fn call_runtime_reentrancy_guarded() { }); } -#[test] -fn sr25519_verify() { - let (binary, _code_hash) = compile_module("sr25519_verify").unwrap(); - - ExtBuilder::default().existential_deposit(50).build().execute_with(|| { - let _ = ::Currency::set_balance(&ALICE, 1_000_000); - - // Instantiate the sr25519_verify contract. - let Contract { addr, .. } = builder::bare_instantiate(Code::Upload(binary)) - .native_value(100_000) - .build_and_unwrap_contract(); - - let call_with = |message: &[u8; 11]| { - // Alice's signature for "hello world" - #[rustfmt::skip] - let signature: [u8; 64] = [ - 184, 49, 74, 238, 78, 165, 102, 252, 22, 92, 156, 176, 124, 118, 168, 116, 247, - 99, 0, 94, 2, 45, 9, 170, 73, 222, 182, 74, 60, 32, 75, 64, 98, 174, 69, 55, 83, - 85, 180, 98, 208, 75, 231, 57, 205, 62, 4, 105, 26, 136, 172, 17, 123, 99, 90, 255, - 228, 54, 115, 63, 30, 207, 205, 131, - ]; - - // Alice's public key - #[rustfmt::skip] - let public_key: [u8; 32] = [ - 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, - 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, - ]; - - let mut params = vec![]; - params.extend_from_slice(&signature); - params.extend_from_slice(&public_key); - params.extend_from_slice(message); - - builder::bare_call(addr).data(params).build_and_unwrap_result() - }; - - // verification should succeed for "hello world" - assert_return_code!(call_with(&b"hello world"), RuntimeReturnCode::Success); - - // verification should fail for other messages - assert_return_code!(call_with(&b"hello worlD"), RuntimeReturnCode::Sr25519VerifyFailed); - }); -} - #[test] fn upload_code_works() { let (binary, code_hash) = compile_module("dummy").unwrap(); diff --git a/substrate/frame/revive/src/tests/sol/system.rs b/substrate/frame/revive/src/tests/sol/system.rs index 5f7a2e4c67872..56aaf8a254427 100644 --- a/substrate/frame/revive/src/tests/sol/system.rs +++ b/substrate/frame/revive/src/tests/sol/system.rs @@ -23,6 +23,7 @@ use crate::{ tests::{builder, Contracts, ExtBuilder, Test}, Code, Config, ExecConfig, TransactionLimits, TransactionMeter, U256, }; + use alloy_core::sol_types::{Revert, SolCall, SolConstructor, SolError}; use frame_support::traits::fungible::{Balanced, Mutate}; use pallet_revive_fixtures::{ diff --git a/substrate/frame/revive/uapi/sol/ISystem.sol b/substrate/frame/revive/uapi/sol/ISystem.sol index be79f98129858..e82e56292c6a0 100644 --- a/substrate/frame/revive/uapi/sol/ISystem.sol +++ b/substrate/frame/revive/uapi/sol/ISystem.sol @@ -51,4 +51,12 @@ interface ISystem { /// - called from delegate context /// - the contract introduced balance locks function terminate(address beneficiary) external; + + /// Verify a sr25519 signature + /// + /// # Parameters + /// + /// - `signature`: The signature bytes. + /// - `message`: The message bytes. + function sr25519Verify(uint8[64] calldata signature, bytes calldata message, bytes32 publicKey) external view returns (bool); } diff --git a/substrate/frame/revive/uapi/src/host.rs b/substrate/frame/revive/uapi/src/host.rs index b2d3c65e8c86c..4bd89486be72d 100644 --- a/substrate/frame/revive/uapi/src/host.rs +++ b/substrate/frame/revive/uapi/src/host.rs @@ -491,19 +491,6 @@ pub trait HostFn: private::Sealed { /// - [EcdsaRecoveryFailed][`crate::ReturnErrorCode::EcdsaRecoveryFailed] #[unstable_hostfn] fn ecdsa_to_eth_address(pubkey: &[u8; 33], output: &mut [u8; 20]) -> Result; - - /// Verify a sr25519 signature - /// - /// # Parameters - /// - /// - `signature`: The signature bytes. - /// - `message`: The message bytes. - /// - /// # Errors - /// - /// - [Sr25519VerifyFailed][`crate::ReturnErrorCode::Sr25519VerifyFailed] - #[unstable_hostfn] - fn sr25519_verify(signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> Result; } mod private { diff --git a/substrate/frame/revive/uapi/src/host/riscv64.rs b/substrate/frame/revive/uapi/src/host/riscv64.rs index 3eb8bf33656cb..53ac4412c3701 100644 --- a/substrate/frame/revive/uapi/src/host/riscv64.rs +++ b/substrate/frame/revive/uapi/src/host/riscv64.rs @@ -126,12 +126,6 @@ mod sys { pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8); pub fn block_author(out_ptr: *mut u8); pub fn hash_keccak_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); - pub fn sr25519_verify( - signature_ptr: *const u8, - pub_key_ptr: *const u8, - message_len: u32, - message_ptr: *const u8, - ) -> ReturnCode; pub fn ecdsa_to_eth_address(key_ptr: *const u8, out_ptr: *mut u8) -> ReturnCode; pub fn instantiation_nonce() -> u64; pub fn return_data_size() -> u64; @@ -517,17 +511,4 @@ impl HostFn for HostFnImpl { let ret_code = unsafe { sys::ecdsa_to_eth_address(pubkey.as_ptr(), output.as_mut_ptr()) }; ret_code.into() } - - #[unstable_hostfn] - fn sr25519_verify(signature: &[u8; 64], message: &[u8], pub_key: &[u8; 32]) -> Result { - let ret_code = unsafe { - sys::sr25519_verify( - signature.as_ptr(), - pub_key.as_ptr(), - message.len() as u32, - message.as_ptr(), - ) - }; - ret_code.into() - } }