Skip to content
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
13 changes: 2 additions & 11 deletions crates/sui-framework/packages/sui-framework/Move.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,9 @@

[move]
version = 3
manifest_digest = "06FD8F5C2B5CB25BBFF27D5AF3EEEC284C453E7190F2FA22CEC3FB4270B4B5D4"
deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600"

dependencies = [
{ id = "MoveStdlib", name = "MoveStdlib" },
]
manifest_digest = "CD04B0AFFBEA9E38D757D76D077FCB8D9F7E69A99F98F542A4F6D5DBBB6B84A0"
deps_digest = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"

[[move.package]]
id = "MoveStdlib"
source = { local = "../move-stdlib" }

[move.toolchain-version]
compiler-version = "1.30.0"
edition = "2024.beta"
flavor = "sui"
11 changes: 11 additions & 0 deletions crates/sui-framework/packages/sui-system-specs/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "SuiSystemSpecs"
version = "0.0.1"
published-at = "0x31"
edition = "2024.beta"

[dependencies]
SuiSystem = { local = "../sui-system" }

[addresses]
sui_system_specs = "0x31"
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
module sui_system_specs::helpers;

#[spec_only]
use std::{u64,u32,u16,u8};
#[spec_only]
use prover::prover::{ensures, invariant};

#[spec_only]
/// x+y will not abort (u64)
fun can_add_u64(x: u64, y: u64): bool {
x.to_int().add(y.to_int()).lte(u64::max_value!().to_int())
}

#[spec_only]
/// x+y will not abort (u32)
fun can_add_u32(x: u32, y: u32): bool {
x.to_int().add(y.to_int()).lte(u32::max_value!().to_int())
}

#[spec_only]
/// x-y will not abort
fun can_sub_u64(x: u64, y: u64): bool {
y <= x
}

#[spec_only]
/// x-y will not abort
fun can_sub_u32(x: u32, y: u32): bool {
y <= x
}

// iteration macros have expansions that wrap up the contained loop,
// so that an invariant cannot be attached. the versions here have a
// parameter that will give the loop invarant, which gets placed in
// the correct spot.

/// like `std::macros::range_do`, but allows for an invariant.
/// The supplied function takes one parameter, the loop index
public macro fun range_do_with_invariant<$T, $R: drop>($start: $T, $stop: $T, $f: |$T| -> $R, $g: |$T| -> bool) {
let mut i = $start;
let stop = $stop;
invariant!(|| { ensures( $g(i) ); });
while (i < stop) {
$f(i);
i = i + 1;
}
}

/// like `std::macros::do`, but allows for an invariant.
/// The supplied function takes one parameter, the loop index
public macro fun do_with_invariant<$T, $R: drop>($stop: $T, $f: |$T| -> $R, $g: |$T| -> bool) {
range_do_with_invariant!(0, $stop, $f, $g)
}

/// like `std:vectors::do`, but allows for an invariant.
/// The supplied function takes one parameter, the loop index
/// (which is also used as the index into the vector in the loop)
public macro fun vector_do_ref_with_invariant<$T, $R: drop>($v: &vector<$T>, $f: |&$T| -> $R, $g: |u64| -> bool) {
let v = $v;
do_with_invariant!(v.length(), |i| $f(&v[i]), |i| i <= v.length() && ($g(i)))
}

