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

[move-compiler] Added linter for accidentally freezing wrapped objects #13194

Merged
merged 12 commits into from
Aug 11, 2023

Conversation

awelc
Copy link
Contributor

@awelc awelc commented Jul 27, 2023

Description

Added a linter signaling a possibility of inadvertently freezing an object that (directly or indirectly) contains other (wrapped) objects. Freezing such object will prevent unwrapping of inner objects.

Added an additional visitor at the hlir level to have easy access to resolved variable types.

Test Plan

A new test has been added.


If your changes are not user-facing and not a breaking change, you can skip the following section. Otherwise, please indicate what changed, and then add to the Release Notes section as highlighted during the release process.

Type of Change (Check all that apply)

  • protocol change
  • user-visible impact
  • breaking change for a client SDKs
  • breaking change for FNs (FN binary must upgrade)
  • breaking change for validators or node operators (must upgrade binaries)
  • breaking change for on-chain data layout
  • necessitate either a data wipe or data migration

Release notes

When building Move code, there are now additional linter warnings related to freezing an object containing (directly or indirectly) other (wrapped) object. Freezing such an object prevents unwrapping of inner objects.

@awelc awelc self-assigned this Jul 27, 2023
@vercel
Copy link

vercel bot commented Jul 27, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
sui-typescript-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 11, 2023 4:49pm
5 Ignored Deployments
Name Status Preview Comments Updated (UTC)
explorer ⬜️ Ignored (Inspect) Visit Preview Aug 11, 2023 4:49pm
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Aug 11, 2023 4:49pm
mysten-ui ⬜️ Ignored (Inspect) Visit Preview Aug 11, 2023 4:49pm
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Aug 11, 2023 4:49pm
sui-wallet-kit ⬜️ Ignored (Inspect) Visit Preview Aug 11, 2023 4:49pm

Comment on lines 28 to 38
("sui", "transfer", "public_freeze_object"),
("sui", "transfer", "freeze_object"),
];
Copy link
Contributor

Choose a reason for hiding this comment

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

Some/all of these names are defined as constants now I believe, so probably best to use those here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed! An artifact of developing this in parallel with another PR that introduced these constants...

Copy link
Contributor

@tzakian tzakian left a comment

Choose a reason for hiding this comment

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

Overall looks good to me -- a couple nits.

Main concern I have is if generic arguments with ability key are handled correctly, but I don't think that should be hard to double-check/fix.

