Skip to content
Open
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
15 changes: 11 additions & 4 deletions basic_bootloader/src/bootloader/transaction/authorization_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use zk_ee::system::Ergs;
use zk_ee::system::IOSubsystem;
use zk_ee::system::NonceError;
use zk_ee::system::Resource;
use zk_ee::system::SystemFunctionsExt;
use zk_ee::system::{AccountDataRequest, EthereumLikeTypes, IOSubsystemExt, Resources, System};
use zk_ee::system_log;
use zk_ee::{internal_error, wrap_error};
Expand Down Expand Up @@ -235,8 +236,10 @@ fn recover_authority<S: EthereumLikeTypes>(
resources: &mut S::Resources,
auth_sig_data: (u8, &[u8], &[u8]),
msg: &[u8; 32],
) -> Result<Option<B160>, TxError> {
use zk_ee::system::SystemFunctions;
) -> Result<Option<B160>, TxError>
where
S::IO: IOSubsystemExt,
{
let mut ecrecover_input = [0u8; 128];
let (parity, r, s) = auth_sig_data;
if parity > 1 {
Expand All @@ -247,14 +250,18 @@ fn recover_authority<S: EthereumLikeTypes>(
ecrecover_input[64..96][(32 - r.len())..].copy_from_slice(r);
ecrecover_input[96..128][(32 - s.len())..].copy_from_slice(s);
let mut ecrecover_output = ArrayBuilder::default();
let mut logger = system.get_logger();
let allocator = system.get_allocator();
// Recover is counted in intrinsic gas
resources
.with_infinite_ergs(|inf_ergs| {
S::SystemFunctions::secp256k1_ec_recover(
S::SystemFunctionsExt::secp256k1_ec_recover(
ecrecover_input.as_slice(),
&mut ecrecover_output,
inf_ergs,
system.get_allocator(),
system.io.oracle(),
&mut logger,
allocator,
)
})
.map_err(SystemError::from)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,18 @@ where

let mut ecrecover_output = ArrayBuilder::default();
// We already charged gas for ecrecover in intrinsic cost, so we only need to charge native resources here.
let mut logger = system.get_logger();
let allocator = system.get_allocator();
tx_resources
.main_resources
.with_infinite_ergs(|resources| {
S::SystemFunctions::secp256k1_ec_recover(
S::SystemFunctionsExt::secp256k1_ec_recover(
ecrecover_input.as_slice(),
&mut ecrecover_output,
resources,
system.get_allocator(),
system.io.oracle(),
&mut logger,
allocator,
)
.map_err(SystemError::from)
})?;
Expand Down
1 change: 1 addition & 0 deletions basic_bootloader/src/bootloader/transaction_flow/zk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::bootloader::transaction_flow::TxExecutionResult;
use crate::bootloader::transaction_flow::{ExecutionOutput, ExecutionResult};
use crate::bootloader::BasicBootloaderExecutionConfig;
use crate::bootloader::TxProcessingOutput;
use alloc::format;
use core::fmt::Write;
use errors::cascade::CascadedError;
use errors::root_cause::RootCause;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use zk_ee::system::metadata::zk_metadata::TxLevelMetadata;
use zk_ee::system::resources::Computational;
use zk_ee::system::tracer::Tracer;
use zk_ee::system::{errors::system::SystemError, EthereumLikeTypes, System};
use zk_ee::system::{AccountDataRequest, SystemFunctions};
use zk_ee::system::{AccountDataRequest, SystemFunctionsExt};
use zk_ee::system::{Ergs, IOSubsystemExt, Resources};
use zk_ee::system::{IOSubsystem, NonceError};
use zk_ee::system::{Resource, SystemTypes};
Expand Down Expand Up @@ -199,14 +199,18 @@ where

let mut ecrecover_output = ArrayBuilder::default();
// We already charged gas for ecrecover in intrinsic cost, so we only need to charge native resources here.
let mut logger = system.get_logger();
let allocator = system.get_allocator();
tx_resources
.main_resources
.with_infinite_ergs(|resources| {
S::SystemFunctions::secp256k1_ec_recover(
S::SystemFunctionsExt::secp256k1_ec_recover(
ecrecover_input.as_slice(),
&mut ecrecover_output,
resources,
system.get_allocator(),
system.io.oracle(),
&mut logger,
allocator,
)
.map_err(SystemError::from)
})?;
Expand Down
2 changes: 2 additions & 0 deletions basic_system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ state-diffs-pi = []
hex = {version = "0.4.3"}
proptest = "1.6.0"
crypto = { path = "../crypto", default-features = false, features = ["secp256k1-static-context", "testing"]}
callable_oracles = { path = "../callable_oracles" }
oracle_provider = { path = "../oracle_provider" }
num-bigint = "*"
num-traits = "*"
arbitrary = { version = "1", features = ["derive"] }
Expand Down
95 changes: 76 additions & 19 deletions basic_system/src/system_functions/ecrecover.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,53 @@
use super::*;
use crate::cost_constants::{ECRECOVER_COST_ERGS, ECRECOVER_NATIVE_COST};
use crypto::secp256k1::hooks::DefaultSecp256k1Hooks;
use field_ops::Secp256k1HooksWithOracle;
use zk_ee::common_traits::TryExtend;
use zk_ee::oracle::IOOracle;
use zk_ee::out_of_return_memory;
use zk_ee::system::base_system_functions::{Secp256k1ECRecoverErrors, SystemFunction};
use zk_ee::system::base_system_functions::Secp256k1ECRecoverErrors;
use zk_ee::system::errors::{subsystem::SubsystemError, system::SystemError};
use zk_ee::system::Computational;
use zk_ee::system::{Computational, SystemFunctionExt};

///
/// ecrecover system function implementation.
///
pub struct EcRecoverImpl;

impl<R: Resources> SystemFunction<R, Secp256k1ECRecoverErrors> for EcRecoverImpl {
impl<R: Resources> SystemFunctionExt<R, Secp256k1ECRecoverErrors> for EcRecoverImpl {
/// If the input size is less than expected - it will be padded with zeroes.
/// If the input size is greater - redundant bytes will be ignored.
/// If the input is invalid(v != 27|28 or failed to recover signer) returns `Ok(0)`.
///
/// Returns `OutOfGas` if not enough resources provided.
fn execute<D: TryExtend<u8> + ?Sized, A: core::alloc::Allocator + Clone>(
fn execute<O: IOOracle, L, D: TryExtend<u8> + ?Sized, A: core::alloc::Allocator + Clone>(
input: &[u8],
output: &mut D,
resources: &mut R,
oracle: &mut O,
_logger: &mut L,
_allocator: A,
) -> Result<(), SubsystemError<Secp256k1ECRecoverErrors>> {
Ok(cycle_marker::wrap_with_resources!(
"ecrecover",
resources,
{ ecrecover_as_system_function_inner(input, output, resources) }
// TODO: reconsider if we actually want to use the oracle based version here
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Opening thread to think if we want to use the oracle-based version in prod

Copy link
Contributor

Choose a reason for hiding this comment

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

Note: we should not forget about it in v0.4.0 @AntonD3

{ ecrecover_as_system_function_inner(input, output, resources, Some(oracle)) }
)?)
}
}

// if the oracle is provided, it will be used for field operations
fn ecrecover_as_system_function_inner<
O: IOOracle,
S: ?Sized + MinimalByteAddressableSlice,
D: ?Sized + TryExtend<u8>,
R: Resources,
>(
src: &S,
dst: &mut D,
resources: &mut R,
oracle: Option<&mut O>,
) -> Result<(), SystemError> {
resources.charge(&R::from_ergs_and_native(
ECRECOVER_COST_ERGS,
Expand Down Expand Up @@ -68,7 +77,14 @@ fn ecrecover_as_system_function_inner<
return Ok(());
}

let Ok(pk_bytes) = ecrecover_inner(digest, r, s, rec_id) else {
// on forward run we do not support oracle-based hooks
let oracle = if cfg!(target_arch = "riscv32") {
oracle
} else {
None
};

let Ok(pk_bytes) = ecrecover_inner(digest, r, s, rec_id, oracle) else {
return Ok(());
};

Expand All @@ -85,11 +101,12 @@ fn ecrecover_as_system_function_inner<
Ok(())
}

pub fn ecrecover_inner(
pub fn ecrecover_inner<O: IOOracle>(
digest: &[u8; 32],
r: &[u8; 32],
s: &[u8; 32],
rec_id: u8,
oracle: Option<&mut O>,
) -> Result<crypto::k256::EncodedPoint, ()> {
use crypto::k256::{
ecdsa::{hazmat::bits2field, RecoveryId, Signature},
Expand All @@ -104,7 +121,22 @@ pub fn ecrecover_inner(
&bits2field::<crypto::k256::Secp256k1>(digest).map_err(|_| ())?,
);

let Ok(pk) = crypto::secp256k1::recover(&message, &signature, &recovery_id) else {
let res = match oracle {
Some(oracle) => crypto::secp256k1::recover(
&message,
&signature,
&recovery_id,
&mut Secp256k1HooksWithOracle::new(oracle),
),
None => crypto::secp256k1::recover(
&message,
&signature,
&recovery_id,
&mut DefaultSecp256k1Hooks,
),
};

let Ok(pk) = res else {
return Err(());
};

Expand All @@ -117,6 +149,7 @@ pub fn ecrecover_inner(
#[cfg(test)]
mod test {
use super::*;
use crate::system_implementation::flat_storage_model::TestingTree;
use hex;
use zk_ee::reference_implementations::BaseResources;
use zk_ee::reference_implementations::DecreasingNative;
Expand All @@ -140,8 +173,13 @@ mod test {

let mut resources = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;

ecrecover_as_system_function_inner(input.as_slice(), &mut pubkey, &mut resources)
.expect("ecrecover");
ecrecover_as_system_function_inner::<TestingTree<false>, _, _, _>(
input.as_slice(),
&mut pubkey,
&mut resources,
None,
)
.expect("ecrecover");
assert_eq!(pubkey.len(), 32, "Size should be 32");
assert_eq!(
pubkey, expected_pubkey,
Expand All @@ -156,8 +194,13 @@ mod test {

let mut resources = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;

ecrecover_as_system_function_inner(input.as_slice(), &mut pubkey, &mut resources)
.expect("ecrecover");
ecrecover_as_system_function_inner::<TestingTree<false>, _, _, _>(
input.as_slice(),
&mut pubkey,
&mut resources,
None,
)
.expect("ecrecover");
assert_eq!(pubkey.len(), 0, "Size should be 0");
}

Expand All @@ -173,8 +216,13 @@ mod test {

let mut resources = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;

ecrecover_as_system_function_inner(input.as_slice(), &mut pubkey, &mut resources)
.expect("ecrecover");
ecrecover_as_system_function_inner::<TestingTree<false>, _, _, _>(
input.as_slice(),
&mut pubkey,
&mut resources,
None,
)
.expect("ecrecover");
assert_eq!(pubkey.len(), 0, "Size should be 0 in case of error");
}

Expand All @@ -190,8 +238,13 @@ mod test {

let mut resources = <BaseResources<DecreasingNative> as Resource>::FORMAL_INFINITE;

ecrecover_as_system_function_inner(input.as_slice(), &mut pubkey, &mut resources)
.expect("ecrecover");
ecrecover_as_system_function_inner::<TestingTree<false>, _, _, _>(
input.as_slice(),
&mut pubkey,
&mut resources,
None,
)
.expect("ecrecover");
assert_eq!(pubkey.len(), 0, "Size should be 0 in case of error");
}

Expand All @@ -213,9 +266,13 @@ mod test {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 249, 114, 95, 16, 115, 88, 201, 17, 91, 201,
216, 108, 114, 221, 88, 35, 233, 177, 230,
];

ecrecover_as_system_function_inner(input.as_slice(), &mut pubkey, &mut resources)
.expect("ecrecover");
ecrecover_as_system_function_inner::<TestingTree<false>, _, _, _>(
input.as_slice(),
&mut pubkey,
&mut resources,
None,
)
.expect("ecrecover");
assert_eq!(pubkey.len(), 32, "Size should be 32");
assert_eq!(
pubkey, expected_pubkey,
Expand Down
Loading
Loading