Module 0x1::reconfiguration_with_dkg
Reconfiguration with DKG helper functions.
- Function
try_start - Function
try_start_with_chunky_dkg - Function
finish - Function
try_finalize_reconfig - Function
finish_with_dkg_result - Function
finish_with_chunky_dkg_result - Function
try_advance_reconfig - Specification
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;