{
// single argument passed by value
let H::Type_::Single(st) = &fun.arguments.ty.value else {
return;
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to make sure I understand here and below: this is returning instead of ICE-ing to let typechecking handle this error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes

crates/sui-move-build/src/linters/freeze_wrapped.rs Outdated Show resolved Hide resolved
};

let sp!(_, tname) = tname;
if let H::TypeName_::ModuleType(mident, sname) = tname {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this cover the case where you try to freeze an object like

struct Wrapper<K: key> has key {
  id: UID,
  field: K,
}

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for this, you should just be able to check that the field has key directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point and I clearly did miss it. Fixed.

};

let sp!(_, tname) = tname;
if let H::TypeName_::ModuleType(mident, sname) = tname {
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for this, you should just be able to check that the field has key directly?

external-crates/move/move-compiler/src/hlir/visitor.rs Outdated Show resolved Hide resolved
external-crates/move/move-compiler/src/hlir/visitor.rs Outdated Show resolved Hide resolved
if let Some((sfields, sloc)) = struct_fields(&sname, &mident, modules) {
for (f, t) in sfields {
if let Some((nested_sname, nested)) =
contains_key(t, modules, /*field_depth*/ 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels a bit wasteful to check everytime? I feel like you should be able to pre-populate all of this information for every time before visiting expressions. In other words:

  • Visit all structs across all modules
    • You will need to do some sort of saturating pass for this I think? Which is maybe why you took this approach you have?
  • Record which have fields with key
  • Visit exps for freeze

Copy link
Contributor

Choose a reason for hiding this comment

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

I would advocate for the approach I laid out over some sort of memoized layer on top of what has been done here in that I would hope what I have suggested is more parallelizable in the future
(it might not look it, but other than a few annoying spots with Context, the pass structure of the compiler is designed to be highly amenable to parallelization (which we need to do some day))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

@@ -0,0 +1,259 @@
// Copyright (c) Mysten Labs, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine to do over HLIR, but I think it will also work over typing?

The typing visitors are run after expansion, so all ability information should be present.
What issue were you anticipating with the typing visitor that caused you to reach for the HLIR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for explaining the subtlety here. Reverted to using typed AST.

crates/sui-move-build/src/linters/freeze_wrapped.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@tnowacki tnowacki left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for the improvements!

return;
};
// see if info about fields of a give struct was already found
let (key_field_info, info_inserted) = self.get_key_field(&mident, &sname);
Copy link
Contributor

Choose a reason for hiding this comment

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

It's fine, but I feel like I would try to encapsulate all of this logic inside of struct_fields somehow? Just feels weird that this area of the visitor knows about the memoization elsewhere

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was a little more complicated than I thought, but I think it does look better now. Thank you for the suggestion! I also did some renaming (from "key_field" to "wrapping_field" which I think is more intuitive, especially considering code comment explanations that were already there). Please take another look if you'd like!

@awelc awelc merged commit 1e1edb7 into main Aug 11, 2023
@awelc awelc deleted the aw/linter-freeze-key branch August 11, 2023 17:06
tnowacki pushed a commit that referenced this pull request Aug 18, 2023
## Description 

The original implementation of the freeze wrapped linter
(#13194) had a bug - arguments to
the transfer function were not processed to look for other cases where
the linter warning should kick in. The case would have to look similarly
to the example below, which makes it pretty unlikely, but still...

```
    public fun freeze_arg(w1: Wrapper, w2: Wrapper) {
        transfer::public_freeze_object({ transfer::public_freeze_object(w1) ; w2});
    }
```

## Test Plan 

Added a test capturing the missing bit (same as example above)

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
damirka pushed a commit that referenced this pull request Aug 22, 2023
## Description 

The original implementation of the freeze wrapped linter
(#13194) had a bug - arguments to
the transfer function were not processed to look for other cases where
the linter warning should kick in. The case would have to look similarly
to the example below, which makes it pretty unlikely, but still...

```
    public fun freeze_arg(w1: Wrapper, w2: Wrapper) {
        transfer::public_freeze_object({ transfer::public_freeze_object(w1) ; w2});
    }
```

## Test Plan 

Added a test capturing the missing bit (same as example above)

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
damirka pushed a commit that referenced this pull request Aug 23, 2023
#13194)

## Description 

Added a linter signaling a possibility of inadvertently freezing an
object that (directly or indirectly) contains other (wrapped) objects.
Freezing such object will prevent unwrapping of inner objects.

Added an additional visitor at the hlir level to have easy access to
resolved variable types.

## Test Plan 

A new test has been added.

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [x] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

When building Move code, additional linter warnings related to freezing
an object containing (directly or indirectly) other (wrapped) object.
Freezing such object will prevent unwrapping of inner objects.
damirka pushed a commit that referenced this pull request Aug 23, 2023
## Description 

The original implementation of the freeze wrapped linter
(#13194) had a bug - arguments to
the transfer function were not processed to look for other cases where
the linter warning should kick in. The case would have to look similarly
to the example below, which makes it pretty unlikely, but still...

```
    public fun freeze_arg(w1: Wrapper, w2: Wrapper) {
        transfer::public_freeze_object({ transfer::public_freeze_object(w1) ; w2});
    }
```

## Test Plan 

Added a test capturing the missing bit (same as example above)

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
ebmifa added a commit that referenced this pull request Aug 29, 2023
## Description 
Adding protocol change highlight to release notes script

## Test Plan 
```
eugene@mac-studio ~/code/sui (eugene/add_protocol_highlight_to_release_notes) $ ./scripts/generate-release-notes.sh releases/sui-v1.7.0-release releases/sui-v1.8.0-release
Sui Protocol Version in this release: XX


#13124:
Add protocol config feature flags for zkLogin to enable testing in Devnet, use updated proof verification logics for zkLogin signature verification.

#13417:

When building Move code, there are now additional linter warnings related to comparing collections from Sui framework code (`Bag`, `Table`, and `TableVec`). Note that this comparison is not a structural one based on the collection content, which is what one might expect, so Sui now indicates this via a linter warning.

#12989:
All transaction execution errors from `execute_transaction_block` of `client-fault` now return a -32002 error code. If you encounter this error code, there is most likely an issue in your transaction inputs.
Previously, when executing a transaction failed on the RPC, you would receive a, "Transaction has non recoverable errors from at least 1/3 of validators" after the transaction failed to execute. You now receive an improved error message, "Transaction execution failed due to issues with transaction inputs, please review the errors and try again: {errors}", where `{errors}` is a string list of actionable errors. After you resolve the errors indicated, your transaction should succeed.

#13194:

When building Move code, there are now additional linter warnings related to freezing an object containing (directly or indirectly) other (wrapped) object. Freezing such an object prevents unwrapping of inner objects.

#12575:

The details included in error messages returned during dependency graph construction might differ from the previous error messages, but they still include similar details and information.


#12933:
Error code designation is updated to support a more cohesive error reporting structure. Internal errors that arise while reading from authority return a `-32603` error code. Client-fault errors that arise while reading from authority return a `-32602` error code. Error strings are not modified.

#13312:

Removes the `--legacy-digest` flag from the `sui client upgrade` and `sui move build` CLI commands, as Sui networks no longer require package digests to be calculated using the legacy algorithm.
```
randall-Mysten pushed a commit that referenced this pull request Sep 6, 2023
## Description 
Adding protocol change highlight to release notes script

## Test Plan 
```
eugene@mac-studio ~/code/sui (eugene/add_protocol_highlight_to_release_notes) $ ./scripts/generate-release-notes.sh releases/sui-v1.7.0-release releases/sui-v1.8.0-release
Sui Protocol Version in this release: XX


#13124:
Add protocol config feature flags for zkLogin to enable testing in Devnet, use updated proof verification logics for zkLogin signature verification.

#13417:

When building Move code, there are now additional linter warnings related to comparing collections from Sui framework code (`Bag`, `Table`, and `TableVec`). Note that this comparison is not a structural one based on the collection content, which is what one might expect, so Sui now indicates this via a linter warning.

#12989:
All transaction execution errors from `execute_transaction_block` of `client-fault` now return a -32002 error code. If you encounter this error code, there is most likely an issue in your transaction inputs.
Previously, when executing a transaction failed on the RPC, you would receive a, "Transaction has non recoverable errors from at least 1/3 of validators" after the transaction failed to execute. You now receive an improved error message, "Transaction execution failed due to issues with transaction inputs, please review the errors and try again: {errors}", where `{errors}` is a string list of actionable errors. After you resolve the errors indicated, your transaction should succeed.

#13194:

When building Move code, there are now additional linter warnings related to freezing an object containing (directly or indirectly) other (wrapped) object. Freezing such an object prevents unwrapping of inner objects.

#12575:

The details included in error messages returned during dependency graph construction might differ from the previous error messages, but they still include similar details and information.


#12933:
Error code designation is updated to support a more cohesive error reporting structure. Internal errors that arise while reading from authority return a `-32603` error code. Client-fault errors that arise while reading from authority return a `-32602` error code. Error strings are not modified.

#13312:

Removes the `--legacy-digest` flag from the `sui client upgrade` and `sui move build` CLI commands, as Sui networks no longer require package digests to be calculated using the legacy algorithm.
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants