Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sui-framework] Reserve addresses for the deny list #17594

Merged
merged 9 commits into from
May 10, 2024
Merged
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
31 changes: 30 additions & 1 deletion crates/sui-framework/docs/sui-framework/deny_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ list.
- [Function `per_type_list`](#0x2_deny_list_per_type_list)


<pre><code><b>use</b> <a href="../sui-framework/bag.md#0x2_bag">0x2::bag</a>;
<pre><code><b>use</b> <a href="../move-stdlib/vector.md#0x1_vector">0x1::vector</a>;
<b>use</b> <a href="../sui-framework/bag.md#0x2_bag">0x2::bag</a>;
<b>use</b> <a href="../sui-framework/object.md#0x2_object">0x2::object</a>;
<b>use</b> <a href="../sui-framework/table.md#0x2_table">0x2::table</a>;
<b>use</b> <a href="../sui-framework/transfer.md#0x2_transfer">0x2::transfer</a>;
Expand Down Expand Up @@ -132,6 +133,16 @@ The index into the deny list vector for the <code>sui::coin::Coin</code> type.



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

The specified address cannot be added to the deny list.


<pre><code><b>const</b> <a href="../sui-framework/deny_list.md#0x2_deny_list_EInvalidAddress">EInvalidAddress</a>: u64 = 1;
</code></pre>



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

The specified address to be removed is not already in the deny list.
Expand All @@ -142,6 +153,18 @@ The specified address to be removed is not already in the deny list.



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

These addresses are reserved and cannot be added to the deny list.
The addresses listed are well known package and object addresses. So it would be
meaningless to add them to the deny list.


<pre><code><b>const</b> <a href="../sui-framework/deny_list.md#0x2_deny_list_RESERVED">RESERVED</a>: <a href="../move-stdlib/vector.md#0x1_vector">vector</a>&lt;<b>address</b>&gt; = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1027, 57065];
</code></pre>



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

