Skip to content

Commit f892ca9

Browse files
committed
TMP
1 parent fb57ead commit f892ca9

File tree

6 files changed

+303
-9
lines changed

6 files changed

+303
-9
lines changed

aptos-move/framework/aptos-framework/doc/account.md

Lines changed: 124 additions & 5 deletions
Large diffs are not rendered by default.

aptos-move/framework/aptos-framework/sources/account.move

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module aptos_framework::account {
99
use aptos_framework::create_signer::create_signer;
1010
use aptos_framework::event::{Self, EventHandle};
1111
use aptos_framework::guid;
12+
use aptos_framework::permissioned_signer;
1213
use aptos_framework::system_addresses;
1314
use aptos_std::ed25519;
1415
use aptos_std::from_bcs;
@@ -179,6 +180,8 @@ module aptos_framework::account {
179180
const ENEW_AUTH_KEY_ALREADY_MAPPED: u64 = 21;
180181
/// The current authentication key and the new authentication key are the same
181182
const ENEW_AUTH_KEY_SAME_AS_CURRENT: u64 = 22;
183+
/// Current permissioned signer cannot perform the privilaged operations.
184+
const ENO_ACCOUNT_PERMISSION: u64 = 23;
182185

183186
/// Explicitly separate the GUID space between Object and Account to prevent accidental overlap.
184187
const MAX_GUID_CREATION_NUM: u64 = 0x4000000000000;
@@ -187,6 +190,43 @@ module aptos_framework::account {
187190
/// Create signer for testing, independently of an Aptos-style `Account`.
188191
public fun create_signer_for_test(addr: address): signer { create_signer(addr) }
189192

193+
enum AccountPermission has copy, drop, store {
194+
/// Permission to rotate a key.
195+
KeyRotation,
196+
/// Permission to offer another address to act like your address
197+
Offering,
198+
}
199+
200+
/// Permissions
201+
///
202+
inline fun check_rotation_permission(s: &signer) {
203+
assert!(
204+
permissioned_signer::check_permission_exists(s, AccountPermission::KeyRotation {}),
205+
error::permission_denied(ENO_ACCOUNT_PERMISSION),
206+
);
207+
}
208+
209+
inline fun check_offering_permission(s: &signer) {
210+
assert!(
211+
permissioned_signer::check_permission_exists(s, AccountPermission::Offering {}),
212+
error::permission_denied(ENO_ACCOUNT_PERMISSION),
213+
);
214+
}
215+
216+
/// Grant permission to perform key rotations on behalf of the master signer.
217+
///
218+
/// This is **extremely dangerous** and should be granted only when it's absolutely needed.
219+
public fun grant_key_rotation_permission(master: &signer, permissioned_signer: &signer) {
220+
permissioned_signer::authorize_unlimited(master, permissioned_signer, AccountPermission::KeyRotation {})
221+
}
222+
223+
/// Grant permission to use offered address's signer on behalf of the master signer.
224+
///
225+
/// This is **extremely dangerous** and should be granted only when it's absolutely needed.
226+
public fun grant_key_offering_permission(master: &signer, permissioned_signer: &signer) {
227+
permissioned_signer::authorize_unlimited(master, permissioned_signer, AccountPermission::Offering {})
228+
}
229+
190230
/// Only called during genesis to initialize system resources for this module.
191231
public(friend) fun initialize(aptos_framework: &signer) {
192232
system_addresses::assert_aptos_framework(aptos_framework);
@@ -302,6 +342,7 @@ module aptos_framework::account {
302342
vector::length(&new_auth_key) == 32,
303343
error::invalid_argument(EMALFORMED_AUTHENTICATION_KEY)
304344
);
345+
check_rotation_permission(account);
305346
let account_resource = borrow_global_mut<Account>(addr);
306347
account_resource.authentication_key = new_auth_key;
307348
}
@@ -357,6 +398,7 @@ module aptos_framework::account {
357398
) acquires Account, OriginatingAddress {
358399
let addr = signer::address_of(account);
359400
assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST));
401+
check_rotation_permission(account);
360402
let account_resource = borrow_global_mut<Account>(addr);
361403

362404
// Verify the given `from_public_key_bytes` matches this account's current authentication key.
@@ -412,6 +454,7 @@ module aptos_framework::account {
412454
new_public_key_bytes: vector<u8>,
413455
cap_update_table: vector<u8>
414456
) acquires Account, OriginatingAddress {
457+
check_rotation_permission(delegate_signer);
415458
assert!(exists_at(rotation_cap_offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST));
416459

417460
// Check that there exists a rotation capability offer at the offerer's account resource for the delegate.
@@ -471,6 +514,7 @@ module aptos_framework::account {
471514
account_public_key_bytes: vector<u8>,
472515
recipient_address: address,
473516
) acquires Account {
517+
check_rotation_permission(account);
474518
let addr = signer::address_of(account);
475519
assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
476520

@@ -569,6 +613,7 @@ module aptos_framework::account {
569613
/// Revoke the rotation capability offer given to `to_be_revoked_recipient_address` from `account`
570614
public entry fun revoke_rotation_capability(account: &signer, to_be_revoked_address: address) acquires Account {
571615
assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
616+
check_rotation_permission(account);
572617
let addr = signer::address_of(account);
573618
let account_resource = borrow_global<Account>(addr);
574619
assert!(
@@ -580,6 +625,7 @@ module aptos_framework::account {
580625

581626
/// Revoke any rotation capability offer in the specified account.
582627
public entry fun revoke_any_rotation_capability(account: &signer) acquires Account {
628+
check_rotation_permission(account);
583629
let account_resource = borrow_global_mut<Account>(signer::address_of(account));
584630
option::extract(&mut account_resource.rotation_capability_offer.for);
585631
}
@@ -600,6 +646,7 @@ module aptos_framework::account {
600646
account_public_key_bytes: vector<u8>,
601647
recipient_address: address
602648
) acquires Account {
649+
check_offering_permission(account);
603650
let source_address = signer::address_of(account);
604651
assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
605652

@@ -639,6 +686,7 @@ module aptos_framework::account {
639686
/// has a signer capability offer from `account` but will be revoked in this function).
640687
public entry fun revoke_signer_capability(account: &signer, to_be_revoked_address: address) acquires Account {
641688
assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
689+
check_offering_permission(account);
642690
let addr = signer::address_of(account);
643691
let account_resource = borrow_global<Account>(addr);
644692
assert!(
@@ -650,13 +698,15 @@ module aptos_framework::account {
650698

651699
/// Revoke any signer capability offer in the specified account.
652700
public entry fun revoke_any_signer_capability(account: &signer) acquires Account {
701+
check_offering_permission(account);
653702
let account_resource = borrow_global_mut<Account>(signer::address_of(account));
654703
option::extract(&mut account_resource.signer_capability_offer.for);
655704
}
656705

657706
/// Return an authorized signer of the offerer, if there's an existing signer capability offer for `account`
658707
/// at the offerer's address.
659708
public fun create_authorized_signer(account: &signer, offerer_address: address): signer acquires Account {
709+
check_offering_permission(account);
660710
assert!(exists_at(offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST));
661711

662712
// Check if there's an existing signer capability offer from the offerer.
@@ -1202,6 +1252,123 @@ module aptos_framework::account {
12021252
assert!(signer::address_of(&signer) == signer::address_of(&alice), 0);
12031253
}
12041254

1255+
#[test(bob = @0x345)]
1256+
public entry fun test_valid_check_signer_capability_and_create_authorized_signer_with_permission(bob: signer) acquires Account {
1257+
let (alice_sk, alice_pk) = ed25519::generate_keys();
1258+
let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk);
1259+
let alice = create_account_from_ed25519_public_key(alice_pk_bytes);
1260+
let alice_addr = signer::address_of(&alice);
1261+
1262+
let bob_addr = signer::address_of(&bob);
1263+
create_account(bob_addr);
1264+
1265+
let challenge = SignerCapabilityOfferProofChallengeV2 {
1266+
sequence_number: borrow_global<Account>(alice_addr).sequence_number,
1267+
source_address: alice_addr,
1268+
recipient_address: bob_addr,
1269+
};
1270+
1271+
let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge);
1272+
1273+
let alice_permission_handle = permissioned_signer::create_permissioned_handle(&alice);
1274+
let alice_permission_signer = permissioned_signer::signer_from_permissioned_handle(&alice_permission_handle);
1275+
1276+
grant_key_offering_permission(&alice, &alice_permission_signer);
1277+
1278+
offer_signer_capability(
1279+
&alice_permission_signer,
1280+
ed25519::signature_to_bytes(&alice_signer_capability_offer_sig),
1281+
0,
1282+
alice_pk_bytes,
1283+
bob_addr
1284+
);
1285+
1286+
assert!(option::contains(&borrow_global<Account>(alice_addr).signer_capability_offer.for, &bob_addr), 0);
1287+
1288+
let signer = create_authorized_signer(&bob, alice_addr);
1289+
assert!(signer::address_of(&signer) == signer::address_of(&alice), 0);
1290+
1291+
permissioned_signer::destroy_permissioned_handle(alice_permission_handle);
1292+
}
1293+
1294+
#[test(bob = @0x345)]
1295+
#[expected_failure(abort_code = 0x50017, location = Self)]
1296+
public entry fun test_valid_check_signer_capability_and_create_authorized_signer_with_no_permission(bob: signer) acquires Account {
1297+
let (alice_sk, alice_pk) = ed25519::generate_keys();
1298+
let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk);
1299+
let alice = create_account_from_ed25519_public_key(alice_pk_bytes);
1300+
let alice_addr = signer::address_of(&alice);
1301+
1302+
let bob_addr = signer::address_of(&bob);
1303+
create_account(bob_addr);
1304+
1305+
let challenge = SignerCapabilityOfferProofChallengeV2 {
1306+
sequence_number: borrow_global<Account>(alice_addr).sequence_number,
1307+
source_address: alice_addr,
1308+
recipient_address: bob_addr,
1309+
};
1310+
1311+
let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge);
1312+
1313+
let alice_permission_handle = permissioned_signer::create_permissioned_handle(&alice);
1314+
let alice_permission_signer = permissioned_signer::signer_from_permissioned_handle(&alice_permission_handle);
1315+
1316+
offer_signer_capability(
1317+
&alice_permission_signer,
1318+
ed25519::signature_to_bytes(&alice_signer_capability_offer_sig),
1319+
0,
1320+
alice_pk_bytes,
1321+
bob_addr
1322+
);
1323+
1324+
assert!(option::contains(&borrow_global<Account>(alice_addr).signer_capability_offer.for, &bob_addr), 0);
1325+
1326+
let signer = create_authorized_signer(&bob, alice_addr);
1327+
assert!(signer::address_of(&signer) == signer::address_of(&alice), 0);
1328+
1329+
permissioned_signer::destroy_permissioned_handle(alice_permission_handle);
1330+
}
1331+
1332+
#[test(bob = @0x345)]
1333+
#[expected_failure(abort_code = 0x50017, location = Self)]
1334+
public entry fun test_valid_check_signer_capability_and_create_authorized_signer_with_wrong_permission(bob: signer) acquires Account {
1335+
let (alice_sk, alice_pk) = ed25519::generate_keys();
1336+
let alice_pk_bytes = ed25519::validated_public_key_to_bytes(&alice_pk);
1337+
let alice = create_account_from_ed25519_public_key(alice_pk_bytes);
1338+
let alice_addr = signer::address_of(&alice);
1339+
1340+
let bob_addr = signer::address_of(&bob);
1341+
create_account(bob_addr);
1342+
1343+
let challenge = SignerCapabilityOfferProofChallengeV2 {
1344+
sequence_number: borrow_global<Account>(alice_addr).sequence_number,
1345+
source_address: alice_addr,
1346+
recipient_address: bob_addr,
1347+
};
1348+
1349+
let alice_signer_capability_offer_sig = ed25519::sign_struct(&alice_sk, challenge);
1350+
1351+
let alice_permission_handle = permissioned_signer::create_permissioned_handle(&alice);
1352+
let alice_permission_signer = permissioned_signer::signer_from_permissioned_handle(&alice_permission_handle);
1353+
1354+
grant_key_rotation_permission(&alice, &alice_permission_signer);
1355+
1356+
offer_signer_capability(
1357+
&alice_permission_signer,
1358+
ed25519::signature_to_bytes(&alice_signer_capability_offer_sig),
1359+
0,
1360+
alice_pk_bytes,
1361+
bob_addr
1362+
);
1363+
1364+
assert!(option::contains(&borrow_global<Account>(alice_addr).signer_capability_offer.for, &bob_addr), 0);
1365+
1366+
let signer = create_authorized_signer(&bob, alice_addr);
1367+
assert!(signer::address_of(&signer) == signer::address_of(&alice), 0);
1368+
1369+
permissioned_signer::destroy_permissioned_handle(alice_permission_handle);
1370+
}
1371+
12051372
#[test(bob = @0x345)]
12061373
public entry fun test_get_signer_cap_and_is_signer_cap(bob: signer) acquires Account {
12071374
let (alice_sk, alice_pk) = ed25519::generate_keys();

aptos-move/framework/aptos-framework/sources/account.spec.move

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ spec aptos_framework::account {
105105
///
106106

107107
spec module {
108-
pragma verify = true;
109-
pragma aborts_if_is_strict;
108+
pragma verify = false;
109+
pragma aborts_if_is_partial;
110110
}
111111

112112
/// Only the address `@aptos_framework` can call.
@@ -390,7 +390,6 @@ spec aptos_framework::account {
390390
source_address,
391391
recipient_address,
392392
};
393-
394393
aborts_if !exists<chain_id::ChainId>(@aptos_framework);
395394
aborts_if !exists<Account>(recipient_address);
396395
aborts_if !exists<Account>(source_address);

aptos-move/framework/aptos-framework/sources/multisig_account.spec.move

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ spec aptos_framework::multisig_account {
207207
}
208208

209209
spec get_next_multisig_account_address(creator: address): address {
210+
pragma aborts_if_is_partial;
210211
aborts_if !exists<account::Account>(creator);
211212
let owner_nonce = global<account::Account>(creator).sequence_number;
212213
}

aptos-move/framework/aptos-framework/sources/resource_account.spec.move

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ spec aptos_framework::resource_account {
6060
///
6161
spec module {
6262
pragma verify = true;
63-
pragma aborts_if_is_strict;
63+
pragma aborts_if_is_partial;
6464
}
6565

6666
spec create_resource_account(
@@ -116,6 +116,8 @@ spec aptos_framework::resource_account {
116116
resource_signer_cap: account::SignerCapability,
117117
optional_auth_key: vector<u8>,
118118
) {
119+
pragma aborts_if_is_partial;
120+
119121
let resource_addr = signer::address_of(resource);
120122
/// [high-level-req-1]
121123
include RotateAccountAuthenticationKeyAndStoreCapabilityAbortsIf;
@@ -172,6 +174,8 @@ spec aptos_framework::resource_account {
172174
resource: &signer,
173175
source_addr: address,
174176
) : account::SignerCapability {
177+
pragma aborts_if_is_partial;
178+
175179
/// [high-level-req-6]
176180
aborts_if !exists<Container>(source_addr);
177181
let resource_addr = signer::address_of(resource);

aptos-move/framework/aptos-framework/sources/staking_contract.spec.move

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ spec aptos_framework::staking_contract {
135135
ensures result == spec_staking_contract_exists(staker, operator);
136136
}
137137

138+
spec get_expected_stake_pool_address {
139+
pragma aborts_if_is_partial;
140+
}
141+
138142
spec fun spec_staking_contract_exists(staker: address, operator: address): bool {
139143
if (!exists<Store>(staker)) {
140144
false

0 commit comments

Comments
 (0)