/// like `std::vectors::find_index`, but allows for an invariant.
public macro fun vector_find_index_with_invariant<$T>($v: &vector<$T>,
$f: |&$T| -> bool,
$g: |u64| -> bool): Option<u64> {
let v = $v;
'find_index: {
do_with_invariant!(v.length(),
(|i| if ($f(&v[i])) return 'find_index std::option::some(i)), // do this
(|i| i <= v.length() && ($g(i)))); // using this invariant
std::option::none()
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think sender_spec and epoch_spec are needed any more with the latest prover

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module sui_system_specs::other_specs;

#[spec(target = sui::tx_context::epoch)]
public fun epoch_spec(self: &TxContext): u64 {
sui::tx_context::epoch(self)
}

#[spec(target = sui::tx_context::sender)]
public fun sender_spec(self: &TxContext): address {
sui::tx_context::sender(self)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module sui_system_specs::stake_subsidy;

#[spec_only]
use sui_system::stake_subsidy::{
StakeSubsidy,
current_epoch_subsidy_amount
};

// This invariant is needed to prove no abort in some of the non-public functions,
// so can be skipped for now.

// #[spec_only]
// fun StakeSubsidy_inv(x: &StakeSubsidy): bool {
// x.stake_subsidy_decrease_rate <= BASIS_POINT_DENOMINATOR as u16 &&
// x.stake_subsidy_period_length > 0
// }

#[spec(prove, no_opaque, target = sui_system::stake_subsidy::current_epoch_subsidy_amount)]
public fun current_epoch_subsidy_amount_spec(self: &StakeSubsidy): u64 {
current_epoch_subsidy_amount(self)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#[allow(unused_const)]
module sui_system_specs::staking_pool;

#[spec_only]
use sui_system::staking_pool::{
PoolTokenExchangeRate,
StakedSui,
StakingPool,
FungibleStakedSui,
staked_sui_amount,
is_preactive,
is_inactive,
split_fungible_staked_sui,
join_fungible_staked_sui,
is_equal_staking_metadata,
split,
split_staked_sui,
pool_token_exchange_rate_at_epoch,
join_staked_sui,
fungible_staked_sui_value,
activation_epoch,
};

#[spec_only]
use sui_system_specs::helpers::can_add_u64;

#[spec_only]
use prover::prover::{requires, ensures};

#[spec_only]
use prover::ghost;

/// CLONE.
#[spec_only]
const MIN_STAKING_THRESHOLD: u64 = 1_000_000_000; // 1 SUI

#[spec(prove, no_opaque, target = sui_system::staking_pool::staked_sui_amount)]
public fun staked_sui_amount_spec(staked_sui: &StakedSui): u64 {
staked_sui_amount(staked_sui)
}

#[spec(prove, no_opaque, target = sui_system::staking_pool::is_preactive)]
public fun is_preactive_spec(pool: &StakingPool): bool {
is_preactive(pool)
}

#[spec(prove, no_opaque, target = sui_system::staking_pool::is_inactive)]
public fun is_inactive_spec(pool: &StakingPool): bool {
is_inactive(pool)
}

#[spec(prove, target = sui_system::staking_pool::split_fungible_staked_sui)]
public fun split_fungible_staked_sui_spec(
fungible_staked_sui: &mut FungibleStakedSui,
split_amount: u64,
ctx: &mut TxContext,
): FungibleStakedSui {
requires(split_amount <= fungible_staked_sui_value(fungible_staked_sui));
split_fungible_staked_sui(fungible_staked_sui, split_amount, ctx)
}

#[spec(prove, target = sui_system::staking_pool::join_fungible_staked_sui)]
public fun join_fungible_staked_sui_spec(self: &mut FungibleStakedSui, other: FungibleStakedSui) {
requires(self.pool_id() == other.pool_id());
requires(can_add_u64(self.value(), other.value()));
join_fungible_staked_sui(self, other);
}

#[spec(prove, target = sui_system::staking_pool::split)]
public fun split_spec(self: &mut StakedSui, split_amount: u64, ctx: &mut TxContext): StakedSui {
requires(split_amount <= staked_sui_amount(self));
requires(split_amount >= MIN_STAKING_THRESHOLD);
requires(staked_sui_amount(self) - split_amount >= MIN_STAKING_THRESHOLD);
split(self, split_amount, ctx)
}

#[spec(prove, no_opaque, target = sui_system::staking_pool::is_equal_staking_metadata)]
public fun is_equal_staking_metadata_spec(self: &StakedSui, other: &StakedSui): bool {
is_equal_staking_metadata(self, other)
}

#[spec_only]
/// function needed to make the requirements of `pool_token_exchange_rate_at_epoch_spec`
/// expressible outside this module.
public fun activation_epoch_is_positive(pool: &StakingPool): bool {
let epoch_opt = activation_epoch(pool);
epoch_opt.is_some() &&
*epoch_opt.borrow() > 0
}

#[spec(prove, target = sui_system::staking_pool::pool_token_exchange_rate_at_epoch)]
public fun pool_token_exchange_rate_at_epoch_spec(
pool: &StakingPool,
epoch: u64,
): PoolTokenExchangeRate {
requires(! pool.is_preactive());
// requires(*pool.activation_epoch.borrow() > 0); // visible? add to invariant?
requires(activation_epoch_is_positive(pool));
pool_token_exchange_rate_at_epoch(pool, epoch)
}

#[spec(prove, target = sui_system::staking_pool::split_staked_sui)]
public fun split_staked_sui_spec(stake: &mut StakedSui, split_amount: u64, ctx: &mut TxContext) {
use specs::transfer_spec::{SpecTransferAddress,SpecTransferAddressExists};
ghost::declare_global_mut<SpecTransferAddressExists, bool>();
ghost::declare_global_mut<SpecTransferAddress, address>();
// preconditions from the call to split:
requires(split_amount <= staked_sui_amount(stake));
requires(split_amount >= MIN_STAKING_THRESHOLD);
requires(staked_sui_amount(stake) - split_amount >= MIN_STAKING_THRESHOLD);
split_staked_sui(stake, split_amount, ctx);
}

#[spec(prove, target = sui_system::staking_pool::join_staked_sui)]
public fun join_staked_sui_spec(self: &mut StakedSui, other: StakedSui) {
requires(is_equal_staking_metadata(self, &other));
requires(can_add_u64(staked_sui_amount(self), staked_sui_amount(&other))); // or the join overflows
join_staked_sui(self, other);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module sui_system_specs::storage_fund;

#[spec_only]
use sui_system::storage_fund::{
StorageFund,
total_object_storage_rebates,
non_refundable_balance,
total_balance,
};

#[spec_only]
use sui_system_specs::helpers::can_add_u64;

#[spec_only]
use prover::prover::requires;


#[spec(prove, no_opaque, target = sui_system::storage_fund::total_object_storage_rebates)]
public fun total_object_storage_rebates_spec(self: &StorageFund): u64 {
total_object_storage_rebates(self)
}

#[spec(prove, target = sui_system::storage_fund::total_balance)]
public fun total_balance_spec(self: &StorageFund): u64 {
requires(can_add_u64(total_object_storage_rebates(self), non_refundable_balance(self)));
total_balance(self)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#[allow(unused_const)]
module sui_system_specs::validator;

#[spec_only]
use sui_system::staking_pool::{
PoolTokenExchangeRate,
};

#[spec_only]
use sui_system::validator::{
Validator,
ValidatorMetadata,
is_preactive,
is_duplicate,
validate_metadata,
validate_metadata_bcs,
staking_pool_id,
pool_token_exchange_rate_at_epoch,
pool_activation_epoch,
};
#[spec_only]
use sui_system::validator_cap::{Self, ValidatorOperationCap};

#[spec_only]
use prover::prover::requires;

#[spec_only]
public fun pool_activation_epoch_is_positive(validator: &Validator): bool {
let epoch_opt = pool_activation_epoch(validator);
epoch_opt.is_some() &&
*epoch_opt.borrow() > 0
}

#[spec(prove, no_opaque, target = sui_system::validator::is_preactive)]
public fun is_preactive_spec(self: &Validator): bool {
is_preactive(self)
}

#[spec(prove, target = sui_system::validator::pool_token_exchange_rate_at_epoch)]
public fun pool_token_exchange_rate_at_epoch_spec(self: &Validator, epoch: u64): PoolTokenExchangeRate {
requires(!is_preactive(self));
requires(pool_activation_epoch_is_positive(self));
pool_token_exchange_rate_at_epoch(self, epoch)
}

#[spec(prove, no_opaque, target = sui_system::validator::staking_pool_id)]
public fun staking_pool_id_spec(self: &Validator): ID {
staking_pool_id(self)
}

#[spec(prove, target = sui_system::validator::is_duplicate)]
public fun is_duplicate_spec(self: &Validator, other: &Validator): bool {
is_duplicate(self, other)
}

#[spec(prove, target = sui_system::validator::validate_metadata)]
public fun validate_metadata_spec(metadata: &ValidatorMetadata) {
validate_metadata(metadata);
}

// "aborts if metadata is not valid" -- how to capture?
#[spec(target = sui_system::validator::validate_metadata_bcs)]
public fun validate_metadata_bcs_spec(metadata: vector<u8>) {
validate_metadata_bcs(metadata);
}
17 changes: 8 additions & 9 deletions crates/sui-framework/packages/sui-system/Move.lock
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
# @generated by Move, please check-in and do not edit manually.

[move]
version = 1
version = 3
manifest_digest = "68AEB9354EE1D616F6D2293EC721FE3D7E810FEC4FE34197676ECFA3DA72CAE3"
deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600"

dependencies = [
{ name = "MoveStdlib" },
{ name = "Sui" },
{ id = "MoveStdlib", name = "MoveStdlib" },
{ id = "Sui", name = "Sui" },
]

[[move.package]]
name = "MoveStdlib"
id = "MoveStdlib"
source = { local = "../move-stdlib" }

[[move.package]]
name = "Sui"
id = "Sui"
source = { local = "../sui-framework" }

dependencies = [
{ name = "MoveStdlib" },
{ id = "MoveStdlib", name = "MoveStdlib" },
]

[move.toolchain-version]
compiler-version = "1.22.0"
edition = "legacy"
compiler-version = "1.54.0"
edition = "2024.beta"
flavor = "sui"
Loading
Loading