## Function `add`
Expand All @@ -167,6 +190,8 @@ the type specified is the type of the coin, not the coin type itself. For exampl
`type`: <a href="../move-stdlib/vector.md#0x1_vector">vector</a>&lt;u8&gt;,
addr: <b>address</b>,
) {
<b>let</b> reserved = <a href="../sui-framework/deny_list.md#0x2_deny_list_RESERVED">RESERVED</a>;
<b>assert</b>!(!reserved.<a href="../sui-framework/deny_list.md#0x2_deny_list_contains">contains</a>(&addr), <a href="../sui-framework/deny_list.md#0x2_deny_list_EInvalidAddress">EInvalidAddress</a>);
<b>let</b> bag_entry: &<b>mut</b> <a href="../sui-framework/deny_list.md#0x2_deny_list_PerTypeList">PerTypeList</a> = &<b>mut</b> <a href="../sui-framework/deny_list.md#0x2_deny_list">deny_list</a>.lists[per_type_index];
bag_entry.<a href="../sui-framework/deny_list.md#0x2_deny_list_per_type_list_add">per_type_list_add</a>(`type`, addr)
}
Expand Down Expand Up @@ -239,6 +264,8 @@ Aborts with <code><a href="../sui-framework/deny_list.md#0x2_deny_list_ENotDenie
`type`: <a href="../move-stdlib/vector.md#0x1_vector">vector</a>&lt;u8&gt;,
addr: <b>address</b>,
) {
<b>let</b> reserved = <a href="../sui-framework/deny_list.md#0x2_deny_list_RESERVED">RESERVED</a>;
<b>assert</b>!(!reserved.<a href="../sui-framework/deny_list.md#0x2_deny_list_contains">contains</a>(&addr), <a href="../sui-framework/deny_list.md#0x2_deny_list_EInvalidAddress">EInvalidAddress</a>);
<a href="../sui-framework/deny_list.md#0x2_deny_list_per_type_list_remove">per_type_list_remove</a>(&<b>mut</b> <a href="../sui-framework/deny_list.md#0x2_deny_list">deny_list</a>.lists[per_type_index], `type`, addr)
}
</code></pre>
Expand Down Expand Up @@ -304,6 +331,8 @@ Returns true iff the given address is denied for the given type.
`type`: <a href="../move-stdlib/vector.md#0x1_vector">vector</a>&lt;u8&gt;,
addr: <b>address</b>,
): bool {
<b>let</b> reserved = <a href="../sui-framework/deny_list.md#0x2_deny_list_RESERVED">RESERVED</a>;
<b>if</b> (reserved.<a href="../sui-framework/deny_list.md#0x2_deny_list_contains">contains</a>(&addr)) <b>return</b> <b>false</b>;
<a href="../sui-framework/deny_list.md#0x2_deny_list_per_type_list_contains">per_type_list_contains</a>(&<a href="../sui-framework/deny_list.md#0x2_deny_list">deny_list</a>.lists[per_type_index], `type`, addr)
}
</code></pre>
Expand Down
38 changes: 38 additions & 0 deletions crates/sui-framework/packages/sui-framework/sources/deny_list.move
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,37 @@ module sui::deny_list {
const ENotSystemAddress: u64 = 0;
/// The specified address to be removed is not already in the deny list.
const ENotDenied: u64 = 1;
/// The specified address cannot be added to the deny list.
const EInvalidAddress: u64 = 1;

/// The index into the deny list vector for the `sui::coin::Coin` type.
const COIN_INDEX: u64 = 0;

/// These addresses are reserved and cannot be added to the deny list.
/// The addresses listed are well known package and object addresses. So it would be
/// meaningless to add them to the deny list.
const RESERVED: vector<address> = vector[
@0x0,
@0x1,
@0x2,
@0x3,
@0x4,
@0x5,
@0x6,
@0x7,
@0x8,
@0x9,
@0xA,
@0xB,
@0xC,
@0xD,
@0xE,
@0xF,
@0x403,
Copy link
Contributor

Choose a reason for hiding this comment

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

bridge?

Copy link
Contributor

Choose a reason for hiding this comment

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

Bridge package (@patrickkuo)
const SUI_BRIDGE_ID: address = @0x9;

Copy link
Contributor

Choose a reason for hiding this comment

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

bridge object is 0x9 and bridge package is 0xb

@0xDEE9,
];


/// A shared object that stores the addresses that are blocked for a given core type.
public struct DenyList has key {
id: UID,
Expand Down Expand Up @@ -46,6 +73,8 @@ module sui::deny_list {
`type`: vector<u8>,
addr: address,
) {
let reserved = RESERVED;
assert!(!reserved.contains(&addr), EInvalidAddress);
let bag_entry: &mut PerTypeList = &mut deny_list.lists[per_type_index];
bag_entry.per_type_list_add(`type`, addr)
}
Expand Down Expand Up @@ -78,6 +107,8 @@ module sui::deny_list {
`type`: vector<u8>,
addr: address,
) {
let reserved = RESERVED;
assert!(!reserved.contains(&addr), EInvalidAddress);
per_type_list_remove(&mut deny_list.lists[per_type_index], `type`, addr)
}

Expand All @@ -103,6 +134,8 @@ module sui::deny_list {
`type`: vector<u8>,
addr: address,
): bool {
let reserved = RESERVED;
if (reserved.contains(&addr)) return false;
per_type_list_contains(&deny_list.lists[per_type_index], `type`, addr)
}

Expand Down Expand Up @@ -145,6 +178,11 @@ module sui::deny_list {
}
}

#[test_only]
public fun reserved_addresses(): vector<address> {
RESERVED
}

#[test_only]
public fun create_for_test(ctx: &mut TxContext) {
create(ctx);
Expand Down
56 changes: 43 additions & 13 deletions crates/sui-framework/packages/sui-framework/tests/coin_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -115,36 +115,66 @@ module sui::coin_tests {
// test freezing an address
scenario.next_tx(TEST_ADDR);
let mut deny_list: deny_list::DenyList = scenario.take_shared();
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @1), 0);
coin::deny_list_add(&mut deny_list, &mut deny_cap, @1, scenario.ctx());
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @1), 0);
coin::deny_list_remove(&mut deny_list, &mut deny_cap, @1, scenario.ctx());
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @1), 0);
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
coin::deny_list_add(&mut deny_list, &mut deny_cap, @100, scenario.ctx());
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
coin::deny_list_remove(&mut deny_list, &mut deny_cap, @100, scenario.ctx());
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
test_scenario::return_shared(deny_list);
};
{
// test freezing an address over multiple "transactions"
scenario.next_tx(TEST_ADDR);
let mut deny_list: deny_list::DenyList = scenario.take_shared();
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @1), 0);
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @2), 0);
coin::deny_list_add(&mut deny_list, &mut deny_cap, @2, scenario.ctx());
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @2), 0);
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @200), 0);
coin::deny_list_add(&mut deny_list, &mut deny_cap, @200, scenario.ctx());
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @200), 0);
test_scenario::return_shared(deny_list);

