Skip to content

Commit

Permalink
implement rust logics and specs
Browse files Browse the repository at this point in the history
  • Loading branch information
runtian-zhou committed Nov 27, 2024
1 parent 246b08a commit 2a56afe
Show file tree
Hide file tree
Showing 52 changed files with 664 additions and 211 deletions.
2 changes: 2 additions & 0 deletions .github/actions/rust-targeted-unit-tests/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ runs:
shell: bash
env:
INDEXER_DATABASE_URL: postgresql://postgres@localhost/postgres
MOVE_COMPILER_V2: true
MOVE_LANGUAGE_V2: true
RUST_MIN_STACK: "4297152"
MVP_TEST_ON_CI: "true"
SOLC_EXE: /home/runner/bin/solc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ crate::gas_schedule::macros::define_gas_parameters!(
[account_create_address_base: InternalGas, "account.create_address.base", 1102],
[account_create_signer_base: InternalGas, "account.create_signer.base", 1102],

// Permissioned signer gas parameters_
[permission_address_base: InternalGas, "permissioned_signer.permission_address.base", 1102],
[is_permissioned_signer_base: InternalGas, "permissioned_signer.is_permissioned_signer.base", 1102],
[signer_from_permissioned_handle_base: InternalGas, "permissioned_signer.signer_from_permissioned_handle.base", 1102],

// BN254 algebra gas parameters begin.
// Generated at time 1701559125.5498126 by `scripts/algebra-gas/update_bn254_algebra_gas_params.py` with gas_per_ns=209.10511688369482.
[algebra_ark_bn254_fq12_add: InternalGas, { 12.. => "algebra.ark_bn254_fq12_add" }, 809],
Expand Down
8 changes: 8 additions & 0 deletions aptos-move/e2e-move-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ pub(crate) fn build_package(
let mut options = options;
if get_move_compiler_v2_from_env() {
options.compiler_version = Some(CompilerVersion::latest_stable());
options.language_version = options
.compiler_version
.map(|v| v.infer_stable_language_version());
}
BuiltPackage::build(package_path.to_owned(), options)
}
Expand All @@ -61,5 +64,10 @@ pub(crate) fn build_package_with_compiler_version(
let mut options = options;
options.language_version = Some(compiler_version.infer_stable_language_version());
options.compiler_version = Some(compiler_version);
if options.compiler_version.unwrap() != CompilerVersion::V1 {
options.language_version = Some(move_model::metadata::LanguageVersion::latest_stable());
} else {
options.language_version = Some(move_model::metadata::LanguageVersion::V1);
}
BuiltPackage::build(package_path.to_owned(), options)
}
10 changes: 7 additions & 3 deletions aptos-move/e2e-move-tests/src/tests/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use aptos_types::{
transaction::{EntryFunction, TransactionPayload},
};
use aptos_vm_environment::prod_configs::set_paranoid_type_checks;
use move_core_types::{identifier::Identifier, language_storage::ModuleId};
use move_core_types::{identifier::Identifier, language_storage::ModuleId, value::MoveValue};
use rand::{rngs::StdRng, SeedableRng};
use sha3::{Digest, Sha3_512};
use std::path::Path;
Expand All @@ -57,7 +57,9 @@ fn test_modify_gas_schedule_check_hash() {
"set_for_next_epoch_check_hash",
vec![],
vec![
bcs::to_bytes(&CORE_CODE_ADDRESS).unwrap(),
MoveValue::Signer(CORE_CODE_ADDRESS)
.simple_serialize()
.unwrap(),
bcs::to_bytes(&old_hash).unwrap(),
bcs::to_bytes(&bcs::to_bytes(&gas_schedule).unwrap()).unwrap(),
],
Expand All @@ -66,7 +68,9 @@ fn test_modify_gas_schedule_check_hash() {
harness
.executor
.exec("reconfiguration_with_dkg", "finish", vec![], vec![
bcs::to_bytes(&CORE_CODE_ADDRESS).unwrap(),
MoveValue::Signer(CORE_CODE_ADDRESS)
.simple_serialize()
.unwrap(),
]);

let (_, gas_params) = harness.get_gas_params();
Expand Down
2 changes: 1 addition & 1 deletion aptos-move/e2e-move-tests/src/tests/move_feature_gating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use move_core_types::vm_status::StatusCode;
use rstest::rstest;

#[rstest(enabled, disabled,
case(vec![], vec![FeatureFlag::ENABLE_ENUM_TYPES]),
// case(vec![], vec![FeatureFlag::ENABLE_ENUM_TYPES]),
case(vec![FeatureFlag::ENABLE_ENUM_TYPES], vec![]),
)]
fn enum_types(enabled: Vec<FeatureFlag>, disabled: Vec<FeatureFlag>) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "test"
version = "0.0.0"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
script {
fun main(s1: &signer, u: u64, s2: &signer) {}
}
43 changes: 41 additions & 2 deletions aptos-move/e2e-move-tests/src/tests/scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use aptos_language_e2e_tests::account::TransactionBuilder;
use aptos_types::{
account_address::AccountAddress,
on_chain_config::FeatureFlag,
transaction::{Script, TransactionArgument},
transaction::{Script, TransactionArgument, TransactionStatus},
};
use move_core_types::language_storage::TypeTag;
use move_core_types::{language_storage::TypeTag, value::MoveValue};

#[test]
fn test_script_with_object_parameter() {
Expand Down Expand Up @@ -146,6 +146,45 @@ fn test_script_with_type_parameter() {
assert_success!(status);
}

#[test]
fn test_script_with_signer_parameter() {
let mut h = MoveHarness::new();

let alice = h.new_account_at(AccountAddress::from_hex_literal("0xa11ce").unwrap());

let package = build_package(
common::test_dir_path("script_with_signer.data/pack"),
aptos_framework::BuildOptions::default(),
)
.expect("building package must succeed");

let code = package.extract_script_code().into_iter().next().unwrap();

let txn = TransactionBuilder::new(alice.clone())
.script(Script::new(code, vec![], vec![
TransactionArgument::U64(0),
TransactionArgument::Serialized(
MoveValue::Signer(*alice.address())
.simple_serialize()
.unwrap(),
),
]))
.sequence_number(10)
.max_gas_amount(1_000_000)
.gas_unit_price(1)
.sign();

let status = h.run(txn);
assert_eq!(
status,
TransactionStatus::Keep(
aptos_types::transaction::ExecutionStatus::MiscellaneousError(Some(
aptos_types::vm_status::StatusCode::INVALID_MAIN_FUNCTION_SIGNATURE
))
)
);
}

#[test]
fn test_two_to_two_transfer() {
let mut h = MoveHarness::new();
Expand Down
17 changes: 14 additions & 3 deletions aptos-move/e2e-tests/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ use move_core_types::{
identifier::Identifier,
language_storage::{ModuleId, StructTag, TypeTag},
move_resource::{MoveResource, MoveStructType},
value::MoveValue,
};
use move_vm_runtime::{
module_traversal::{TraversalContext, TraversalStorage},
Expand Down Expand Up @@ -1044,13 +1045,23 @@ impl FakeExecutor {
let mut arg = args.clone();
match &dynamic_args {
ExecFuncTimerDynamicArgs::DistinctSigners => {
arg.insert(0, bcs::to_bytes(&extra_accounts.pop().unwrap()).unwrap());
arg.insert(
0,
MoveValue::Signer(extra_accounts.pop().unwrap())
.simple_serialize()
.unwrap(),
);
},
ExecFuncTimerDynamicArgs::DistinctSignersAndFixed(signers) => {
for signer in signers.iter().rev() {
arg.insert(0, bcs::to_bytes(&signer).unwrap());
arg.insert(0, MoveValue::Signer(*signer).simple_serialize().unwrap());
}
arg.insert(0, bcs::to_bytes(&extra_accounts.pop().unwrap()).unwrap());
arg.insert(
0,
MoveValue::Signer(extra_accounts.pop().unwrap())
.simple_serialize()
.unwrap(),
);
},
_ => {},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ Returns the inner entry function payload of the multisig payload.


<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> [abstract] <b>false</b>;
<b>ensures</b> [abstract] result == <a href="transaction_context.md#0x1_transaction_context_spec_generate_unique_address">spec_generate_unique_address</a>();
</code></pre>

Expand All @@ -1055,6 +1056,7 @@ Returns the inner entry function payload of the multisig payload.


<pre><code><b>pragma</b> opaque;
<b>aborts_if</b> [abstract] <b>false</b>;
// This enforces <a id="high-level-req-3" href="#high-level-req">high-level requirement 3</a>:
<b>ensures</b> [abstract] result == <a href="transaction_context.md#0x1_transaction_context_spec_generate_unique_address">spec_generate_unique_address</a>();
</code></pre>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
spec aptos_framework::permissioned_signer {

spec module {
pragma verify = false;
axiom forall a: GrantedPermissionHandles:
(
forall i in 0..len(a.active_handles):
forall j in 0..len(a.active_handles):
i != j ==>
a.active_handles[i] != a.active_handles[j]
);
}

spec fun spec_is_permissioned_signer(s: signer): bool;

spec is_permissioned_signer(s: &signer): bool {
pragma opaque;
aborts_if [abstract] false;
ensures [abstract] result == spec_is_permissioned_signer(s);
}

spec fun spec_permission_address(s: signer): address;

spec permission_address(permissioned: &signer): address {
pragma opaque;
aborts_if [abstract]!spec_is_permissioned_signer(permissioned);
ensures [abstract] result == spec_permission_address(permissioned);
}

spec fun spec_signer_from_permissioned_handle_impl(
master_account_addr: address, permissions_storage_addr: address
): signer;

spec signer_from_permissioned_handle_impl(
master_account_addr: address, permissions_storage_addr: address
): signer {
pragma opaque;
ensures [abstract] result
== spec_signer_from_permissioned_handle_impl(
master_account_addr, permissions_storage_addr
);
}

spec create_permissioned_handle(master: &signer): PermissionedHandle {
use aptos_framework::transaction_context;
pragma opaque;
aborts_if [abstract] spec_is_permissioned_signer(master);
let permissions_storage_addr = transaction_context::spec_generate_unique_address();
modifies global<PermissionStorage>(permissions_storage_addr);
let master_account_addr = signer::address_of(master);
ensures result.master_account_addr == master_account_addr;
ensures result.permissions_storage_addr == permissions_storage_addr;
}

spec create_storable_permissioned_handle(master: &signer, expiration_time: u64): StorablePermissionedHandle {
use aptos_framework::transaction_context;
pragma opaque;
aborts_if [abstract] spec_is_permissioned_signer(master);
let permissions_storage_addr = transaction_context::spec_generate_unique_address();
modifies global<PermissionStorage>(permissions_storage_addr);
let master_account_addr = signer::address_of(master);
modifies global<GrantedPermissionHandles>(master_account_addr);
ensures result.master_account_addr == master_account_addr;
ensures result.permissions_storage_addr == permissions_storage_addr;
ensures result.expiration_time == expiration_time;
ensures vector::spec_contains(
global<GrantedPermissionHandles>(master_account_addr).active_handles,
permissions_storage_addr
);
ensures exists<GrantedPermissionHandles>(master_account_addr);
}

spec destroy_permissioned_handle(p: PermissionedHandle) {
ensures !exists<PermissionStorage>(p.permissions_storage_addr);
}

spec destroy_storable_permissioned_handle(p: StorablePermissionedHandle) {
ensures !exists<PermissionStorage>(p.permissions_storage_addr);
let post granted_permissions = global<GrantedPermissionHandles>(
p.master_account_addr
);
// ensures [abstract] !vector::spec_contains(granted_permissions.active_handles, p.permissions_storage_addr);
}

spec revoke_permission_storage_address(s: &signer, permissions_storage_addr: address) {
// aborts_if spec_is_permissioned_signer(s);
}

spec authorize<PermKey: copy + drop + store>(
master: &signer, permissioned: &signer, capacity: u256, perm: PermKey
) {

// use aptos_std::type_info;
// use std::bcs;
pragma aborts_if_is_partial;
aborts_if !spec_is_permissioned_signer(permissioned);
aborts_if spec_is_permissioned_signer(master);
aborts_if signer::address_of(permissioned) != signer::address_of(master);
ensures exists<PermissionStorage>(
spec_permission_address(permissioned)
);
// let perms = global<PermissionStorage>(permission_signer_addr).perms;
// let post post_perms = global<PermissionStorage>(permission_signer_addr).perms;
// let key = Any {
// type_name: type_info::type_name<SmartTable<Any, u256>>(),
// data: bcs::serialize(perm)
// };
// ensures smart_table::spec_contains(perms, key) ==>
// smart_table::spec_get(post_perms, key) == old(smart_table::spec_get(perms, key)) + capacity;
// ensures !smart_table::spec_contains(perms, key) ==>
// smart_table::spec_get(post_perms, key) == capacity;
}

spec check_permission_exists<PermKey: copy + drop + store>(s: &signer, perm: PermKey): bool {
pragma opaque;
aborts_if false;
ensures result == spec_check_permission_exists(s, perm);
}

spec fun spec_check_permission_exists<PermKey: copy + drop + store>(s: signer, perm: PermKey): bool {
use aptos_std::type_info;
use std::bcs;
let addr = spec_permission_address(s);
let key = Any {
type_name: type_info::type_name<PermKey>(),
data: bcs::serialize(perm)
};
if (!spec_is_permissioned_signer(s)) { true }
else if (!exists<PermissionStorage>(addr)) { false }
else {
simple_map::spec_contains_key(global<PermissionStorage>(addr).perms, key)
}
}

spec check_permission_capacity_above<PermKey: copy + drop + store>(
s: &signer, threshold: u256, perm: PermKey
): bool {
use aptos_std::type_info;
use std::bcs;
let permissioned_signer_addr = spec_permission_address(s);
ensures !spec_is_permissioned_signer(s) ==> result == true;
ensures (
spec_is_permissioned_signer(s)
&& !exists<PermissionStorage>(permissioned_signer_addr)
) ==> result == false;
let key = Any {
type_name: type_info::type_name<SimpleMap<Any, u256>>(),
data: bcs::serialize(perm)
};
// ensures (spec_is_permissioned_signer(s) && exists<PermissionStorage>(permissioned_signer_addr) && !smart_table::spec_contains(global<PermissionStorage>(permissioned_signer_addr).perms, key)) ==>
// result == false;
// ensures (spec_is_permissioned_signer(s) && exists<PermissionStorage>(permissioned_signer_addr) && smart_table::spec_contains(global<PermissionStorage>(permissioned_signer_addr).perms, key)) ==>
// result == (smart_table::spec_get(global<PermissionStorage>(permissioned_signer_addr).perms, key) > threshold);
}

spec check_permission_consume<PermKey: copy + drop + store>(
s: &signer, threshold: u256, perm: PermKey
): bool {
let permissioned_signer_addr = spec_permission_address(s);
ensures !spec_is_permissioned_signer(s) ==> result == true;
ensures (
spec_is_permissioned_signer(s)
&& !exists<PermissionStorage>(permissioned_signer_addr)
) ==> result == false;

}

spec capacity<PermKey: copy + drop + store>(s: &signer, perm: PermKey): Option<u256> {
// let permissioned_signer_addr = signer::address_of(spec_permission_address(s));
// ensures !exists<PermissionStorage>(permissioned_signer_addr) ==>
// option::is_none(result);
}

spec consume_permission<PermKey: copy + drop + store>(
perm: &mut Permission<PermKey>, weight: u256, perm_key: PermKey
): bool {
// ensures perm.key != perm_key ==> result == false;
// ensures perm.key == perm_key && old(perm.capacity) < weight ==> result == false;
// ensures perm.key == perm_key
// && perm.capacity >= weight ==>
// (perm.capacity == old(perm.capacity) - weight
// && result == true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,13 @@ spec aptos_framework::transaction_context {
}
spec generate_unique_address(): address {
pragma opaque;
aborts_if [abstract] false;
ensures [abstract] result == spec_generate_unique_address();
}
spec fun spec_generate_unique_address(): address;
spec generate_auid_address(): address {
pragma opaque;
aborts_if [abstract] false;
// property 3: Generating the unique address should return a vector with 32 bytes, if the auid feature flag is enabled.
/// [high-level-req-3]
ensures [abstract] result == spec_generate_unique_address();
Expand Down
Loading

0 comments on commit 2a56afe

Please sign in to comment.