Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Module 0x1::reconfiguration_with_dkg

Reconfiguration with DKG helper functions.

use 0x1::chunky_dkg;
use 0x1::chunky_dkg_config;
use 0x1::chunky_dkg_config_seqnum;
use 0x1::consensus_config;
use 0x1::create_signer;
use 0x1::decryption;
use 0x1::dkg;
use 0x1::execution_config;
use 0x1::features;
use 0x1::gas_schedule;
use 0x1::jwk_consensus_config;
use 0x1::jwks;
use 0x1::keyless_account;
use 0x1::option;
use 0x1::randomness_api_v0_config;
use 0x1::randomness_config;
use 0x1::randomness_config_seqnum;
use 0x1::reconfiguration;
use 0x1::reconfiguration_state;
use 0x1::stake;
use 0x1::system_addresses;
use 0x1::timestamp;
use 0x1::validator_consensus_info;
use 0x1::version;

Function try_start

Trigger a reconfiguration with DKG. Do nothing if one is already in progress.

public(friend) fun try_start()
Implementation
public(friend) fun try_start() {
    let incomplete_dkg_session = dkg::incomplete_session();
    if (incomplete_dkg_session.is_some()) {
        let session = incomplete_dkg_session.borrow();
        if (dkg::session_dealer_epoch(session) == reconfiguration::current_epoch()) {
            return
        }
    };
    // V1 prologue dispatch means chunky DKG is not running this attempt;
    // drop any stale chunky session so finish_with_dkg_result can proceed
    // (e.g., recovery from a stall via local chunky_dkg_override_seq_num).
    if (chunky_dkg::incomplete_session().is_some()) {
        let framework = create_signer::create_signer(@aptos_framework);
        chunky_dkg::try_clear_incomplete_session(&framework);
    };

    reconfiguration_state::on_reconfig_start();
    let cur_epoch = reconfiguration::current_epoch();
    dkg::start(
        cur_epoch,
        randomness_config::current(),
        stake::cur_validator_consensus_infos(),
        validator_consensus_infos_from_validator_set(&stake::next_validator_consensus_infos_v2())
    );
}

Function try_start_with_chunky_dkg

Trigger a reconfiguration with DKG and Chunky DKG. Do nothing if reconfiguration is already in progress; otherwise start both DKG and Chunky DKG.

public(friend) fun try_start_with_chunky_dkg()
Implementation
public(friend) fun try_start_with_chunky_dkg() {
    if (reconfiguration_state::is_in_progress()) { return };

    reconfiguration_state::on_reconfig_start();

    let cur_epoch = reconfiguration::current_epoch();
    let dealer_validator_set = stake::cur_validator_consensus_infos();
    let target_validator_set = validator_consensus_infos_from_validator_set(&stake::next_validator_consensus_infos_v2());
    dkg::start(
        cur_epoch,
        randomness_config::current(),
        dealer_validator_set,
        target_validator_set,
    );
    chunky_dkg::start(
        cur_epoch,
        chunky_dkg_config::current(),
        dealer_validator_set,
        target_validator_set,
    );
}

Function finish

Clear incomplete DKG session, if it exists. Apply buffered on-chain configs (except for ValidatorSet, which is done inside reconfiguration::reconfigure()). Re-enable validator set changes. Run the default reconfiguration to enter the new epoch.

public(friend) fun finish(framework: &signer)
Implementation
public(friend) fun finish(framework: &signer) {
    system_addresses::assert_aptos_framework(framework);
    dkg::try_clear_incomplete_session(framework);
    chunky_dkg::try_clear_incomplete_session(framework);
    consensus_config::on_new_epoch(framework);
    execution_config::on_new_epoch(framework);
    gas_schedule::on_new_epoch(framework);
    std::version::on_new_epoch(framework);
    features::on_new_epoch(framework);
    jwk_consensus_config::on_new_epoch(framework);
    jwks::on_new_epoch(framework);
    keyless_account::on_new_epoch(framework);
    randomness_config_seqnum::on_new_epoch(framework);
    randomness_config::on_new_epoch(framework);
    randomness_api_v0_config::on_new_epoch(framework);
    chunky_dkg_config_seqnum::on_new_epoch(framework);
    chunky_dkg_config::on_new_epoch(framework);
    decryption::on_new_epoch(framework);
    reconfiguration::reconfigure();
}

Function try_finalize_reconfig

Single decision point for completing the in-progress reconfig. Calls finish(account) iff:

  • reconfiguration is in progress, AND
  • DKG has no in-progress session, AND
  • Chunky DKG has no in-progress session, OR the configured grace period (shadow mode) has elapsed since the chunky session started. No-op otherwise. Callers (finish_with_dkg_result, finish_with_chunky_dkg_result, try_complete_after_grace_period) just signal “something may have changed” and let this function decide.
fun try_finalize_reconfig(account: &signer)
Implementation
fun try_finalize_reconfig(account: &signer) {
    if (!reconfiguration_state::is_in_progress()) { return };

    // DKG must be done.
    if (dkg::incomplete_session().is_some()) { return };

    // Chunky DKG must be done OR its grace period (shadow mode) must have elapsed.
    let chunky_session = chunky_dkg::incomplete_session();
    if (chunky_session.is_some()) {
        let grace_period = chunky_dkg_config::grace_period_secs();
        if (grace_period.is_none()) { return };
        let start_time_us = chunky_dkg::session_start_time(chunky_session.borrow());
        let grace_period_us = (*grace_period.borrow()) * 1_000_000;
        if (timestamp::now_microseconds() - start_time_us < grace_period_us) {
            return
        };
    };

    finish(account);
}

