Skip to content

Commit

Permalink
[config] Added ability to remove settings (MystenLabs#18434)
Browse files Browse the repository at this point in the history
## Description 

- Added the ability to remove settings and unset settings for a current
epoch

## Test plan 

- Added new tests 

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
  • Loading branch information
tnowacki authored and tx-tomcat committed Jul 29, 2024
1 parent b9be512 commit af92cae
Show file tree
Hide file tree
Showing 9 changed files with 428 additions and 64 deletions.
102 changes: 88 additions & 14 deletions crates/sui-framework/docs/sui-framework/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ title: Module `0x2::config`
- [Function `new`](#0x2_config_new)
- [Function `create`](#0x2_config_create)
- [Function `add_for_current_epoch`](#0x2_config_add_for_current_epoch)
- [Function `remove_for_current_epoch`](#0x2_config_remove_for_current_epoch)
- [Function `exists_with_type`](#0x2_config_exists_with_type)
- [Function `exists_with_type_for_current_epoch`](#0x2_config_exists_with_type_for_current_epoch)
- [Function `borrow_for_current_epoch_mut`](#0x2_config_borrow_for_current_epoch_mut)
Expand Down Expand Up @@ -61,7 +62,7 @@ title: Module `0x2::config`



<pre><code><b>struct</b> <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value: <b>copy</b>, drop, store&gt; <b>has</b> store
<pre><code><b>struct</b> <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value: <b>copy</b>, drop, store&gt; <b>has</b> drop, store
</code></pre>


Expand All @@ -88,7 +89,7 @@ title: Module `0x2::config`



<pre><code><b>struct</b> <a href="../sui-framework/config.md#0x2_config_SettingData">SettingData</a>&lt;Value: <b>copy</b>, drop, store&gt; <b>has</b> store
<pre><code><b>struct</b> <a href="../sui-framework/config.md#0x2_config_SettingData">SettingData</a>&lt;Value: <b>copy</b>, drop, store&gt; <b>has</b> drop, store
</code></pre>


Expand All @@ -105,7 +106,7 @@ title: Module `0x2::config`

</dd>
<dt>
<code>newer_value: Value</code>
<code>newer_value: <a href="../move-stdlib/option.md#0x1_option_Option">option::Option</a>&lt;Value&gt;</code>
</dt>
<dd>

Expand Down Expand Up @@ -207,7 +208,7 @@ title: Module `0x2::config`



<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="../sui-framework/config.md#0x2_config_add_for_current_epoch">add_for_current_epoch</a>&lt;WriteCap, Name: <b>copy</b>, drop, store, Value: <b>copy</b>, drop, store&gt;(<a href="../sui-framework/config.md#0x2_config">config</a>: &<b>mut</b> <a href="../sui-framework/config.md#0x2_config_Config">config::Config</a>&lt;WriteCap&gt;, _cap: &<b>mut</b> WriteCap, name: Name, value: Value, _ctx: &<b>mut</b> <a href="../sui-framework/tx_context.md#0x2_tx_context_TxContext">tx_context::TxContext</a>): <a href="../move-stdlib/option.md#0x1_option_Option">option::Option</a>&lt;Value&gt;
<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="../sui-framework/config.md#0x2_config_add_for_current_epoch">add_for_current_epoch</a>&lt;WriteCap, Name: <b>copy</b>, drop, store, Value: <b>copy</b>, drop, store&gt;(<a href="../sui-framework/config.md#0x2_config">config</a>: &<b>mut</b> <a href="../sui-framework/config.md#0x2_config_Config">config::Config</a>&lt;WriteCap&gt;, _cap: &<b>mut</b> WriteCap, name: Name, value: Value, ctx: &<b>mut</b> <a href="../sui-framework/tx_context.md#0x2_tx_context_TxContext">tx_context::TxContext</a>): <a href="../move-stdlib/option.md#0x1_option_Option">option::Option</a>&lt;Value&gt;
</code></pre>


Expand All @@ -225,14 +226,14 @@ title: Module `0x2::config`
_cap: &<b>mut</b> WriteCap,
name: Name,
value: Value,
_ctx: &<b>mut</b> TxContext,
ctx: &<b>mut</b> TxContext,
): Option&lt;Value&gt; {
<b>let</b> epoch = _ctx.epoch();
<b>let</b> epoch = ctx.epoch();
<b>if</b> (!field::exists_(&<a href="../sui-framework/config.md#0x2_config">config</a>.id, name)) {
<b>let</b> sobj = <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a> {
data: <a href="../move-stdlib/option.md#0x1_option_some">option::some</a>(<a href="../sui-framework/config.md#0x2_config_SettingData">SettingData</a> {
newer_value_epoch: epoch,
newer_value: value,
newer_value: <a href="../move-stdlib/option.md#0x1_option_some">option::some</a>(value),
older_value_opt: <a href="../move-stdlib/option.md#0x1_option_none">option::none</a>(),
}),
};
Expand All @@ -245,19 +246,88 @@ title: Module `0x2::config`
newer_value,
older_value_opt,
} = sobj.data.extract();
<b>assert</b>!(epoch &gt; newer_value_epoch, <a href="../sui-framework/config.md#0x2_config_EAlreadySetForEpoch">EAlreadySetForEpoch</a>);
<b>let</b> (older_value_opt, removed_value) =
<b>if</b> (epoch &gt; newer_value_epoch) {
// <b>if</b> the `newer_value` is for a previous epoch, <b>move</b> it <b>to</b> `older_value_opt`
(<b>move</b> newer_value, <b>move</b> older_value_opt)
} <b>else</b> {
// the current epoch cannot be less than the `newer_value_epoch`
<b>assert</b>!(epoch == newer_value_epoch);
// <b>if</b> the `newer_value` is for the current epoch, then the <a href="../move-stdlib/option.md#0x1_option">option</a> must be `none`
<b>assert</b>!(newer_value.is_none(), <a href="../sui-framework/config.md#0x2_config_EAlreadySetForEpoch">EAlreadySetForEpoch</a>);
(<b>move</b> older_value_opt, <a href="../move-stdlib/option.md#0x1_option_none">option::none</a>())
};
sobj.data.fill(<a href="../sui-framework/config.md#0x2_config_SettingData">SettingData</a> {
newer_value_epoch: epoch,
newer_value: value,
older_value_opt: <a href="../move-stdlib/option.md#0x1_option_some">option::some</a>(newer_value),
newer_value: <a href="../move-stdlib/option.md#0x1_option_some">option::some</a>(value),
older_value_opt,
});
older_value_opt
removed_value
}
}
</code></pre>



</details>

<a name="0x2_config_remove_for_current_epoch"></a>

## Function `remove_for_current_epoch`



<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="../sui-framework/config.md#0x2_config_remove_for_current_epoch">remove_for_current_epoch</a>&lt;WriteCap, Name: <b>copy</b>, drop, store, Value: <b>copy</b>, drop, store&gt;(<a href="../sui-framework/config.md#0x2_config">config</a>: &<b>mut</b> <a href="../sui-framework/config.md#0x2_config_Config">config::Config</a>&lt;WriteCap&gt;, _cap: &<b>mut</b> WriteCap, name: Name, ctx: &<b>mut</b> <a href="../sui-framework/tx_context.md#0x2_tx_context_TxContext">tx_context::TxContext</a>): <a href="../move-stdlib/option.md#0x1_option_Option">option::Option</a>&lt;Value&gt;
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b>(package) <b>fun</b> <a href="../sui-framework/config.md#0x2_config_remove_for_current_epoch">remove_for_current_epoch</a>&lt;
WriteCap,
Name: <b>copy</b> + drop + store,
Value: <b>copy</b> + drop + store,
&gt;(
<a href="../sui-framework/config.md#0x2_config">config</a>: &<b>mut</b> <a href="../sui-framework/config.md#0x2_config_Config">Config</a>&lt;WriteCap&gt;,
_cap: &<b>mut</b> WriteCap,
name: Name,
ctx: &<b>mut</b> TxContext,
): Option&lt;Value&gt; {
<b>let</b> epoch = ctx.epoch();
<b>if</b> (!field::exists_(&<a href="../sui-framework/config.md#0x2_config">config</a>.id, name)) <b>return</b> <a href="../move-stdlib/option.md#0x1_option_none">option::none</a>();
<b>let</b> sobj: &<b>mut</b> <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value&gt; = field::borrow_mut(&<b>mut</b> <a href="../sui-framework/config.md#0x2_config">config</a>.id, name);
<b>let</b> <a href="../sui-framework/config.md#0x2_config_SettingData">SettingData</a> {
newer_value_epoch,
newer_value,
older_value_opt,
} = sobj.data.extract();
<b>let</b> (older_value_opt, removed_value) =
<b>if</b> (epoch &gt; newer_value_epoch) {
// <b>if</b> the `newer_value` is for a previous epoch, <b>move</b> it <b>to</b> `older_value_opt`
(<b>move</b> newer_value, <a href="../move-stdlib/option.md#0x1_option_none">option::none</a>())
} <b>else</b> {
// the current epoch cannot be less than the `newer_value_epoch`
<b>assert</b>!(epoch == newer_value_epoch);
(<b>move</b> older_value_opt, <b>move</b> newer_value)
};
<b>let</b> older_value_opt_is_none = older_value_opt.is_none();
sobj.data.fill(<a href="../sui-framework/config.md#0x2_config_SettingData">SettingData</a> {
newer_value_epoch: epoch,
newer_value: <a href="../move-stdlib/option.md#0x1_option_none">option::none</a>(),
older_value_opt,
});
<b>if</b> (older_value_opt_is_none) {
field::remove&lt;_, <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value&gt;&gt;(&<b>mut</b> <a href="../sui-framework/config.md#0x2_config">config</a>.id, name);
};
removed_value
}
</code></pre>



</details>

<a name="0x2_config_exists_with_type"></a>
Expand Down Expand Up @@ -318,7 +388,8 @@ title: Module `0x2::config`
field::exists_with_type&lt;_, <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value&gt;&gt;(&<a href="../sui-framework/config.md#0x2_config">config</a>.id, name) && {
<b>let</b> epoch = ctx.epoch();
<b>let</b> sobj: &<a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value&gt; = field::borrow(&<a href="../sui-framework/config.md#0x2_config">config</a>.id, name);
epoch == sobj.data.borrow().newer_value_epoch
epoch == sobj.data.borrow().newer_value_epoch &&
sobj.data.borrow().newer_value.is_some()
}
}
</code></pre>
Expand Down Expand Up @@ -356,7 +427,8 @@ title: Module `0x2::config`
<b>let</b> sobj: &<b>mut</b> <a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value&gt; = field::borrow_mut(&<b>mut</b> <a href="../sui-framework/config.md#0x2_config">config</a>.id, name);
<b>let</b> data = sobj.data.borrow_mut();
<b>assert</b>!(data.newer_value_epoch == epoch, <a href="../sui-framework/config.md#0x2_config_ENotSetForEpoch">ENotSetForEpoch</a>);
&<b>mut</b> data.newer_value
<b>assert</b>!(data.newer_value.is_some(), <a href="../sui-framework/config.md#0x2_config_ENotSetForEpoch">ENotSetForEpoch</a>);
data.newer_value.borrow_mut()
}
</code></pre>

Expand Down Expand Up @@ -388,7 +460,9 @@ title: Module `0x2::config`
name: Name,
): &Value {
<b>let</b> sobj: &<a href="../sui-framework/config.md#0x2_config_Setting">Setting</a>&lt;Value&gt; = field::borrow(&<a href="../sui-framework/config.md#0x2_config">config</a>.id, name);
&sobj.data.borrow().newer_value
<b>let</b> data = sobj.data.borrow();
<b>assert</b>!(data.newer_value.is_some(), <a href="../sui-framework/config.md#0x2_config_ENotSetForEpoch">ENotSetForEpoch</a>);
data.newer_value.borrow()
}
</code></pre>

Expand Down
4 changes: 1 addition & 3 deletions crates/sui-framework/docs/sui-framework/deny_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,13 +393,11 @@ meaningless to add them to the deny list.
) {
<b>let</b> per_type_config = <a href="../sui-framework/deny_list.md#0x2_deny_list">deny_list</a>.per_type_config_entry!(per_type_index, per_type_key, ctx);
<b>let</b> setting_name = <a href="../sui-framework/deny_list.md#0x2_deny_list_AddressKey">AddressKey</a>(addr);
<b>let</b> next_epoch_entry = per_type_config.entry!&lt;_, <a href="../sui-framework/deny_list.md#0x2_deny_list_AddressKey">AddressKey</a>, bool&gt;(
per_type_config.remove_for_current_epoch&lt;_, <a href="../sui-framework/deny_list.md#0x2_deny_list_AddressKey">AddressKey</a>, bool&gt;(
&<b>mut</b> <a href="../sui-framework/deny_list.md#0x2_deny_list_ConfigWriteCap">ConfigWriteCap</a>(),
setting_name,
|_deny_list, _cap, _ctx| <b>false</b>,
ctx,
);
*next_epoch_entry = <b>false</b>;
}
</code></pre>

Expand Down
81 changes: 68 additions & 13 deletions crates/sui-framework/packages/sui-framework/sources/config.move
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ module sui::config {
id: UID,
}

public struct Setting<Value: copy + drop + store> has store {
public struct Setting<Value: copy + drop + store> has store, drop {
data: Option<SettingData<Value>>,
}

public struct SettingData<Value: copy + drop + store> has store {
public struct SettingData<Value: copy + drop + store> has store, drop {
newer_value_epoch: u64,
newer_value: Value,
newer_value: Option<Value>,
older_value_opt: Option<Value>,
}

Expand All @@ -43,6 +43,7 @@ module sui::config {
transfer::share_object(new<WriteCap>(cap, ctx))
}

#[allow(unused_mut_parameter)]
public(package) fun add_for_current_epoch<
WriteCap,
Name: copy + drop + store,
Expand All @@ -52,14 +53,14 @@ module sui::config {
_cap: &mut WriteCap,
name: Name,
value: Value,
_ctx: &mut TxContext,
ctx: &mut TxContext,
): Option<Value> {
let epoch = _ctx.epoch();
let epoch = ctx.epoch();
if (!field::exists_(&config.id, name)) {
let sobj = Setting {
data: option::some(SettingData {
newer_value_epoch: epoch,
newer_value: value,
newer_value: option::some(value),
older_value_opt: option::none(),
}),
};
Expand All @@ -72,16 +73,66 @@ module sui::config {
newer_value,
older_value_opt,
} = sobj.data.extract();
assert!(epoch > newer_value_epoch, EAlreadySetForEpoch);
let (older_value_opt, removed_value) =
if (epoch > newer_value_epoch) {
// if the `newer_value` is for a previous epoch, move it to `older_value_opt`
(move newer_value, move older_value_opt)
} else {
// the current epoch cannot be less than the `newer_value_epoch`
assert!(epoch == newer_value_epoch);
// if the `newer_value` is for the current epoch, then the option must be `none`
assert!(newer_value.is_none(), EAlreadySetForEpoch);
(move older_value_opt, option::none())
};
sobj.data.fill(SettingData {
newer_value_epoch: epoch,
newer_value: value,
older_value_opt: option::some(newer_value),
newer_value: option::some(value),
older_value_opt,
});
older_value_opt
removed_value
}
}

#[allow(unused_mut_parameter)]
public(package) fun remove_for_current_epoch<
WriteCap,
Name: copy + drop + store,
Value: copy + drop + store,
>(
config: &mut Config<WriteCap>,
_cap: &mut WriteCap,
name: Name,
ctx: &mut TxContext,
): Option<Value> {
let epoch = ctx.epoch();
if (!field::exists_(&config.id, name)) return option::none();
let sobj: &mut Setting<Value> = field::borrow_mut(&mut config.id, name);
let SettingData {
newer_value_epoch,
newer_value,
older_value_opt,
} = sobj.data.extract();
let (older_value_opt, removed_value) =
if (epoch > newer_value_epoch) {
// if the `newer_value` is for a previous epoch, move it to `older_value_opt`
(move newer_value, option::none())
} else {
// the current epoch cannot be less than the `newer_value_epoch`
assert!(epoch == newer_value_epoch);
(move older_value_opt, move newer_value)
};
let older_value_opt_is_none = older_value_opt.is_none();
sobj.data.fill(SettingData {
newer_value_epoch: epoch,
newer_value: option::none(),
older_value_opt,
});
if (older_value_opt_is_none) {
field::remove<_, Setting<Value>>(&mut config.id, name);
};
removed_value
}

public(package) fun exists_with_type<
WriteCap,
Name: copy + drop + store,
Expand All @@ -106,7 +157,8 @@ module sui::config {
field::exists_with_type<_, Setting<Value>>(&config.id, name) && {
let epoch = ctx.epoch();
let sobj: &Setting<Value> = field::borrow(&config.id, name);
epoch == sobj.data.borrow().newer_value_epoch
epoch == sobj.data.borrow().newer_value_epoch &&
sobj.data.borrow().newer_value.is_some()
}
}

Expand All @@ -125,7 +177,8 @@ module sui::config {
let sobj: &mut Setting<Value> = field::borrow_mut(&mut config.id, name);
let data = sobj.data.borrow_mut();
assert!(data.newer_value_epoch == epoch, ENotSetForEpoch);
&mut data.newer_value
assert!(data.newer_value.is_some(), ENotSetForEpoch);
data.newer_value.borrow_mut()
}

public(package) fun borrow_most_recent<
Expand All @@ -137,7 +190,9 @@ module sui::config {
name: Name,
): &Value {
let sobj: &Setting<Value> = field::borrow(&config.id, name);
&sobj.data.borrow().newer_value
let data = sobj.data.borrow();
assert!(data.newer_value.is_some(), ENotSetForEpoch);
data.newer_value.borrow()
}

public(package) macro fun entry<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,11 @@ module sui::deny_list {
) {
let per_type_config = deny_list.per_type_config_entry!(per_type_index, per_type_key, ctx);
let setting_name = AddressKey(addr);
let next_epoch_entry = per_type_config.entry!<_, AddressKey, bool>(
per_type_config.remove_for_current_epoch<_, AddressKey, bool>(
&mut ConfigWriteCap(),
setting_name,
|_deny_list, _cap, _ctx| false,
ctx,
);
*next_epoch_entry = false;
}

public(package) fun v2_most_recent_contains(
Expand Down
Loading

0 comments on commit af92cae

Please sign in to comment.