Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

goverened gas pool spec #118

Open
wants to merge 9 commits into
base: l-monninger/governed-gas-pool
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ module aptos_framework::governed_gas_pool {
aptos_framework: &signer,
delegation_pool_creation_seed: vector<u8>,
) {
system_addresses::assert_aptos_framework(aptos_framework);

// generate a seed to be used to create the resource account hosting the delegation pool
let seed = create_resource_account_seed(delegation_pool_creation_seed);

Expand Down Expand Up @@ -312,4 +314,4 @@ module aptos_framework::governed_gas_pool {

}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
spec aptos_framework::governed_gas_pool {
use aptos_framework::coin::CoinStore;
use aptos_framework::coin::EINSUFFICIENT_BALANCE;
use aptos_framework::error;

/// <high-level-req>
/// No.: 1
/// Requirement: The GovernedGasPool resource must exist at the aptos_framework address after initialization.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

/// Criticality: Critical
/// Implementation: The initialize function ensures the resource is created at the aptos_framework address.
/// Enforcement: Formally verified via [high-level-req-1](initialize).
///
/// No.: 2
/// Requirement: Only the aptos_framework address is allowed to initialize the GovernedGasPool.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

/// Criticality: Critical
/// Implementation: The initialize function verifies the signer is the aptos_framework address.
/// Enforcement: Formally verified via [high-level-req-2](initialize).
///
/// No.: 3
/// Requirement: Deposits into the GovernedGasPool must be reflected in the pool's balance.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say you want to prove above that initialization creates a resource account distinct from the aptos_framework address. Then deposits into the GovernedGasPool are reflected in that account's balance.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I try to to do ensures with anything resource account related I get the error noted down in the PR description.

/// Criticality: High
/// Implementation: The deposit and deposit_from functions update the pool's balance.
/// Enforcement: Formally verified via [high-level-req-3](deposit), [high-level-req-3.1](deposit_from).
///
/// No.: 4
/// Requirement: Only the aptos_framework address can fund accounts from the GovernedGasPool.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

/// Criticality: High
/// Implementation: The fund function verifies the signer is the aptos_framework address.
/// Enforcement: Formally verified via [high-level-req-4](fund).
///
/// No.: 5
/// Requirement: Gas fees must be deposited into the GovernedGasPool whenever specified by the configuration.
0xmovses marked this conversation as resolved.
Show resolved Hide resolved
/// Criticality: High
/// Implementation: The deposit_gas_fee function ensures gas fees are deposited correctly.
/// Enforcement: Formally verified via [high-level-req-5](deposit_gas_fee).
/// </high-level-req>

spec module {
/// [high-level-req-1]
/// The GovernedGasPool resource must exist at aptos_framework after initialization.
invariant exists<GovernedGasPool>(@aptos_framework);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GovernGasPool exists for the aptos_framework cannot be an invariant. You would need an exists implies, i.e., ==>. One thing the GovernedGasPool existing could imply is that the resource account for the GovernedGasPool exists.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's passing though, I think because of

spec initialize(aptos_framework: &signer, delegation_pool_creation_seed: vector<u8>) {
        requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
        /// [high-level-req-1]
        ensures exists<GovernedGasPool>(@aptos_framework);
    }
    ```

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can remove it if you we prefer. I suppose we would need to be doing an init_module for it to be an invariant.

}

spec initialize(aptos_framework: &signer, delegation_pool_creation_seed: vector<u8>) {
requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
/// [high-level-req-1]
ensures exists<GovernedGasPool>(@aptos_framework);
}

spec fund<CoinType>(aptos_framework: &signer, account: address, amount: u64) {
pragma aborts_if_is_partial = true;

/// [high-level-req-4]
// Abort if the caller is not the Aptos framework
aborts_if !system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));

/// Abort if the governed gas pool has insufficient funds
aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
}

spec deposit<CoinType>(coin: Coin<CoinType>) {
pragma aborts_if_is_partial = true;

/// [high-level-req-3]
/// Ensure the deposit increases the value in the CoinStore

//@TODO: Calling governed_gas_pool_adddress() doesn't work as the boogie gen cant check the signer
// created for the resource account created at runtime

/// Ensure the governed gas pool resource account exists
//aborts_if !exists<CoinStore<CoinType>>(governed_gas_pool_address());

//ensures global<CoinStore<CoinType>>(aptos_framework_address).coin.value ==
//old(global<CoinStore<CoinType>>(aptos_framework_address).coin.value) + coin.value;
}

spec deposit_gas_fee(gas_payer: address, gas_fee: u64) {
/// [high-level-req-5]
// ensures governed_gas_pool_balance<AptosCoin> == old(governed_gas_pool_balance<AptosCoin>) + gas_fee;
// ensures gas_payer_balance<AptosCoin> == old(gas_payer_balance<AptosCoin>) - gas_fee;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ spec aptos_framework::transaction_validation {
use aptos_framework::coin::{CoinStore, CoinInfo};
use aptos_framework::optional_aggregator;
use aptos_framework::transaction_fee::{AptosCoinCapabilities, AptosCoinMintCapability, CollectedFeesPerBlock};
use aptos_framework::governed_gas_pool::{GovernedGasPool, governed_gas_pool_address};

account: signer;
gas_payer: address;
Expand All @@ -272,6 +273,10 @@ spec aptos_framework::transaction_validation {
txn_max_gas_units: u64;
gas_units_remaining: u64;

// Precondition: Governed Gas Pool must be initialized
requires exists<GovernedGasPool>(@aptos_framework);
requires exists<CoinStore<AptosCoin>>(governed_gas_pool_address());

// Check transaction invariants.
aborts_if !(txn_max_gas_units >= gas_units_remaining);
let gas_used = txn_max_gas_units - gas_units_remaining;
Expand All @@ -285,8 +290,8 @@ spec aptos_framework::transaction_validation {
// let post balance = global<coin::CoinStore<AptosCoin>>(gas_payer).coin.value;

// TODO(governed_gas_pool)
// let pre_governed_gas_pool_balance = global<coin::CoinStore<AptosCoin>>(governed_gas_pool).coin.value;
// let post governed_gas_pool_balance = global<coin::CoinStore<AptosCoin>>(governed_gas_pool).coin.value;
let pre_governed_gas_pool_balance = global<coin::CoinStore<AptosCoin>>(governed_gas_pool_address()).coin.value;
let post governed_gas_pool_balance = global<coin::CoinStore<AptosCoin>>(governed_gas_pool_address()).coin.value;

let pre_account = global<account::Account>(addr);
let post account = global<account::Account>(addr);
Expand All @@ -298,8 +303,8 @@ spec aptos_framework::transaction_validation {
// aborts_if pre_balance < transaction_fee_amount;
// ensures balance == pre_balance - transaction_fee_amount + storage_fee_refunded;
// TODO(governd_gas_pool)
// ensures governed_gas_pool_balance == pre_governed_gas_pool_balance + transaction_fee_amount;
ensures account.sequence_number == pre_account.sequence_number + 1;
//ensures governed_gas_pool_balance == pre_governed_gas_pool_balance + transaction_fee_amount;
//ensures account.sequence_number == pre_account.sequence_number + 1;

// Check fee collection.
let governed_gas_pool_enabled = features::spec_is_enabled(features::GOVERNED_GAS_POOL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ module std::features {
public fun get_coin_to_fungible_asset_migration_feature(): u64 { COIN_TO_FUNGIBLE_ASSET_MIGRATION }

public fun coin_to_fungible_asset_migration_feature_enabled(): bool acquires Features {
is_enabled(COIN_TO_FUNGIBLE_ASSET_MIGRATION)
is_enabled(COIN_TO_FUNGIBLE_ASSET_MIGRATION)
}

const PRIMARY_APT_FUNGIBLE_STORE_AT_USER_ADDRESS: u64 = 61;
Expand Down