Skip to content

Commit 21ec1f2

Browse files
committed
feat: DECOMMISSION_CORE_RESOURCES feature flag
1 parent 0357005 commit 21ec1f2

File tree

5 files changed

+195
-7
lines changed

5 files changed

+195
-7
lines changed

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

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- [Function `create_account_if_does_not_exist`](#0x1_account_create_account_if_does_not_exist)
2424
- [Function `create_account`](#0x1_account_create_account)
2525
- [Function `create_account_unchecked`](#0x1_account_create_account_unchecked)
26+
- [Function `destroy_account_from`](#0x1_account_destroy_account_from)
2627
- [Function `exists_at`](#0x1_account_exists_at)
2728
- [Function `get_guid_next_creation_num`](#0x1_account_get_guid_next_creation_num)
2829
- [Function `get_sequence_number`](#0x1_account_get_sequence_number)
@@ -616,6 +617,16 @@ This V2 struct adds the <code><a href="chain_id.md#0x1_chain_id">chain_id</a></c
616617

617618

618619

620+
<a id="0x1_account_DECOMMISSION_CORE_RESOURCES"></a>
621+
622+
Feature flag for decommissioning core resources.
623+
624+
625+
<pre><code><b>const</b> <a href="account.md#0x1_account_DECOMMISSION_CORE_RESOURCES">DECOMMISSION_CORE_RESOURCES</a>: u64 = 222;
626+
</code></pre>
627+
628+
629+
619630
<a id="0x1_account_DERIVE_RESOURCE_ACCOUNT_SCHEME"></a>
620631

621632
Scheme identifier used when hashing an account's address together with a seed to derive the address (not the
@@ -943,7 +954,16 @@ is returned. This way, the caller of this function can publish additional resour
943954
// there cannot be an <a href="account.md#0x1_account_Account">Account</a> resource under new_addr already.
944955
<b>assert</b>!(!<b>exists</b>&lt;<a href="account.md#0x1_account_Account">Account</a>&gt;(new_address), <a href="../../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_already_exists">error::already_exists</a>(<a href="account.md#0x1_account_EACCOUNT_ALREADY_EXISTS">EACCOUNT_ALREADY_EXISTS</a>));
945956

946-
// NOTE: @core_resources gets created via a `create_account` call, so we do not <b>include</b> it below.
957+
// Check <b>if</b> the feature flag for decommissioning core resources is enabled.
958+
<b>if</b> (get_decommission_core_resources_enabled()) {
959+
// Assert separately for the core resources <b>address</b> <b>if</b> the feature flag is enabled.
960+
<b>assert</b>!(
961+
new_address != @0xa550c18,
962+
<a href="../../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="account.md#0x1_account_ECANNOT_RESERVED_ADDRESS">ECANNOT_RESERVED_ADDRESS</a>)
963+
);
964+
};
965+
966+
// Assert for other reserved addresses.
947967
<b>assert</b>!(
948968
new_address != @vm_reserved && new_address != @aptos_framework && new_address != @aptos_token,
949969
<a href="../../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="account.md#0x1_account_ECANNOT_RESERVED_ADDRESS">ECANNOT_RESERVED_ADDRESS</a>)
@@ -1007,6 +1027,48 @@ is returned. This way, the caller of this function can publish additional resour
10071027

10081028

10091029

1030+
</details>
1031+
1032+
<a id="0x1_account_destroy_account_from"></a>
1033+
1034+
## Function `destroy_account_from`
1035+
1036+
Destroy the Account resource from a given account.
1037+
Used to destroy the core resources account on mainnet.
1038+
1039+
1040+
<pre><code><b>public</b> <b>fun</b> <a href="account.md#0x1_account_destroy_account_from">destroy_account_from</a>(<a href="account.md#0x1_account">account</a>: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, from: <b>address</b>)
1041+
</code></pre>
1042+
1043+
1044+
1045+
<details>
1046+
<summary>Implementation</summary>
1047+
1048+
1049+
<pre><code><b>public</b> <b>fun</b> <a href="account.md#0x1_account_destroy_account_from">destroy_account_from</a>(<a href="account.md#0x1_account">account</a>: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, from: <b>address</b>) <b>acquires</b> <a href="account.md#0x1_account_Account">Account</a> {
1050+
<a href="system_addresses.md#0x1_system_addresses_assert_aptos_framework">system_addresses::assert_aptos_framework</a>(<a href="account.md#0x1_account">account</a>);
1051+
1052+
<b>let</b> <a href="account.md#0x1_account_Account">Account</a> {
1053+
authentication_key: _,
1054+
sequence_number: _,
1055+
guid_creation_num: _,
1056+
coin_register_events,
1057+
key_rotation_events,
1058+
rotation_capability_offer,
1059+
signer_capability_offer,
1060+
} = <b>move_from</b>&lt;<a href="account.md#0x1_account_Account">Account</a>&gt;(from);
1061+
1062+
<a href="event.md#0x1_event_destroy_handle">event::destroy_handle</a>&lt;<a href="account.md#0x1_account_CoinRegisterEvent">CoinRegisterEvent</a>&gt;(coin_register_events);
1063+
<a href="event.md#0x1_event_destroy_handle">event::destroy_handle</a>&lt;<a href="account.md#0x1_account_KeyRotationEvent">KeyRotationEvent</a>&gt;(key_rotation_events);
1064+
1065+
<b>let</b> <a href="account.md#0x1_account_CapabilityOffer">CapabilityOffer</a> { for: _ } = rotation_capability_offer;
1066+
<b>let</b> <a href="account.md#0x1_account_CapabilityOffer">CapabilityOffer</a> { for: _ } = signer_capability_offer;
1067+
}
1068+
</code></pre>
1069+
1070+
1071+
10101072
</details>
10111073

10121074
<a id="0x1_account_exists_at"></a>

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

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ module aptos_framework::account {
55
use std::option::{Self, Option};
66
use std::signer;
77
use std::vector;
8+
use std::features::get_decommission_core_resources_enabled;
9+
#[test_only]
10+
use std::features::change_feature_flags_for_testing;
811
use aptos_framework::chain_id;
912
use aptos_framework::create_signer::create_signer;
1013
use aptos_framework::event::{Self, EventHandle};
@@ -130,6 +133,9 @@ module aptos_framework::account {
130133
/// whose address matches an existing address of a MultiEd25519 wallet.
131134
const DERIVE_RESOURCE_ACCOUNT_SCHEME: u8 = 255;
132135

136+
/// Feature flag for decommissioning core resources.
137+
const DECOMMISSION_CORE_RESOURCES: u64 = 222;
138+
133139
/// Account already exists
134140
const EACCOUNT_ALREADY_EXISTS: u64 = 1;
135141
/// Account does not exist
@@ -170,6 +176,8 @@ module aptos_framework::account {
170176
const ENO_SIGNER_CAPABILITY_OFFERED: u64 = 19;
171177
// This account has exceeded the allocated GUIDs it can create. It should be impossible to reach this number for real applications.
172178
const EEXCEEDED_MAX_GUID_CREATION_NUM: u64 = 20;
179+
// A required feature flag is not enabled.
180+
const EFLAG_NOT_ENABLED: u64 = 21;
173181

174182
/// Explicitly separate the GUID space between Object and Account to prevent accidental overlap.
175183
const MAX_GUID_CREATION_NUM: u64 = 0x4000000000000;
@@ -199,9 +207,18 @@ module aptos_framework::account {
199207
// there cannot be an Account resource under new_addr already.
200208
assert!(!exists<Account>(new_address), error::already_exists(EACCOUNT_ALREADY_EXISTS));
201209

202-
// NOTE: @core_resources gets created via a `create_account` call, so we do not include it below.
210+
// Check if the feature flag for decommissioning core resources is enabled.
211+
if (get_decommission_core_resources_enabled()) {
212+
// Assert separately for the core resources address if the feature flag is enabled.
213+
assert!(
214+
new_address != @0xa550c18,
215+
error::invalid_argument(ECANNOT_RESERVED_ADDRESS)
216+
);
217+
};
218+
219+
// Assert for other reserved addresses.
203220
assert!(
204-
new_address != @vm_reserved && new_address != @aptos_framework && new_address != @aptos_token && new_address != @0xa550c18,
221+
new_address != @vm_reserved && new_address != @aptos_framework && new_address != @aptos_token,
205222
error::invalid_argument(ECANNOT_RESERVED_ADDRESS)
206223
);
207224

@@ -245,6 +262,12 @@ module aptos_framework::account {
245262
public fun destroy_account_from(account: &signer, from: address) acquires Account {
246263
system_addresses::assert_aptos_framework(account);
247264

265+
// Assert that the feature flag for decommissioning core resources is enabled
266+
assert!(
267+
std::features::get_decommission_core_resources_enabled(),
268+
EFLAG_NOT_ENABLED
269+
);
270+
248271
let Account {
249272
authentication_key: _,
250273
sequence_number: _,
@@ -976,10 +999,13 @@ module aptos_framework::account {
976999
}
9771000

9781001
#[test(aptos_framework = @aptos_framework, from = @0xdead)]
979-
public entry fun test_destroy_account_from(
1002+
public entry fun test_destroy_account_from_with_flag_enabled(
9801003
aptos_framework: &signer,
9811004
from: &signer,
9821005
) acquires Account {
1006+
// Enable the feature flag for testing
1007+
std::features::change_feature_flags_for_testing(aptos_framework, vector[222], vector[]);
1008+
9831009
// Ensure the Account resource exists under the from account
9841010
if (!exists<Account>(signer::address_of(from))) {
9851011
create_account(signer::address_of(from));
@@ -995,6 +1021,27 @@ module aptos_framework::account {
9951021
assert!(!exists<Account>(signer::address_of(from)), 2);
9961022
}
9971023

1024+
#[test(aptos_framework = @aptos_framework, from = @0xdead)]
1025+
#[expected_failure(abort_code = 21, location = Self)]
1026+
public entry fun test_destroy_account_from_with_flag_disabled(
1027+
aptos_framework: &signer,
1028+
from: &signer,
1029+
) acquires Account {
1030+
// Disable the feature flag for testing
1031+
std::features::change_feature_flags_for_testing(aptos_framework, vector[], vector[222]);
1032+
1033+
// Ensure the Account resource exists under the from account
1034+
if (!exists<Account>(signer::address_of(from))) {
1035+
create_account(signer::address_of(from));
1036+
};
1037+
1038+
// Confirm it now exists
1039+
assert!(exists<Account>(signer::address_of(from)), 1);
1040+
1041+
// Attempt to destroy the Account resource (should fail)
1042+
destroy_account_from(aptos_framework, signer::address_of(from));
1043+
}
1044+
9981045
#[test_only]
9991046
struct DummyResource has key {}
10001047

@@ -1574,9 +1621,22 @@ module aptos_framework::account {
15741621
assert!(!event::was_event_emitted_by_handle(eventhandle, &event), 3);
15751622
}
15761623

1577-
#[test]
1624+
#[test(framework = @0x1)]
15781625
#[expected_failure(abort_code = 65541, location = Self)]
1579-
public entry fun test_cannot_create_account_at_core_resources_address() {
1626+
public entry fun test_cannot_create_account_at_core_resources_address_with_feature_flag(framework: signer) {
1627+
// Enable the feature flag for testing
1628+
change_feature_flags_for_testing(&framework, vector[222], vector[]);
1629+
1630+
// Attempt to create an account at the core resources address
1631+
create_account(@0xa550c18);
1632+
}
1633+
1634+
#[test(framework = @0x1)]
1635+
public entry fun test_can_create_account_at_core_resources_address_without_feature_flag(framework: signer) {
1636+
// Disable the feature flag for testing
1637+
change_feature_flags_for_testing(&framework, vector[], vector[222]);
1638+
1639+
// Attempt to create an account at the core resources address
15801640
create_account(@0xa550c18);
15811641
}
15821642
}

aptos-move/framework/aptos-framework/sources/genesis.move

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,6 @@ module aptos_framework::genesis {
531531

532532
/// Expected to fail after post-l1-merge release; it's okay because we will not regenesis.
533533
#[test(aptos_framework = @0x1, root = @0xabcd)]
534-
#[expected_failure(abort_code = 65541, location = aptos_framework::account)]
535534
fun test_create_root_account(aptos_framework: &signer) {
536535
use aptos_framework::aggregator_factory;
537536
use aptos_framework::object;

aptos-move/framework/move-stdlib/doc/features.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ return true.
135135
- [Function `abort_native_bridge_enabled`](#0x1_features_abort_native_bridge_enabled)
136136
- [Function `get_governed_gas_pool_feature`](#0x1_features_get_governed_gas_pool_feature)
137137
- [Function `governed_gas_pool_enabled`](#0x1_features_governed_gas_pool_enabled)
138+
- [Function `get_decommission_core_resources_feature`](#0x1_features_get_decommission_core_resources_feature)
139+
- [Function `get_decommission_core_resources_enabled`](#0x1_features_get_decommission_core_resources_enabled)
138140
- [Function `change_feature_flags`](#0x1_features_change_feature_flags)
139141
- [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal)
140142
- [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch)
@@ -427,6 +429,16 @@ Lifetime: transient
427429

428430

429431

432+
<a id="0x1_features_DECOMMISSION_CORE_RESOURCES"></a>
433+
434+
Lifetime: transient
435+
436+
437+
<pre><code><b>const</b> <a href="features.md#0x1_features_DECOMMISSION_CORE_RESOURCES">DECOMMISSION_CORE_RESOURCES</a>: u64 = 222;
438+
</code></pre>
439+
440+
441+
430442
<a id="0x1_features_DEFAULT_TO_CONCURRENT_FUNGIBLE_BALANCE"></a>
431443

432444
Whether to default new Fungible Store to the concurrent variant.
@@ -3331,6 +3343,52 @@ Whether the Governed Gas Pool is enabled.
33313343

33323344

33333345

3346+
</details>
3347+
3348+
<a id="0x1_features_get_decommission_core_resources_feature"></a>
3349+
3350+
## Function `get_decommission_core_resources_feature`
3351+
3352+
3353+
3354+
<pre><code><b>public</b> <b>fun</b> <a href="features.md#0x1_features_get_decommission_core_resources_feature">get_decommission_core_resources_feature</a>(): u64
3355+
</code></pre>
3356+
3357+
3358+
3359+
<details>
3360+
<summary>Implementation</summary>
3361+
3362+
3363+
<pre><code><b>public</b> <b>fun</b> <a href="features.md#0x1_features_get_decommission_core_resources_feature">get_decommission_core_resources_feature</a>(): u64 { <a href="features.md#0x1_features_DECOMMISSION_CORE_RESOURCES">DECOMMISSION_CORE_RESOURCES</a> }
3364+
</code></pre>
3365+
3366+
3367+
3368+
</details>
3369+
3370+
<a id="0x1_features_get_decommission_core_resources_enabled"></a>
3371+
3372+
## Function `get_decommission_core_resources_enabled`
3373+
3374+
3375+
3376+
<pre><code><b>public</b> <b>fun</b> <a href="features.md#0x1_features_get_decommission_core_resources_enabled">get_decommission_core_resources_enabled</a>(): bool
3377+
</code></pre>
3378+
3379+
3380+
3381+
<details>
3382+
<summary>Implementation</summary>
3383+
3384+
3385+
<pre><code><b>public</b> <b>fun</b> <a href="features.md#0x1_features_get_decommission_core_resources_enabled">get_decommission_core_resources_enabled</a>(): bool <b>acquires</b> <a href="features.md#0x1_features_Features">Features</a> {
3386+
<a href="features.md#0x1_features_is_enabled">is_enabled</a>(<a href="features.md#0x1_features_DECOMMISSION_CORE_RESOURCES">DECOMMISSION_CORE_RESOURCES</a>)
3387+
}
3388+
</code></pre>
3389+
3390+
3391+
33343392
</details>
33353393

33363394
<a id="0x1_features_change_feature_flags"></a>

aptos-move/framework/move-stdlib/sources/configs/features.move

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,15 @@ module std::features {
615615
is_enabled(GOVERNED_GAS_POOL)
616616
}
617617

618+
/// Lifetime: transient
619+
const DECOMMISSION_CORE_RESOURCES: u64 = 222;
620+
621+
public fun get_decommission_core_resources_feature(): u64 { DECOMMISSION_CORE_RESOURCES }
622+
623+
public fun get_decommission_core_resources_enabled(): bool acquires Features {
624+
is_enabled(DECOMMISSION_CORE_RESOURCES)
625+
}
626+
618627
// ============================================================================================
619628
// Feature Flag Implementation
620629

0 commit comments

Comments
 (0)