keyless_account - [devnet]
This module is responsible for configuring keyless blockchain accounts which were introduced in AIP-61.
use 0x1::bn254_algebra;use 0x1::chain_status;use 0x1::config_buffer;use 0x1::crypto_algebra;use 0x1::ed25519;use 0x1::option;use 0x1::signer;use 0x1::string;use 0x1::system_addresses;Constants
A serialized BN254 G1 point is invalid.
const E_INVALID_BN254_G1_SERIALIZATION: u64 = 2;A serialized BN254 G2 point is invalid.
const E_INVALID_BN254_G2_SERIALIZATION: u64 = 3;The training wheels PK needs to be 32 bytes long.
const E_TRAINING_WHEELS_PK_WRONG_SIZE: u64 = 1;Structs
Group
#[resource_group(#[scope = global])]struct GroupFields
- 
dummy_field: bool 
Resources
Groth16VerificationKey
The 288-byte Groth16 verification key (VK) for the ZK relation that implements keyless accounts
#[resource_group_member(#[group = 0x1::keyless_account::Group])]struct Groth16VerificationKey has drop, store, keyFields
- 
alpha_g1: vector<u8> - 
 32-byte serialization of 
alpha * G, whereGis the generator ofG1. - 
beta_g2: vector<u8> - 
 64-byte serialization of 
alpha * H, whereHis the generator ofG2. - 
gamma_g2: vector<u8> - 
 64-byte serialization of 
gamma * H, whereHis the generator ofG2. - 
delta_g2: vector<u8> - 
 64-byte serialization of 
delta * H, whereHis the generator ofG2. - 
gamma_abc_g1: vector<vector<u8>> - 
 
\forall i \in {0, ..., \ell}, 64-byte serialization of gamma^{-1} * (beta * a_i + alpha * b_i + c_i) * H, whereHis the generator ofG1and\ellis 1 for the ZK relation. 
Configuration
#[resource_group_member(#[group = 0x1::keyless_account::Group])]struct Configuration has copy, drop, store, keyFields
- 
override_aud_vals: vector<string::String> - 
 An override 
audfor the identity of a recovery service, which will help users recover their keyless accounts associated with dapps or wallets that have disappeared. IMPORTANT: This recovery service **cannot** on its own take over user accounts; a user must first sign in via OAuth in the recovery service in order to allow it to rotate any of that user's keyless accounts. - 
max_signatures_per_txn: u16 - No transaction can have more than this many keyless signatures.
 - 
max_exp_horizon_secs: u64 - How far in the future from the JWT issued at time the EPK expiry can be set.
 - 
training_wheels_pubkey: option::Option<vector<u8>> - The training wheels PK, if training wheels are on
 - 
max_commited_epk_bytes: u16 - The max length of an ephemeral public key supported in our circuit (93 bytes)
 - 
max_iss_val_bytes: u16 - 
 The max length of the value of the JWT's 
issfield supported in our circuit (e.g.,"https://accounts.google.com") - 
max_extra_field_bytes: u16 - 
 The max length of the JWT field name and value (e.g., 
"max_age":"18") supported in our circuit - 
max_jwt_header_b64_bytes: u32 - The max length of the base64url-encoded JWT header in bytes supported in our circuit
 
