diff --git a/engine-precompiles/src/secp256k1.rs b/engine-precompiles/src/secp256k1.rs
index fa00a58d6..14b01868b 100644
--- a/engine-precompiles/src/secp256k1.rs
+++ b/engine-precompiles/src/secp256k1.rs
@@ -53,7 +53,7 @@ fn internal_impl(hash: H256, signature: &[u8]) -> Result
{
Err(ExitError::Other(Borrowed(sdk::ECRecoverErr.as_str())))
}
-pub(super) struct ECRecover;
+pub struct ECRecover;
impl ECRecover {
pub(super) const ADDRESS: Address = super::make_address(0, 1);
@@ -194,11 +194,58 @@ mod tests {
.output;
assert_eq!(res, expected);
- // Why is this test returning an address???
- // let input = hex::decode("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap();
- // let expected: Vec = Vec::new();
- //
- // let res = ecrecover_raw(&input, Some(500)).unwrap().output;
- // assert_eq!(res, expected);
+ let input = hex::decode("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap();
+ let expected: Vec = Vec::new();
+
+ let res = ECRecover
+ .run(&input, Some(EthGas::new(3_000)), &new_context(), false)
+ .unwrap()
+ .output;
+ assert_eq!(res, expected);
+ }
+
+ #[test]
+ fn test_ecrecover_geth_tests() {
+ let input = hex::decode("a8b53bdf3306a35a7103ab5504a0c9b492295564b6202b1942a84ef300107281000000000000000000000000000000000000000000000000000000000000001b307835653165303366353363653138623737326363623030393366663731663366353366356337356237346463623331613835616138623838393262346538621122334455667788991011121314151617181920212223242526272829303132").unwrap();
+ let expected: Vec = Vec::new();
+ let res = ECRecover
+ .run(&input, Some(EthGas::new(3_000)), &new_context(), false)
+ .unwrap()
+ .output;
+ assert_eq!(res, expected);
+
+ let input = hex::decode("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549").unwrap();
+ let expected =
+ hex::decode("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b")
+ .unwrap();
+ let res = ECRecover
+ .run(&input, Some(EthGas::new(3_000)), &new_context(), false)
+ .unwrap()
+ .output;
+ assert_eq!(res, expected);
+
+ let input = hex::decode("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c100000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549").unwrap();
+ let expected: Vec = Vec::new();
+ let res = ECRecover
+ .run(&input, Some(EthGas::new(3_000)), &new_context(), false)
+ .unwrap()
+ .output;
+ assert_eq!(res, expected);
+
+ let input = hex::decode("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549").unwrap();
+ let expected: Vec = Vec::new();
+ let res = ECRecover
+ .run(&input, Some(EthGas::new(3_000)), &new_context(), false)
+ .unwrap()
+ .output;
+ assert_eq!(res, expected);
+
+ let input = hex::decode("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000011c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549").unwrap();
+ let expected: Vec = Vec::new();
+ let res = ECRecover
+ .run(&input, Some(EthGas::new(3_000)), &new_context(), false)
+ .unwrap()
+ .output;
+ assert_eq!(res, expected);
}
}
diff --git a/engine-sdk/src/lib.rs b/engine-sdk/src/lib.rs
index 4df77bcb1..97beb87e5 100644
--- a/engine-sdk/src/lib.rs
+++ b/engine-sdk/src/lib.rs
@@ -24,7 +24,7 @@ const ECRECOVER_MESSAGE_SIZE: u64 = 32;
#[cfg(feature = "contract")]
const ECRECOVER_SIGNATURE_LENGTH: u64 = 64;
#[cfg(feature = "contract")]
-const ECRECOVER_MALLEABILITY_FLAG: u64 = 1;
+const ECRECOVER_MALLEABILITY_FLAG: u64 = 0;
#[cfg(feature = "contract")]
pub fn panic_utf8(bytes: &[u8]) -> ! {
diff --git a/engine-tests/src/tests/ecrecover.rs b/engine-tests/src/tests/ecrecover.rs
new file mode 100644
index 000000000..bdc4353d3
--- /dev/null
+++ b/engine-tests/src/tests/ecrecover.rs
@@ -0,0 +1,93 @@
+use super::sanity::initialize_transfer;
+use crate::prelude::Wei;
+use crate::prelude::{Address, U256};
+use crate::test_utils::{self, AuroraRunner, Signer};
+use aurora_engine_precompiles::Precompile;
+
+const ECRECOVER_ADDRESS: Address = aurora_engine_precompiles::make_address(0, 1);
+
+/// ecrecover tests taken from geth
+#[test]
+fn test_ecrecover_geth() {
+ let (mut runner, mut signer, _) = initialize_transfer();
+
+ let inputs = [
+ "a8b53bdf3306a35a7103ab5504a0c9b492295564b6202b1942a84ef300107281000000000000000000000000000000000000000000000000000000000000001b307835653165303366353363653138623737326363623030393366663731663366353366356337356237346463623331613835616138623838393262346538621122334455667788991011121314151617181920212223242526272829303132",
+ "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c100000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000001000000000000000000000011c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549",
+ ];
+ let outputs = [
+ Vec::new(),
+ hex::decode("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b").unwrap(),
+ Vec::new(),
+ Vec::new(),
+ Vec::new(),
+ ];
+
+ for (input, output) in inputs.iter().zip(outputs.iter()) {
+ check_wasm_ecrecover(
+ &mut runner,
+ &mut signer,
+ hex::decode(input).unwrap(),
+ output,
+ );
+ }
+}
+
+/// The ecrecover implementation in both the standalone and wasm contract should be the same.
+#[test]
+fn test_ecrecover_standalone() {
+ let (mut runner, mut signer, _) = initialize_transfer();
+
+ let hash =
+ hex::decode("5cc4cee58087de1a2ea481fe9c65c92adc27cff464b7f00a486dc9bf6bb8efb3").unwrap();
+ let sig = hex::decode("32573a0b258f251971a4ec35511c018a7e7bf75a5886534b48d12e47263048a2fe6e03543955255e235388b224704555fd036a954d3ee6dd030d9d1fea1830d71c").unwrap();
+
+ let input = construct_input(&hash, &sig);
+
+ let ctx = evm::Context {
+ address: Default::default(),
+ caller: Default::default(),
+ apparent_value: U256::zero(),
+ };
+ let standalone_result = aurora_engine_precompiles::secp256k1::ECRecover
+ .run(&input, None, &ctx, false)
+ .unwrap();
+
+ check_wasm_ecrecover(&mut runner, &mut signer, input, &standalone_result.output);
+}
+
+fn check_wasm_ecrecover(
+ runner: &mut AuroraRunner,
+ signer: &mut Signer,
+ input: Vec,
+ expected_output: &[u8],
+) {
+ let wasm_result = runner
+ .submit_with_signer(signer, |nonce| {
+ aurora_engine_transactions::legacy::TransactionLegacy {
+ nonce,
+ gas_price: U256::zero(),
+ gas_limit: u64::MAX.into(),
+ to: Some(ECRECOVER_ADDRESS),
+ value: Wei::zero(),
+ data: input,
+ }
+ })
+ .unwrap();
+ assert_eq!(
+ expected_output,
+ test_utils::unwrap_success_slice(&wasm_result),
+ );
+}
+
+fn construct_input(hash: &[u8], sig: &[u8]) -> Vec {
+ let mut buf = [0u8; 128];
+ (&mut buf[0..32]).copy_from_slice(hash);
+ buf[63] = sig[64];
+ (&mut buf[64..128]).copy_from_slice(&sig[0..64]);
+
+ buf.to_vec()
+}
diff --git a/engine-tests/src/tests/mod.rs b/engine-tests/src/tests/mod.rs
index 76e083706..f6b4dd0ed 100644
--- a/engine-tests/src/tests/mod.rs
+++ b/engine-tests/src/tests/mod.rs
@@ -1,6 +1,7 @@
mod access_lists;
mod account_id_precompiles;
mod contract_call;
+mod ecrecover;
mod eip1559;
mod erc20;
mod erc20_connector;
@@ -12,7 +13,7 @@ mod one_inch;
mod prepaid_gas_precompile;
mod random;
mod repro;
-mod sanity;
+pub(crate) mod sanity;
mod self_destruct_state;
mod standalone;
mod standard_precompiles;
diff --git a/engine-tests/src/tests/sanity.rs b/engine-tests/src/tests/sanity.rs
index a8613fbea..62b490ce1 100644
--- a/engine-tests/src/tests/sanity.rs
+++ b/engine-tests/src/tests/sanity.rs
@@ -718,7 +718,7 @@ fn test_eth_transfer_charging_gas_not_enough_balance() {
test_utils::validate_address_balance_and_nonce(&runner, relayer, Wei::zero(), 0.into());
}
-fn initialize_transfer() -> (test_utils::AuroraRunner, test_utils::Signer, Address) {
+pub(crate) fn initialize_transfer() -> (test_utils::AuroraRunner, test_utils::Signer, Address) {
// set up Aurora runner and accounts
let mut runner = test_utils::deploy_evm();
let mut rng = rand::thread_rng();