Function finish_with_dkg_result

Complete the current DKG session with the given result. Aborts if no DKG session is in progress.

fun finish_with_dkg_result(account: &signer, dkg_result: vector<u8>)
Implementation
fun finish_with_dkg_result(account: &signer, dkg_result: vector<u8>) {
    dkg::finish(dkg_result);
    try_finalize_reconfig(account);
}

Function finish_with_chunky_dkg_result

Complete the current Chunky DKG session with the given result. No-op if Chunky DKG is not enabled. Buffers the derived encryption key for the next epoch.

fun finish_with_chunky_dkg_result(account: &signer, chunky_dkg_result: vector<u8>, encryption_key: vector<u8>)
Implementation
fun finish_with_chunky_dkg_result(
    account: &signer, chunky_dkg_result: vector<u8>, encryption_key: vector<u8>
) {
    if (!chunky_dkg_config::enabled()) {
        return;
    };

    chunky_dkg::finish(chunky_dkg_result);
    let next_epoch = reconfiguration::current_epoch() + 1;
    decryption::set_for_next_epoch(next_epoch, encryption_key);
    try_finalize_reconfig(account);
}

Function try_advance_reconfig

Periodic finalization tick: try to advance the in-progress reconfig. Called from block_prologue_ext / block_prologue_ext_v2 every block after the epoch interval has elapsed. In V2 mode, also gives the grace-period (shadow-mode) escape a chance to fire. In V1 mode after a chunky-only override recovery, lets the reconfig finalize without re-dealing DKG (dkg::start is idempotent per epoch).

public(friend) fun try_advance_reconfig()
Implementation
public(friend) fun try_advance_reconfig() {
    let framework = create_signer::create_signer(@aptos_framework);
    try_finalize_reconfig(&framework);
}

Specification

pragma verify = true;

Function try_start

public(friend) fun try_start()
pragma verify_duration_estimate = 120;
requires exists<reconfiguration::Configuration>(@aptos_framework);
requires chain_status::is_operating();
include stake::ResourceRequirement;
include stake::GetReconfigStartTimeRequirement;
include features::spec_periodical_reward_rate_decrease_enabled() ==>
    staking_config::StakingRewardsConfigEnabledRequirement;
aborts_if false;
pragma verify_duration_estimate = 600;
ensures !old(reconfiguration_state::spec_is_in_progress()) ==>
    exists<stake::PrecomputedValidatorSet>(@aptos_framework);

Function try_start_with_chunky_dkg

public(friend) fun try_start_with_chunky_dkg()
pragma verify_duration_estimate = 600;
requires exists<reconfiguration::Configuration>(@aptos_framework);
requires chain_status::is_operating();
requires exists<chunky_dkg::ChunkyDKGState>(@aptos_framework);
requires exists<timestamp::CurrentTimeMicroseconds>(@aptos_framework);
include stake::ResourceRequirement;
include stake::GetReconfigStartTimeRequirement;
include features::spec_periodical_reward_rate_decrease_enabled() ==>
    staking_config::StakingRewardsConfigEnabledRequirement;
aborts_if false;
ensures !old(reconfiguration_state::spec_is_in_progress()) ==>
    exists<stake::PrecomputedValidatorSet>(@aptos_framework);

Function finish

public(friend) fun finish(framework: &signer)
pragma verify_duration_estimate = 1500;
include FinishRequirement;
aborts_if false;

schema FinishRequirement {
    framework: signer;
    requires signer::address_of(framework) == @aptos_framework;
    requires chain_status::is_operating();
    requires exists<CoinInfo<AptosCoin>>(@aptos_framework);
    include staking_config::StakingRewardsConfigRequirement;
    requires exists<features::Features>(@std);
    include config_buffer::OnNewEpochRequirement<version::Version>;
    include config_buffer::OnNewEpochRequirement<gas_schedule::GasScheduleV2>;
    include config_buffer::OnNewEpochRequirement<execution_config::ExecutionConfig>;
    include config_buffer::OnNewEpochRequirement<consensus_config::ConsensusConfig>;
    include config_buffer::OnNewEpochRequirement<jwks::SupportedOIDCProviders>;
    include config_buffer::OnNewEpochRequirement<randomness_config::RandomnessConfig>;
    include config_buffer::OnNewEpochRequirement<randomness_config_seqnum::RandomnessConfigSeqNum>;
    include config_buffer::OnNewEpochRequirement<randomness_api_v0_config::AllowCustomMaxGasFlag>;
    include config_buffer::OnNewEpochRequirement<randomness_api_v0_config::RequiredGasDeposit>;
    include config_buffer::OnNewEpochRequirement<jwk_consensus_config::JWKConsensusConfig>;
    include config_buffer::OnNewEpochRequirement<keyless_account::Configuration>;
    include config_buffer::OnNewEpochRequirement<keyless_account::Groth16VerificationKey>;
}

Function try_finalize_reconfig

fun try_finalize_reconfig(account: &signer)
pragma verify = false;

Function finish_with_dkg_result

fun finish_with_dkg_result(account: &signer, dkg_result: vector<u8>)
pragma verify_duration_estimate = 1500;
include FinishRequirement { framework: account };
requires dkg::has_incomplete_session();
aborts_if false;

Function finish_with_chunky_dkg_result

fun finish_with_chunky_dkg_result(account: &signer, chunky_dkg_result: vector<u8>, encryption_key: vector<u8>)
pragma verify = false;

Function try_advance_reconfig

public(friend) fun try_advance_reconfig()
pragma verify = false;