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();