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
7 changes: 7 additions & 0 deletions prdoc/pr_10267.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
title: 'pallet-revive: add secp256r1 (0x100) precompile'
doc:
- audience: Runtime Dev
description: Add secp256r1 precompile (0x100)
crates:
- name: pallet-revive
bump: patch
22 changes: 22 additions & 0 deletions substrate/frame/revive/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,28 @@ mod benchmarks {
assert_eq!(result.unwrap().data, expected);
}

#[benchmark(pov_mode = Measured)]
fn p256_verify() {
use hex_literal::hex;
let input = hex!("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e").to_vec();
Comment thread
xermicus marked this conversation as resolved.
let expected = U256::one().to_big_endian();
let mut call_setup = CallSetup::<T>::default();
let (mut ext, _) = call_setup.ext();

let result;

#[block]
{
result = run_builtin_precompile(
&mut ext,
H160::from_low_u64_be(100).as_fixed_bytes(),
input,
);
}

assert_eq!(result.unwrap().data, expected);
}

#[benchmark(pov_mode = Measured)]
fn bn128_add() {
use hex_literal::hex;
Expand Down
5 changes: 4 additions & 1 deletion substrate/frame/revive/src/precompiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,10 @@ pub mod run {
E: ExtWithInfo,
{
let precompile = <Builtin<E::T>>::get(address)
.ok_or(DispatchError::from("No pre-compile at address"))?;
.ok_or(DispatchError::from("No pre-compile at address"))
.inspect_err(|_| {
log::debug!(target: crate::LOG_TARGET, "No pre-compile at address {address:?}");
})?;
precompile.call(input, ext)
}
}
2 changes: 2 additions & 0 deletions substrate/frame/revive/src/precompiles/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod bn128;
mod ecrecover;
mod identity;
mod modexp;
mod p256_verify;
mod point_eval;
mod ripemd160;
mod sha256;
Expand Down Expand Up @@ -59,6 +60,7 @@ type Production<T> = (
bn128::Bn128Pairing<T>,
blake2f::Blake2F<T>,
point_eval::PointEval<T>,
p256_verify::P256Verify<T>,
system::System<T>,
storage::Storage<T>,
);
Expand Down
73 changes: 73 additions & 0 deletions substrate/frame/revive/src/precompiles/builtin/p256_verify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// 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.

//! # RIP-7212 secp256r1 Precompile
//!
//! This module implements the [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md) precompile for
//! secp256r1 curve support.
//!
//! The main purpose of this precompile is to verify ECDSA signatures that use the secp256r1, or
//! P256 elliptic curve.

use crate::{
precompiles::{BuiltinAddressMatcher, Error, Ext, PrimitivePrecompile},
vm::RuntimeCosts,
Config, U256,
};
use alloc::vec::Vec;
use core::{marker::PhantomData, num::NonZero};

pub struct P256Verify<T>(PhantomData<T>);

impl<T: Config> PrimitivePrecompile for P256Verify<T> {
type T = T;
const MATCHER: BuiltinAddressMatcher = BuiltinAddressMatcher::Fixed(NonZero::new(100).unwrap());
const HAS_CONTRACT_INFO: bool = false;

/// [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md#specification) secp256r1 precompile.
///
/// The input is encoded as follows:
///
/// | signed message hash | r | s | public key x | public key y |
/// | :-----------------: | :-: | :-: | :----------: | :----------: |
/// | 32 | 32 | 32 | 32 | 32 |
fn call(
_address: &[u8; 20],
input: Vec<u8>,
env: &mut impl Ext<T = Self::T>,
) -> Result<Vec<u8>, Error> {
env.gas_meter_mut().charge(RuntimeCosts::P256Verify)?;

if revm::precompile::secp256r1::verify_impl(&input).is_some() {
Ok(U256::one().to_big_endian().to_vec())
} else {
Ok(Default::default())
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{precompiles::tests::run_test_vectors, tests::Test};

#[test]
fn test_p256_verify() {
// https://github.com/ethereum/go-ethereum/blob/master/core/vm/testdata/precompiles/p256Verify.json
run_test_vectors::<P256Verify<Test>>(include_str!("./testdata/256-p256_verify.json"));
}
}
5,476 changes: 5,476 additions & 0 deletions substrate/frame/revive/src/precompiles/builtin/testdata/256-p256_verify.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions substrate/frame/revive/src/vm/runtime_costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ pub enum RuntimeCosts {
HashBlake128(u32),
/// Weight of calling `ECERecover` precompile.
EcdsaRecovery,
/// Weight of calling `P256Verify` precompile.
P256Verify,
/// Weight of calling `seal_sr25519_verify` for the given input size.
Sr25519Verify(u32),
/// Weight charged by a precompile.
Expand Down Expand Up @@ -316,6 +318,7 @@ impl<T: Config> Token<T> for RuntimeCosts {
HashBlake256(len) => T::WeightInfo::hash_blake2_256(len),
HashBlake128(len) => T::WeightInfo::hash_blake2_128(len),
EcdsaRecovery => T::WeightInfo::ecdsa_recover(),
P256Verify => T::WeightInfo::p256_verify(),
Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len),
Precompile(weight) => weight,
SetCodeHash { old_code_removed } =>
Expand Down
Loading
Loading