Functions
new_groth16_verification_key
public fun new_groth16_verification_key(alpha_g1: vector<u8>, beta_g2: vector<u8>, gamma_g2: vector<u8>, delta_g2: vector<u8>, gamma_abc_g1: vector<vector<u8>>): keyless_account::Groth16VerificationKeyImplementation
public fun new_groth16_verification_key(alpha_g1: vector<u8>,                                        beta_g2: vector<u8>,                                        gamma_g2: vector<u8>,                                        delta_g2: vector<u8>,                                        gamma_abc_g1: vector<vector<u8>>): Groth16VerificationKey {    Groth16VerificationKey {        alpha_g1,        beta_g2,        gamma_g2,        delta_g2,        gamma_abc_g1,    }}new_configuration
public fun new_configuration(override_aud_val: vector<string::String>, max_signatures_per_txn: u16, max_exp_horizon_secs: u64, training_wheels_pubkey: option::Option<vector<u8>>, max_commited_epk_bytes: u16, max_iss_val_bytes: u16, max_extra_field_bytes: u16, max_jwt_header_b64_bytes: u32): keyless_account::ConfigurationImplementation
public fun new_configuration(    override_aud_val: vector<String>,    max_signatures_per_txn: u16,    max_exp_horizon_secs: u64,    training_wheels_pubkey: Option<vector<u8>>,    max_commited_epk_bytes: u16,    max_iss_val_bytes: u16,    max_extra_field_bytes: u16,    max_jwt_header_b64_bytes: u32): Configuration {    Configuration {        override_aud_vals: override_aud_val,        max_signatures_per_txn,        max_exp_horizon_secs,        training_wheels_pubkey,        max_commited_epk_bytes,        max_iss_val_bytes,        max_extra_field_bytes,        max_jwt_header_b64_bytes,    }}validate_groth16_vk
Pre-validate the VK to actively-prevent incorrect VKs from being set on-chain.
fun validate_groth16_vk(vk: &keyless_account::Groth16VerificationKey)Implementation
fun validate_groth16_vk(vk: &Groth16VerificationKey) {    // Could be leveraged to speed up the VM deserialization of the VK by 2x, since it can assume the points are valid.    assert!(option::is_some(&crypto_algebra::deserialize<bn254_algebra::G1, bn254_algebra::FormatG1Compr>(&vk.alpha_g1)), E_INVALID_BN254_G1_SERIALIZATION);    assert!(option::is_some(&crypto_algebra::deserialize<bn254_algebra::G2, bn254_algebra::FormatG2Compr>(&vk.beta_g2)), E_INVALID_BN254_G2_SERIALIZATION);    assert!(option::is_some(&crypto_algebra::deserialize<bn254_algebra::G2, bn254_algebra::FormatG2Compr>(&vk.gamma_g2)), E_INVALID_BN254_G2_SERIALIZATION);    assert!(option::is_some(&crypto_algebra::deserialize<bn254_algebra::G2, bn254_algebra::FormatG2Compr>(&vk.delta_g2)), E_INVALID_BN254_G2_SERIALIZATION);    for (i in 0..vector::length(&vk.gamma_abc_g1)) {        assert!(option::is_some(&crypto_algebra::deserialize<bn254_algebra::G1, bn254_algebra::FormatG1Compr>(vector::borrow(&vk.gamma_abc_g1, i))), E_INVALID_BN254_G1_SERIALIZATION);    };}update_groth16_verification_key
Sets the Groth16 verification key, only callable during genesis. To call during governance proposals, use
set_groth16_verification_key_for_next_epoch.
WARNING: See set_groth16_verification_key_for_next_epoch for caveats.
public fun update_groth16_verification_key(fx: &signer, vk: keyless_account::Groth16VerificationKey)Implementation
public fun update_groth16_verification_key(fx: &signer, vk: Groth16VerificationKey) {    system_addresses::assert_aptos_framework(fx);    chain_status::assert_genesis();    // There should not be a previous resource set here.    move_to(fx, vk);}update_configuration
Sets the keyless configuration, only callable during genesis. To call during governance proposals, use
set_configuration_for_next_epoch.
WARNING: See set_configuration_for_next_epoch for caveats.
public fun update_configuration(fx: &signer, config: keyless_account::Configuration)Implementation
public fun update_configuration(fx: &signer, config: Configuration) {    system_addresses::assert_aptos_framework(fx);    chain_status::assert_genesis();    // There should not be a previous resource set here.    move_to(fx, config);}update_training_wheels
#[deprecated]public fun update_training_wheels(fx: &signer, pk: option::Option<vector<u8>>)Implementation
public fun update_training_wheels(fx: &signer, pk: Option<vector<u8>>) acquires Configuration {    system_addresses::assert_aptos_framework(fx);    chain_status::assert_genesis();
    if (option::is_some(&pk)) {        assert!(vector::length(option::borrow(&pk)) == 32, E_TRAINING_WHEELS_PK_WRONG_SIZE)    };
    let config = borrow_global_mut<Configuration>(signer::address_of(fx));    config.training_wheels_pubkey = pk;}update_max_exp_horizon
#[deprecated]public fun update_max_exp_horizon(fx: &signer, max_exp_horizon_secs: u64)Implementation
public fun update_max_exp_horizon(fx: &signer, max_exp_horizon_secs: u64) acquires Configuration {    system_addresses::assert_aptos_framework(fx);    chain_status::assert_genesis();
    let config = borrow_global_mut<Configuration>(signer::address_of(fx));    config.max_exp_horizon_secs = max_exp_horizon_secs;}remove_all_override_auds
#[deprecated]public fun remove_all_override_auds(fx: &signer)Implementation
public fun remove_all_override_auds(fx: &signer) acquires Configuration {    system_addresses::assert_aptos_framework(fx);    chain_status::assert_genesis();
    let config = borrow_global_mut<Configuration>(signer::address_of(fx));    config.override_aud_vals = vector[];}add_override_aud
#[deprecated]public fun add_override_aud(fx: &signer, aud: string::String)Implementation
public fun add_override_aud(fx: &signer, aud: String) acquires Configuration {    system_addresses::assert_aptos_framework(fx);    chain_status::assert_genesis();
    let config = borrow_global_mut<Configuration>(signer::address_of(fx));    vector::push_back(&mut config.override_aud_vals, aud);}set_groth16_verification_key_for_next_epoch
Queues up a change to the Groth16 verification key. The change will only be effective after reconfiguration. Only callable via governance proposal.
WARNING: To mitigate against DoS attacks, a VK change should be done together with a training wheels PK change, so that old ZKPs for the old VK cannot be replayed as potentially-valid ZKPs.
WARNING: If a malicious key is set, this would lead to stolen funds.
public fun set_groth16_verification_key_for_next_epoch(fx: &signer, vk: keyless_account::Groth16VerificationKey)Implementation
public fun set_groth16_verification_key_for_next_epoch(fx: &signer, vk: Groth16VerificationKey) {    system_addresses::assert_aptos_framework(fx);    config_buffer::upsert<Groth16VerificationKey>(vk);}set_configuration_for_next_epoch
Queues up a change to the keyless configuration. The change will only be effective after reconfiguration. Only callable via governance proposal.
WARNING: A malicious Configuration could lead to DoS attacks, create liveness issues, or enable a malicious
recovery service provider to phish users’ accounts.
public fun set_configuration_for_next_epoch(fx: &signer, config: keyless_account::Configuration)Implementation
public fun set_configuration_for_next_epoch(fx: &signer, config: Configuration) {    system_addresses::assert_aptos_framework(fx);    config_buffer::upsert<Configuration>(config);}update_training_wheels_for_next_epoch
Convenience method to queue up a change to the training wheels PK. The change will only be effective after reconfiguration. Only callable via governance proposal.
WARNING: If a malicious key is set, this could lead to stolen funds.
public fun update_training_wheels_for_next_epoch(fx: &signer, pk: option::Option<vector<u8>>)Implementation
public fun update_training_wheels_for_next_epoch(fx: &signer, pk: Option<vector<u8>>) acquires Configuration {    system_addresses::assert_aptos_framework(fx);
    // If a PK is being set, validate it first.    if (option::is_some(&pk)) {        let bytes = *option::borrow(&pk);        let vpk = ed25519::new_validated_public_key_from_bytes(bytes);        assert!(option::is_some(&vpk), E_TRAINING_WHEELS_PK_WRONG_SIZE)    };
    let config = if (config_buffer::does_exist<Configuration>()) {        config_buffer::extract_v2<Configuration>()    } else {        *borrow_global<Configuration>(signer::address_of(fx))    };
    config.training_wheels_pubkey = pk;
    set_configuration_for_next_epoch(fx, config);}update_max_exp_horizon_for_next_epoch
Convenience method to queues up a change to the max expiration horizon. The change will only be effective after reconfiguration. Only callable via governance proposal.
public fun update_max_exp_horizon_for_next_epoch(fx: &signer, max_exp_horizon_secs: u64)Implementation
public fun update_max_exp_horizon_for_next_epoch(fx: &signer, max_exp_horizon_secs: u64) acquires Configuration {    system_addresses::assert_aptos_framework(fx);
    let config = if (config_buffer::does_exist<Configuration>()) {        config_buffer::extract_v2<Configuration>()    } else {        *borrow_global<Configuration>(signer::address_of(fx))    };
    config.max_exp_horizon_secs = max_exp_horizon_secs;
    set_configuration_for_next_epoch(fx, config);}remove_all_override_auds_for_next_epoch
Convenience method to queue up clearing the set of override aud’s. The change will only be effective after
reconfiguration. Only callable via governance proposal.
WARNING: When no override aud is set, recovery of keyless accounts associated with applications that disappeared
is no longer possible.
public fun remove_all_override_auds_for_next_epoch(fx: &signer)Implementation
public fun remove_all_override_auds_for_next_epoch(fx: &signer) acquires Configuration {    system_addresses::assert_aptos_framework(fx);
    let config = if (config_buffer::does_exist<Configuration>()) {        config_buffer::extract_v2<Configuration>()    } else {        *borrow_global<Configuration>(signer::address_of(fx))    };
    config.override_aud_vals = vector[];
    set_configuration_for_next_epoch(fx, config);}add_override_aud_for_next_epoch
Convenience method to queue up an append to the set of override aud’s. The change will only be effective
after reconfiguration. Only callable via governance proposal.
WARNING: If a malicious override aud is set, this could lead to stolen funds.
public fun add_override_aud_for_next_epoch(fx: &signer, aud: string::String)Implementation
public fun add_override_aud_for_next_epoch(fx: &signer, aud: String) acquires Configuration {    system_addresses::assert_aptos_framework(fx);
    let config = if (config_buffer::does_exist<Configuration>()) {        config_buffer::extract_v2<Configuration>()    } else {        *borrow_global<Configuration>(signer::address_of(fx))    };
    vector::push_back(&mut config.override_aud_vals, aud);
    set_configuration_for_next_epoch(fx, config);}on_new_epoch
Only used in reconfigurations to apply the queued up configuration changes, if there are any.
public(friend) fun on_new_epoch(fx: &signer)Implementation
public(friend) fun on_new_epoch(fx: &signer) acquires Groth16VerificationKey, Configuration {    system_addresses::assert_aptos_framework(fx);
    if (config_buffer::does_exist<Groth16VerificationKey>()) {        let vk = config_buffer::extract_v2();        if (exists<Groth16VerificationKey>(@aptos_framework)) {            *borrow_global_mut<Groth16VerificationKey>(@aptos_framework) = vk;        } else {            move_to(fx, vk);        }    };
    if (config_buffer::does_exist<Configuration>()) {        let config = config_buffer::extract_v2();        if (exists<Configuration>(@aptos_framework)) {            *borrow_global_mut<Configuration>(@aptos_framework) = config;        } else {            move_to(fx, config);        }    };}Specification
pragma verify=false;