scenario.next_tx(TEST_ADDR);
let mut deny_list: deny_list::DenyList = scenario.take_shared();
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @2), 0);
coin::deny_list_remove(&mut deny_list, &mut deny_cap, @2, scenario.ctx());
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @2), 0);
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @200), 0);
coin::deny_list_remove(&mut deny_list, &mut deny_cap, @200, scenario.ctx());
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @200), 0);
test_scenario::return_shared(deny_list);
};
transfer::public_freeze_object(deny_cap);
scenario.end();
}


#[test]
fun address_is_frozen_with_arbitrary_types() {
fun deny_list_double_add() {
let mut scenario = test_scenario::begin(@0);
deny_list::create_for_test(scenario.ctx());
scenario.next_tx(TEST_ADDR);

let witness = COIN_TESTS {};
let (treasury, mut deny_cap, metadata) = coin::create_regulated_currency(
witness,
6,
b"COIN_TESTS",
b"coin_name",
b"description",
option::some(url::new_unsafe_from_bytes(b"icon_url")),
scenario.ctx(),
);
transfer::public_freeze_object(metadata);
transfer::public_freeze_object(treasury);
{
// test freezing an address
scenario.next_tx(TEST_ADDR);
let mut deny_list: deny_list::DenyList = scenario.take_shared();
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
coin::deny_list_add(&mut deny_list, &mut deny_cap, @100, scenario.ctx());
coin::deny_list_add(&mut deny_list, &mut deny_cap, @100, scenario.ctx());
assert!(coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
coin::deny_list_remove(&mut deny_list, &mut deny_cap, @100, scenario.ctx());
assert!(!coin::deny_list_contains<COIN_TESTS>(&deny_list, @100), 0);
test_scenario::return_shared(deny_list);
};
transfer::public_freeze_object(deny_cap);
scenario.end();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

#[test_only]
module sui::deny_list_tests {
use sui::deny_list;
use sui::test_scenario;
use std::type_name;

public struct X()

#[test, expected_failure(abort_code = sui::deny_list::EInvalidAddress)]
fun add_zero() {
let mut ctx = tx_context::dummy();
let mut dl = deny_list::new_for_testing(&mut ctx);
let ty = type_name::into_string(type_name::get_with_original_ids<X>()).into_bytes();
dl.add(1, ty, deny_list::reserved_addresses()[0]); // should error
abort 0 // should not be reached
}

#[test, expected_failure(abort_code = sui::deny_list::EInvalidAddress)]
fun remove_zero() {
let mut ctx = tx_context::dummy();
let mut dl = deny_list::new_for_testing(&mut ctx);
let ty = type_name::into_string(type_name::get_with_original_ids<X>()).into_bytes();
dl.add(1, ty, deny_list::reserved_addresses()[1]); // should error
abort 0 // should not be reached
}

#[test]
fun contains_zero () {
let mut scenario = test_scenario::begin(@0);
deny_list::create_for_test(scenario.ctx());
scenario.next_tx(@0);
let dl: deny_list::DenyList = scenario.take_shared();
let ty = type_name::into_string(type_name::get_with_original_ids<X>()).into_bytes();
let reserved = deny_list::reserved_addresses();
let mut i = 0;
let n = reserved.length();
while (i < n) {
assert!(!dl.contains(1, ty, reserved[i]), 0);
i = i + 1;
};
test_scenario::return_shared(dl);
scenario.end();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -240,56 +240,56 @@ validators:
next_epoch_worker_address: ~
extra_fields:
id:
id: "0xac9fdccb1113a5ead94e4673576e6a760db21d991a22cf2b0d24ac484a05bddf"
id: "0x78419e399d09b062dad70b4da1b913398832d36ab3e52dcc5692a34306f21aa8"
size: 0
voting_power: 10000
operation_cap_id: "0x60e827aab20f6d00deeb5c2b6905b69691e348779b3bbef9934241028fad9cac"
operation_cap_id: "0x210f997d8ec5c8c41de7eef78d479e695662abf8f7524550e111a9dcb4e69048"
gas_price: 1000
staking_pool:
id: "0x92c825f5f682227d3d6b9bc4250ee58b871457e71c25c8cb35188318f3beeb75"
id: "0xa906ffe57044c2c1b8ef2730abef7fc05c293200072808ec96ab219e116e8643"
activation_epoch: 0
deactivation_epoch: ~
sui_balance: 20000000000000000
rewards_pool:
value: 0
pool_token_balance: 20000000000000000
exchange_rates:
id: "0x755c1a3a47fd39c01a5f0254f9cddfda49d5e3c5fdc0e8cdfb8c9e09ea4ab159"
id: "0x55411d92935af33910fab31c8f404715506ad85325c13d397668d454a9cc5771"
size: 1
pending_stake: 0
pending_total_sui_withdraw: 0
pending_pool_token_withdraw: 0
extra_fields:
id:
id: "0x1e62cc42d9d0f988f2ca64ba977265fc927f8902b6a9c4463ce1403dcfb53481"
id: "0x369d32b68b08acbc82bf9810b2899b3308dc983295ea961e4e7fa566750d2f0a"
size: 0
commission_rate: 200
next_epoch_stake: 20000000000000000
next_epoch_gas_price: 1000
next_epoch_commission_rate: 200
extra_fields:
id:
id: "0xda16f4a6cf350652385ee9f70a75f75bf5fc4db3881f551ff4667590dec6b168"
id: "0x03cf25df3afa79796d6b713beda5fb211ebe68c3106f02ef4d46ef1db94ac38e"
size: 0
pending_active_validators:
contents:
id: "0x3e54263b253e0a34c4d7cc3411c1d1e71c04d439296063f4abd59d2d36361476"
id: "0x2cee5364052fddf06e543654a8b4e70ba368886b7499549341471ace8c17bd8d"
size: 0
pending_removals: []
staking_pool_mappings:
id: "0x481b46e1234711601011a3509fc058f5412acf2c45a6df50a3efbcef1fdbea2c"
id: "0xebda3240d8d9d03612abed57cb7956589798d02c4e1fbbb9f2d858dad3676226"
size: 1
inactive_validators:
id: "0x25813ecb5889bb69bf99c7ef124c41ab5ee402a70d8e8f8b8292be0164bdb102"
id: "0x505e3f96ec5b8fbb89cd915fb89fe2e3f4a5185841b4409ab425c7b7e5e150d1"
size: 0
validator_candidates:
id: "0xa553c4986f10db731d26ce7681a5f12f36c155e968ddf8aece4adb000fffe675"
id: "0x63dbfab711c6417f47755ddbdafcca1381d485088aeba3b5a0329c397b54da6c"
size: 0
at_risk_validators:
contents: []
extra_fields:
id:
id: "0x9a36528247ca768e9978a0f6261262eb9a1ee1c36171d62a34274a5585154766"
id: "0x54b12ac490ec6068f6c4b3e55598a3b37feac91f03eef7c1644db3f483a29df6"
size: 0
storage_fund:
total_object_storage_rebates:
Expand All @@ -306,7 +306,7 @@ parameters:
validator_low_stake_grace_period: 7
extra_fields:
id:
id: "0x0a1a9f6c24196754c0fbc53ee19825c9b4dc08c48235ccd24300cba232c5b230"
id: "0xd79ef5b750f92c7568694fceb273433544e462e96f22ad58c746737086392b56"
size: 0
reference_gas_price: 1000
validator_report_records:
Expand All @@ -320,7 +320,7 @@ stake_subsidy:
stake_subsidy_decrease_rate: 1000
extra_fields:
id:
id: "0x7d66ca292c50b9c41a42b1b6c8e0e364e216ed855ebe2501d635e0460095a681"
id: "0xbb7880c641a8b0a8acced69d2591a80cb2d62b2ea84e3014ffe7b78d1b687deb"
size: 0
safe_mode: false
safe_mode_storage_rewards:
Expand All @@ -332,6 +332,6 @@ safe_mode_non_refundable_storage_fee: 0
epoch_start_timestamp_ms: 10
extra_fields:
id:
id: "0x8f29d92087ed1cc18eb60278915388fb7276b96e0ed4eee38b811366cec36ec9"
id: "0x6674346a07bbb4c87f10094588767ba31dda96f7018a720a2699be8f5d738f16"
size: 0

Loading