Skip to content

Commit dc6b695

Browse files
authored
[stdlib] internal::Permit (#24240)
## Description Describe the changes or additions included in this PR. ## Test plan How did you test the new or updated feature? --- ## 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): - [ ] gRPC: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: - [ ] Indexing Framework:
1 parent 72442b0 commit dc6b695

File tree

22 files changed

+478
-14
lines changed

22 files changed

+478
-14
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Mysten Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Case: successful call through delegated public function
5+
6+
//# init --addresses test=0x0
7+
8+
//# publish
9+
module test::custom_type {
10+
use std::internal;
11+
12+
public struct CustomType {}
13+
14+
public fun create_internal(): internal::Permit<CustomType> {
15+
internal::permit<CustomType>()
16+
}
17+
}
18+
19+
module test::internal_delegated {
20+
use test::custom_type;
21+
22+
public fun test_internal() {
23+
let _ = custom_type::create_internal();
24+
}
25+
}
26+
27+
//# run test::internal_delegated::test_internal
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
source: external-crates/move/crates/move-transactional-test-runner/src/framework.rs
3+
---
4+
processed 3 tasks
5+
6+
task 1, lines 8-25:
7+
//# publish
8+
created: object(1,0)
9+
mutated: object(0,0)
10+
gas summary: computation_cost: 1000000, storage_cost: 6878000, storage_rebate: 0, non_refundable_storage_fee: 0
11+
12+
task 2, line 27:
13+
//# run test::internal_delegated::test_internal
14+
mutated: object(0,0)
15+
gas summary: computation_cost: 1000000, storage_cost: 988000, storage_rebate: 978120, non_refundable_storage_fee: 9880
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Mysten Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Case: try to call internal in PTB, fail
5+
6+
//# init --addresses test=0x0 --accounts A
7+
8+
//# publish
9+
module test::custom_type {
10+
public struct CustomType {}
11+
}
12+
13+
//# programmable --sender A
14+
//> 0: std::internal::permit<test::custom_type::CustomType>();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
source: external-crates/move/crates/move-transactional-test-runner/src/framework.rs
3+
---
4+
processed 3 tasks
5+
6+
init:
7+
A: object(0,0)
8+
9+
task 1, lines 8-11:
10+
//# publish
11+
created: object(1,0)
12+
mutated: object(0,1)
13+
gas summary: computation_cost: 1000000, storage_cost: 4020400, storage_rebate: 0, non_refundable_storage_fee: 0
14+
15+
task 2, lines 13-14:
16+
//# programmable --sender A
17+
//> 0: std::internal::permit<test::custom_type::CustomType>();
18+
Error: Transaction Effects Status: Non Entry Function Invoked. Move Call must start with an entry function
19+
Execution Error: ExecutionError: ExecutionError { inner: ExecutionErrorInner { kind: NonEntryFunctionInvoked, source: Some("Cannot directly call function 'std::internal::permit' since type parameter #0 can only be instantiated with types defined within the caller's module."), command: Some(0) } }
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
title: Module `std::internal`
3+
---
4+
5+
Defines the <code><a href="../std/internal.md#std_internal_Permit">Permit</a></code> type, which can be used to constrain the logic of a
6+
generic function to be authorized only by the module that defines the type
7+
parameter.
8+
9+
```move
10+
module example::use_permit;
11+
12+
public struct MyType { /* ... */ }
13+
14+
public fun test_permit() {
15+
let permit = internal::permit<MyType>();
16+
/* external_module::call_with_permit(permit); */
17+
}
18+
```
19+
20+
To write a function that is guarded by a <code><a href="../std/internal.md#std_internal_Permit">Permit</a></code>, require it as an argument.
21+
22+
```move
23+
// Silly mockup of a type registry where a type can be registered only by
24+
// the module that defines the type.
25+
module example::type_registry;
26+
27+
public fun register_type<T>(_: internal::Permit<T> /* ... */) {
28+
/* ... */
29+
}
30+
```
31+
32+
33+
- [Struct `Permit`](#std_internal_Permit)
34+
- [Function `permit`](#std_internal_permit)
35+
36+
37+
<pre><code></code></pre>
38+
39+
40+
41+
<a name="std_internal_Permit"></a>
42+
43+
## Struct `Permit`
44+
45+
A privileged witness of the <code>T</code> type.
46+
Instances can only be created by the module that defines the type <code>T</code>.
47+
48+
49+
<pre><code><b>public</b> <b>struct</b> <a href="../std/internal.md#std_internal_Permit">Permit</a>&lt;<b>phantom</b> T&gt; <b>has</b> drop
50+
</code></pre>
51+
52+
53+
54+
<details>
55+
<summary>Fields</summary>
56+
57+
58+
<dl>
59+
</dl>
60+
61+
62+
</details>
63+
64+
<a name="std_internal_permit"></a>
65+
66+
## Function `permit`
67+
68+
Construct a new <code><a href="../std/internal.md#std_internal_Permit">Permit</a></code> for the type <code>T</code>.
69+
Can only be called by the module that defines the type <code>T</code>.
70+
71+
72+
<pre><code><b>public</b> <b>fun</b> <a href="../std/internal.md#std_internal_permit">permit</a>&lt;T&gt;(): <a href="../std/internal.md#std_internal_Permit">std::internal::Permit</a>&lt;T&gt;
73+
</code></pre>
74+
75+
76+
77+
<details>
78+
<summary>Implementation</summary>
79+
80+
81+
<pre><code><b>public</b> <b>fun</b> <a href="../std/internal.md#std_internal_permit">permit</a>&lt;T&gt;(): <a href="../std/internal.md#std_internal_Permit">Permit</a>&lt;T&gt; { <a href="../std/internal.md#std_internal_Permit">Permit</a>() }
82+
</code></pre>
83+
84+
85+
86+
</details>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (c) Mysten Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/// Defines the `Permit` type, which can be used to constrain the logic of a
5+
/// generic function to be authorized only by the module that defines the type
6+
/// parameter.
7+
///
8+
/// ```move
9+
/// module example::use_permit;
10+
///
11+
/// public struct MyType { /* ... */ }
12+
///
13+
/// public fun test_permit() {
14+
/// let permit = internal::permit<MyType>();
15+
/// /* external_module::call_with_permit(permit); */
16+
/// }
17+
/// ```
18+
///
19+
/// To write a function that is guarded by a `Permit`, require it as an argument.
20+
///
21+
/// ```move
22+
/// // Silly mockup of a type registry where a type can be registered only by
23+
/// // the module that defines the type.
24+
/// module example::type_registry;
25+
///
26+
/// public fun register_type<T>(_: internal::Permit<T> /* ... */) {
27+
/// /* ... */
28+
/// }
29+
/// ```
30+
module std::internal;
31+
32+
/// A privileged witness of the `T` type.
33+
/// Instances can only be created by the module that defines the type `T`.
34+
public struct Permit<phantom T>() has drop;
35+
36+
/// Construct a new `Permit` for the type `T`.
37+
/// Can only be called by the module that defines the type `T`.
38+
public fun permit<T>(): Permit<T> { Permit() }
147 Bytes
Binary file not shown.

crates/sui-framework/published_api.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4801,6 +4801,12 @@ sha2_256
48014801
sha3_256
48024802
public fun
48034803
0x1::hash
4804+
Permit
4805+
public struct
4806+
0x1::internal
4807+
permit
4808+
public fun
4809+
0x1::internal
48044810
UQ32_32
48054811
public struct
48064812
0x1::uq32_32

crates/sui-swarm-config/tests/snapshots/snapshot_tests__populated_genesis_snapshot_matches-2.snap

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -240,56 +240,56 @@ validators:
240240
next_epoch_worker_address: ~
241241
extra_fields:
242242
id:
243-
id: "0x41bab75a4999f01b96b0e9fb86616407b1646162329127308bfb83e0bbaf2269"
243+
id: "0xd56f788abad50abeefebdd0d9af9fdbab0fb91f2005da06626fcd933c051a8f9"
244244
size: 0
245245
voting_power: 10000
246-
operation_cap_id: "0xd6f39968901e8a440fe11b4fa7626052c331ee64c54a099b469d6d8250bd826e"
246+
operation_cap_id: "0x16f6724bff899ca38745cb44a2d160ec77121cfc8f4df84e26c57f892dff6a79"
247247
gas_price: 1000
248248
staking_pool:
249-
id: "0x5926424fffede15fe80ebfa20ed336c74c98aa9f2ce28f6662530a0c0fd9c02f"
249+
id: "0xf73b3f3ecb181dc2f0f0567cf90c1f48bac7adc7e38d392b4c99a21111b7bc88"
250250
activation_epoch: 0
251251
deactivation_epoch: ~
252252
sui_balance: 20000000000000000
253253
rewards_pool:
254254
value: 0
255255
pool_token_balance: 20000000000000000
256256
exchange_rates:
257-
id: "0x8e2de2713792615d0245ec30a7784eb0d271dab1a3eb8c0a92829c73fcf6e611"
257+
id: "0x68648c5848c250a2adb1af9f029d7c8536dcfa7a4d177b4b416fb7874a5f5839"
258258
size: 1
259259
pending_stake: 0
260260
pending_total_sui_withdraw: 0
261261
pending_pool_token_withdraw: 0
262262
extra_fields:
263263
id:
264-
id: "0xf05055bdd05ab954963fababc162bfe50164423a3b09cb0b0ad85fcaed9920a2"
264+
id: "0xe8e4e693bdbdc0f6de831e1f886fd15af540cf2cc8328d6d48df89811c30d8fe"
265265
size: 0
266266
commission_rate: 200
267267
next_epoch_stake: 20000000000000000
268268
next_epoch_gas_price: 1000
269269
next_epoch_commission_rate: 200
270270
extra_fields:
271271
id:
272-
id: "0x6ee5e1b2fd2fc0b9bc90f85df23b81247131efd1300c1ff31f7cddfe088c5c2d"
272+
id: "0x897d15f0002f266d5b9b8f66d4a9a707251544836cdf8f8cd91d4475e7f7da79"
273273
size: 0
274274
pending_active_validators:
275275
contents:
276-
id: "0xfc993d4f6b2c43a15c50d27265b3fbe102f98f3e880096fda2651249d7cfc28c"
276+
id: "0xda7c4a25ae9c2f1315eda1c2763ec63d00cc8349db558dfc062e1bf1b294c3d7"
277277
size: 0
278278
pending_removals: []
279279
staking_pool_mappings:
280-
id: "0x6b11d537051c1260bb91f25479ebbe52a57e30f2a4f9d17d77e76c9b96693cc9"
280+
id: "0x62eb7915f8b03fcd877374854407880f5d7043b533673bab36a659bc29ab92af"
281281
size: 1
282282
inactive_validators:
283-
id: "0xf672cf94515c0e99a207ccab019d5e7cd78310fe10a2bd6bca524c5fe69c5849"
283+
id: "0x22c902973d26bf667c737cb6735c6a59148eed5c7f2db2ee48ef1f3f6a3ac1f7"
284284
size: 0
285285
validator_candidates:
286-
id: "0x87d2ae9a8cf6642d06d1b9943f6179c2dd06cc3b58da17a7d14c593edeb07f1d"
286+
id: "0x47c9da179195fa4e938199c422018ffd8132a50e8af0fa3e7a5b0d9e270a6817"
287287
size: 0
288288
at_risk_validators:
289289
contents: []
290290
extra_fields:
291291
id:
292-
id: "0x8e7dfbedf7295c65affc16a595cf3d7c518f789e5b53f79d6114e4d17cf0ff7c"
292+
id: "0x8761485511ea5939399ce1c7b6eaf00ac49692ba3efbf4023382a403eb4834ae"
293293
size: 0
294294
storage_fund:
295295
total_object_storage_rebates:
@@ -306,7 +306,7 @@ parameters:
306306
validator_low_stake_grace_period: 7
307307
extra_fields:
308308
id:
309-
id: "0x293b3b5f09e713d5c5ee4b243cbd25e9a7e96010760ea54399f7a602684deacf"
309+
id: "0x872f9b99082062dbbbc47d43ae7cf499bf12ccb9d54107c040d30e1b2acd27f9"
310310
size: 0
311311
reference_gas_price: 1000
312312
validator_report_records:
@@ -320,7 +320,7 @@ stake_subsidy:
320320
stake_subsidy_decrease_rate: 1000
321321
extra_fields:
322322
id:
323-
id: "0x536eae7cd37967730e534a0e3a14e24b4cab4e01d4739061c4dd1d72588e4c5d"
323+
id: "0x8c1e39e4b7f2adbc9d744bfa8de4970e32bd252a90b522c1f5fcb7e3ccc8cafe"
324324
size: 0
325325
safe_mode: false
326326
safe_mode_storage_rewards:
@@ -332,5 +332,5 @@ safe_mode_non_refundable_storage_fee: 0
332332
epoch_start_timestamp_ms: 10
333333
extra_fields:
334334
id:
335-
id: "0x2bcf2f212c4f178fc6972629ebfdb650235a65581b362982faa159a27b07e4c3"
335+
id: "0xf43e8dea30a07a2ae910e62fe3bc73a880d4aa8a2c147b059cc208a9ad6be0d2"
336336
size: 0
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) Mysten Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// tests that internal::permit can only be called on types internal to the module
5+
6+
//# publish
7+
module 0x0.t {
8+
import 0x1.internal;
9+
10+
struct Internal { dummy_field: bool }
11+
12+
test_success() {
13+
let permit: internal.Permit<Self.Internal>;
14+
label l0:
15+
permit = internal.permit<Self.Internal>();
16+
abort 0;
17+
}
18+
}
19+
20+
//# publish
21+
module 0x0.t {
22+
import 0x1.internal;
23+
import 0x1.string;
24+
25+
test_fail_foreign_type() {
26+
let permit: internal.Permit<string.String>;
27+
label l0:
28+
permit = internal.permit<string.String>();
29+
abort 0;
30+
}
31+
}
32+
33+
//# publish
34+
module 0x0.t {
35+
import 0x1.internal;
36+
37+
struct Internal { dummy_field: bool }
38+
39+
test_fail_permit_type() {
40+
let permit: internal.Permit<internal.Permit<Self.Internal>>;
41+
label l0:
42+
permit = internal.permit<internal.Permit<Self.Internal>>();
43+
abort 0;
44+
}
45+
}
46+
47+
//# publish
48+
module 0x0.t {
49+
import 0x1.internal;
50+
51+
struct Internal { dummy_field: bool }
52+
53+
test_fail_permit_type() {
54+
let permit: internal.Permit<vector<Self.Internal>>;
55+
label l0:
56+
permit = internal.permit<vector<Self.Internal>>();
57+
abort 0;
58+
}
59+
}

0 commit comments

Comments
 (0)