diff --git a/aptos-move/e2e-move-tests/README.md b/aptos-move/e2e-move-tests/README.md new file mode 100644 index 0000000000000..f025e0ca31a9b --- /dev/null +++ b/aptos-move/e2e-move-tests/README.md @@ -0,0 +1,9 @@ +# e2e-move-tests + +## Keyless + +To run the keyless VM tests: + +``` +cargo test -- keyless +``` diff --git a/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs b/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs index 08d283cd67feb..2524f6fdffa3d 100644 --- a/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs +++ b/aptos-move/e2e-move-tests/src/tests/keyless_feature_gating.rs @@ -16,6 +16,7 @@ use aptos_types::{ }, AnyKeylessPublicKey, Configuration, EphemeralCertificate, FederatedKeylessPublicKey, Groth16VerificationKey, KeylessPublicKey, KeylessSignature, TransactionAndProof, + VERIFICATION_KEY_FOR_TESTING, }, on_chain_config::FeatureFlag, transaction::{ @@ -35,7 +36,7 @@ use move_core_types::{ }, }; -/// Initializes an Aptos VM and sets the keyless configuration via script (the VK is already set in genesis). +/// Initializes an Aptos VM and sets the keyless configuration via script. fn init_feature_gating( enabled_features: Vec, disabled_features: Vec, @@ -46,6 +47,12 @@ fn init_feature_gating( // initialize JWKs let core_resources = run_jwk_and_config_script(&mut h); + // initialize default VK + run_upgrade_vk_script( + &mut h, + core_resources.clone(), + Groth16VerificationKey::from(VERIFICATION_KEY_FOR_TESTING.clone()), + ); (h, recipient, core_resources) } @@ -256,6 +263,14 @@ fn test_federated_keyless_at_jwk_addr() { let jwk_addr = AccountAddress::from_hex_literal("0xadd").unwrap(); + // Step 0: Make sure the default VK is installed + let core_resources = h.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); + run_upgrade_vk_script( + &mut h, + core_resources.clone(), + Groth16VerificationKey::from(VERIFICATION_KEY_FOR_TESTING.clone()), + ); + // Step 1: Make sure TXN validation fails if JWKs are not installed at jwk_addr. let (sig, pk) = get_sample_groth16_sig_and_pk(); let sender = create_federated_keyless_account(&mut h, jwk_addr, pk); @@ -280,7 +295,7 @@ fn test_federated_keyless_at_jwk_addr() { // Step 1: Make sure TXN validation succeeds once JWKs are installed at jwk_addr. let iss = get_sample_iss(); let jwk = get_sample_jwk(); - let _core_resources = install_federated_jwks_and_set_keyless_config(&mut h, jwk_addr, iss, jwk); + let _ = install_federated_jwks_and_set_keyless_config(&mut h, jwk_addr, iss, jwk); let txn = spend_keyless_account(&mut h, sig, &sender, *recipient.address()); let output = h.run_raw(txn); @@ -308,7 +323,14 @@ fn test_federated_keyless_override_at_0x1() { let jwk_addr = AccountAddress::from_hex_literal("0xadd").unwrap(); let iss = get_sample_iss(); let jwk = secure_test_rsa_jwk(); // this will be the wrong JWK - let _core_resources = install_federated_jwks_and_set_keyless_config(&mut h, jwk_addr, iss, jwk); + let core_resources = install_federated_jwks_and_set_keyless_config(&mut h, jwk_addr, iss, jwk); + + // Step 0: Make sure the default VK is installed + run_upgrade_vk_script( + &mut h, + core_resources.clone(), + Groth16VerificationKey::from(VERIFICATION_KEY_FOR_TESTING.clone()), + ); // Step 1: Make sure the TXN does not validate, since the wrong JWK is installed at JWK addr let (sig, pk) = get_sample_groth16_sig_and_pk(); @@ -441,7 +463,7 @@ fn create_and_spend_keyless_account( spend_keyless_account(h, sig, &account, recipient) } -/// Sets the keyless configuration (Note: the VK is already set in genesis.) +/// Sets the keyless configuration fn run_jwk_and_config_script(h: &mut MoveHarness) -> Account { let core_resources = h.new_account_at(AccountAddress::from_hex_literal("0xA550C18").unwrap()); @@ -475,16 +497,14 @@ fn run_jwk_and_config_script(h: &mut MoveHarness) -> Account { .sign(); // NOTE: We cannot write the Configuration and Groth16Verification key via MoveHarness::set_resource - // because it does not (yet) work with resource groups. This is okay, because the VK will be - // there from genesis. + // because it does not (yet) work with resource groups. assert_success!(h.run(txn)); core_resources } -/// Sets the keyless configuration and installs the sample RSA JWK as a federated JWK -/// (Note: the VK is already set in genesis.) +/// Sets the keyless configuration and installs the sample RSA JWK as a federated JWK. fn install_federated_jwks_and_set_keyless_config( h: &mut MoveHarness, jwk_owner: AccountAddress, @@ -524,8 +544,7 @@ fn federated_keyless_init_config(h: &mut MoveHarness, core_resources: Account) { .sign(); // NOTE: We cannot write the Configuration and Groth16Verification key via MoveHarness::set_resource - // because it does not (yet) work with resource groups. This is okay, because the VK will be - // there from genesis. + // because it does not (yet) work with resource groups. assert_success!(h.run(txn)); } @@ -557,8 +576,7 @@ fn federated_keyless_install_jwk( .sign(); // NOTE: We cannot write the Configuration and Groth16Verification key via MoveHarness::set_resource - // because it does not (yet) work with resource groups. This is okay, because the VK will be - // there from genesis. + // because it does not (yet) work with resource groups. assert_success!(h.run(txn)); } diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 239713079c616..ea57e7b377de2 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -27,8 +27,7 @@ use aptos_types::{ secure_test_rsa_jwk, }, keyless::{ - self, test_utils::get_sample_iss, Groth16VerificationKey, DEVNET_VERIFICATION_KEY, - KEYLESS_ACCOUNT_MODULE_NAME, + self, test_utils::get_sample_iss, Groth16VerificationKey, KEYLESS_ACCOUNT_MODULE_NAME, }, move_utils::as_move_value::AsMoveValue, on_chain_config::{ @@ -111,7 +110,7 @@ pub struct GenesisConfiguration { pub randomness_config_override: Option, pub jwk_consensus_config_override: Option, pub initial_jwks: Vec, - pub keyless_groth16_vk_override: Option, + pub keyless_groth16_vk: Option, } pub static GENESIS_KEYPAIR: Lazy<(Ed25519PrivateKey, Ed25519PublicKey)> = Lazy::new(|| { @@ -312,7 +311,7 @@ pub fn encode_genesis_change_set( &module_storage, chain_id, genesis_config.initial_jwks.clone(), - genesis_config.keyless_groth16_vk_override.clone(), + genesis_config.keyless_groth16_vk.clone(), ); set_genesis_end(&mut session, &module_storage); @@ -686,7 +685,7 @@ fn initialize_keyless_accounts( module_storage: &impl AptosModuleStorage, chain_id: ChainId, mut initial_jwks: Vec, - vk_override: Option, + vk: Option, ) { let config = keyless::Configuration::new_for_devnet(); exec_function( @@ -700,9 +699,8 @@ fn initialize_keyless_accounts( config.as_move_value(), ]), ); - if !chain_id.is_mainnet() { - let vk = - vk_override.unwrap_or_else(|| Groth16VerificationKey::from(&*DEVNET_VERIFICATION_KEY)); + + if vk.is_some() { exec_function( session, module_storage, @@ -711,10 +709,11 @@ fn initialize_keyless_accounts( vec![], serialize_values(&vec![ MoveValue::Signer(CORE_CODE_ADDRESS), - vk.as_move_value(), + vk.unwrap().as_move_value(), ]), ); - + } + if !chain_id.is_mainnet() { let additional_jwk_patch = IssuerJWK { issuer: get_sample_iss(), jwk: JWK::RSA(secure_test_rsa_jwk()), @@ -1255,7 +1254,7 @@ pub fn generate_test_genesis( randomness_config_override: None, jwk_consensus_config_override: None, initial_jwks: vec![], - keyless_groth16_vk_override: None, + keyless_groth16_vk: None, }, &OnChainConsensusConfig::default_for_genesis(), &OnChainExecutionConfig::default_for_genesis(), @@ -1307,7 +1306,7 @@ fn mainnet_genesis_config() -> GenesisConfiguration { randomness_config_override: None, jwk_consensus_config_override: None, initial_jwks: vec![], - keyless_groth16_vk_override: None, + keyless_groth16_vk: None, } } diff --git a/crates/aptos-genesis/src/builder.rs b/crates/aptos-genesis/src/builder.rs index 01921473e7c9b..c3440d5cee217 100644 --- a/crates/aptos-genesis/src/builder.rs +++ b/crates/aptos-genesis/src/builder.rs @@ -444,7 +444,7 @@ pub struct GenesisConfiguration { pub randomness_config_override: Option, pub jwk_consensus_config_override: Option, pub initial_jwks: Vec, - pub keyless_groth16_vk_override: Option, + pub keyless_groth16_vk: Option, } pub type InitConfigFn = Arc; @@ -667,7 +667,7 @@ impl Builder { randomness_config_override: None, jwk_consensus_config_override: None, initial_jwks: vec![], - keyless_groth16_vk_override: None, + keyless_groth16_vk: None, }; if let Some(init_genesis_config) = &self.init_genesis_config { (init_genesis_config)(&mut genesis_config); diff --git a/crates/aptos-genesis/src/lib.rs b/crates/aptos-genesis/src/lib.rs index 8fed37e85cfa6..bcce6731f1e16 100644 --- a/crates/aptos-genesis/src/lib.rs +++ b/crates/aptos-genesis/src/lib.rs @@ -79,7 +79,7 @@ pub struct GenesisInfo { pub randomness_config_override: Option, pub jwk_consensus_config_override: Option, pub initial_jwks: Vec, - pub keyless_groth16_vk_override: Option, + pub keyless_groth16_vk: Option, } impl GenesisInfo { @@ -120,7 +120,7 @@ impl GenesisInfo { randomness_config_override: genesis_config.randomness_config_override.clone(), jwk_consensus_config_override: genesis_config.jwk_consensus_config_override.clone(), initial_jwks: genesis_config.initial_jwks.clone(), - keyless_groth16_vk_override: genesis_config.keyless_groth16_vk_override.clone(), + keyless_groth16_vk: genesis_config.keyless_groth16_vk.clone(), }) } @@ -157,7 +157,7 @@ impl GenesisInfo { randomness_config_override: self.randomness_config_override.clone(), jwk_consensus_config_override: self.jwk_consensus_config_override.clone(), initial_jwks: self.initial_jwks.clone(), - keyless_groth16_vk_override: self.keyless_groth16_vk_override.clone(), + keyless_groth16_vk: self.keyless_groth16_vk.clone(), }, &self.consensus_config, &self.execution_config, diff --git a/crates/aptos-genesis/src/mainnet.rs b/crates/aptos-genesis/src/mainnet.rs index 37ece1845d719..e78e619694ee2 100644 --- a/crates/aptos-genesis/src/mainnet.rs +++ b/crates/aptos-genesis/src/mainnet.rs @@ -144,7 +144,7 @@ impl MainnetGenesisInfo { randomness_config_override: self.randomness_config_override.clone(), jwk_consensus_config_override: self.jwk_consensus_config_override.clone(), initial_jwks: vec![], - keyless_groth16_vk_override: None, + keyless_groth16_vk: None, }, ) } diff --git a/crates/aptos/src/common/types.rs b/crates/aptos/src/common/types.rs index 9667831e814f5..5443a9a936be9 100644 --- a/crates/aptos/src/common/types.rs +++ b/crates/aptos/src/common/types.rs @@ -1608,7 +1608,7 @@ impl FaucetOptions { } /// Gas price options for manipulating how to prioritize transactions -#[derive(Debug, Eq, Parser, PartialEq)] +#[derive(Debug, Clone, Eq, Parser, PartialEq)] pub struct GasOptions { /// Gas multiplier per unit of gas /// diff --git a/crates/aptos/src/genesis/mod.rs b/crates/aptos/src/genesis/mod.rs index 001f9ae1a93ca..5e5fcca4d8ea6 100644 --- a/crates/aptos/src/genesis/mod.rs +++ b/crates/aptos/src/genesis/mod.rs @@ -261,7 +261,7 @@ pub fn fetch_mainnet_genesis_info(git_options: GitOptions) -> CliTypedResult CliTypedResult( &client, AccountAddress::ONE, @@ -900,10 +919,7 @@ pub(crate) async fn spawn_network_and_execute_gov_proposals( ) .await; - assert_eq!( - vk, - Groth16VerificationKey::from(DEVNET_VERIFICATION_KEY.clone()) - ); + assert_eq!(vk, vk_for_testing); let old_config = print_account_resource::( &client, @@ -962,11 +978,6 @@ fun main(core_resources: &signer) {{ hex::encode(training_wheels_pk.to_bytes()) ); - let gas_options = GasOptions { - gas_unit_price: Some(100), - max_gas: Some(2000000), - expiration_secs: 60, - }; let txn_summary = cli .run_script_with_gas_options(root_idx, &script, Some(gas_options)) .await @@ -998,8 +1009,6 @@ fun main(core_resources: &signer) {{ assert_ne!(old_config, new_config); assert_eq!(new_config.max_exp_horizon_secs, max_exp_horizon_secs); - let mut info = swarm.aptos_public_info(); - // Increment sequence number since we patched a JWK info.root_account().increment_sequence_number(); @@ -1014,12 +1023,7 @@ async fn get_latest_jwkset(rest_client: &Client) -> PatchedJWKs { response.into_inner() } -async fn rotate_vk_by_governance<'a>( - cli: &mut CliTestFramework, - info: &mut AptosPublicInfo, - vk: &Groth16VerificationKey, - root_idx: usize, -) { +fn get_rotate_vk_governance_script(vk: &Groth16VerificationKey) -> String { let script = format!( r#" script {{ @@ -1045,6 +1049,17 @@ script {{ ); debug!("Move script for changing VK follows below:\n{:?}", script); + script +} + +async fn rotate_vk_by_governance<'a>( + cli: &mut CliTestFramework, + info: &mut AptosPublicInfo, + vk: &Groth16VerificationKey, + root_idx: usize, +) { + let script = get_rotate_vk_governance_script(vk); + print_account_resource::( info.client(), AccountAddress::ONE, diff --git a/types/src/keyless/bn254_circom.rs b/types/src/keyless/bn254_circom.rs index 1991e32c91420..546bdc968ef29 100644 --- a/types/src/keyless/bn254_circom.rs +++ b/types/src/keyless/bn254_circom.rs @@ -399,7 +399,7 @@ mod test { G1Bytes, G2Bytes, G1_PROJECTIVE_COMPRESSED_NUM_BYTES, G2_PROJECTIVE_COMPRESSED_NUM_BYTES, }, - circuit_constants::devnet_prepared_vk, + circuit_constants::prepared_vk_for_testing, Groth16VerificationKey, }; use ark_bn254::Bn254; @@ -436,7 +436,7 @@ mod test { // Tests conversion between the devnet ark_groth16::PreparedVerificationKey and our Move // representation of it. fn print_groth16_pvk() { - let groth16_vk: Groth16VerificationKey = devnet_prepared_vk().into(); + let groth16_vk: Groth16VerificationKey = prepared_vk_for_testing().into(); println!("alpha_g1: {:?}", hex::encode(groth16_vk.alpha_g1.clone())); println!("beta_g2: {:?}", hex::encode(groth16_vk.beta_g2.clone())); @@ -448,6 +448,6 @@ mod test { let same_pvk: PreparedVerifyingKey = groth16_vk.try_into().unwrap(); - assert_eq!(same_pvk, devnet_prepared_vk()); + assert_eq!(same_pvk, prepared_vk_for_testing()); } } diff --git a/types/src/keyless/circuit_constants.rs b/types/src/keyless/circuit_constants.rs index ce0017e1fe5a9..7013b1fb3fbb6 100644 --- a/types/src/keyless/circuit_constants.rs +++ b/types/src/keyless/circuit_constants.rs @@ -27,7 +27,7 @@ pub(crate) const MAX_COMMITED_EPK_BYTES: u16 = /// This function uses the decimal uncompressed point serialization which is outputted by circom. /// https://github.com/aptos-labs/devnet-groth16-keys/commit/02e5675f46ce97f8b61a4638e7a0aaeaa4351f76 -pub fn devnet_prepared_vk() -> PreparedVerifyingKey { +pub fn prepared_vk_for_testing() -> PreparedVerifyingKey { // Convert the projective points to affine. let alpha_g1 = g1_projective_str_to_affine( "20491192805390485299153009773594534940189261866228447918068658471970481763042", diff --git a/types/src/keyless/mod.rs b/types/src/keyless/mod.rs index 39b546673a723..e686bfc7c6644 100644 --- a/types/src/keyless/mod.rs +++ b/types/src/keyless/mod.rs @@ -32,7 +32,7 @@ pub mod proof_simulation; pub mod test_utils; mod zkp_sig; -use crate::keyless::circuit_constants::devnet_prepared_vk; +use crate::keyless::circuit_constants::prepared_vk_for_testing; pub use bn254_circom::{ g1_projective_str_to_affine, g2_projective_str_to_affine, get_public_inputs_hash, G1Bytes, G2Bytes, G1_PROJECTIVE_COMPRESSED_NUM_BYTES, G2_PROJECTIVE_COMPRESSED_NUM_BYTES, @@ -47,9 +47,9 @@ pub use zkp_sig::ZKP; /// The name of the Move module for keyless accounts deployed at 0x1. pub const KEYLESS_ACCOUNT_MODULE_NAME: &str = "keyless_account"; -/// The devnet VK that is initialized during genesis. -pub static DEVNET_VERIFICATION_KEY: Lazy> = - Lazy::new(devnet_prepared_vk); +/// A VK that we use often for keyless e2e tests and smoke tests. +pub static VERIFICATION_KEY_FOR_TESTING: Lazy> = + Lazy::new(prepared_vk_for_testing); #[macro_export] macro_rules! invalid_signature { diff --git a/types/src/keyless/test_utils.rs b/types/src/keyless/test_utils.rs index 1d275ff3c8b30..83a0021f864a8 100644 --- a/types/src/keyless/test_utils.rs +++ b/types/src/keyless/test_utils.rs @@ -403,7 +403,7 @@ mod test { get_sample_epk_blinder, get_sample_esk, get_sample_exp_date, get_sample_groth16_sig_and_pk, get_sample_jwt_token, get_sample_pepper, }, - Configuration, Groth16Proof, OpenIdSig, DEVNET_VERIFICATION_KEY, + Configuration, Groth16Proof, OpenIdSig, VERIFICATION_KEY_FOR_TESTING, }, transaction::authenticator::EphemeralPublicKey, }; @@ -521,7 +521,7 @@ mod test { // Verify the proof with the test verifying key. If this fails the verifying key does not match the proving used // to generate the proof. proof - .verify_proof(public_inputs_hash, DEVNET_VERIFICATION_KEY.deref()) + .verify_proof(public_inputs_hash, VERIFICATION_KEY_FOR_TESTING.deref()) .unwrap(); prover_response diff --git a/types/src/keyless/tests.rs b/types/src/keyless/tests.rs index 52293caf94336..95d1ad41de51c 100644 --- a/types/src/keyless/tests.rs +++ b/types/src/keyless/tests.rs @@ -9,7 +9,7 @@ use crate::keyless::{ get_sample_openid_sig_and_pk, }, Configuration, EphemeralCertificate, KeylessPublicKey, KeylessSignature, - DEVNET_VERIFICATION_KEY, + VERIFICATION_KEY_FOR_TESTING, }; use aptos_crypto::poseidon_bn254::keyless::fr_to_bytes_le; use std::ops::{AddAssign, Deref}; @@ -74,7 +74,7 @@ fn test_keyless_groth16_proof_verification() { ); proof - .verify_groth16_proof(public_inputs_hash, DEVNET_VERIFICATION_KEY.deref()) + .verify_groth16_proof(public_inputs_hash, VERIFICATION_KEY_FOR_TESTING.deref()) .unwrap(); }