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 cli: upstream sui-client-gen #15984

Open
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

kklas
Copy link
Contributor

@kklas kklas commented Jan 30, 2024

Description

This upstreams sui-client-gen from https://github.com/kunalabs-io/sui-client-gen to the sui CLI as a new subcommand sui client-gen.

A new crate has been created (sui-client-gen) that exposes the run_client_gen method which is ran from the sui crate as a clap subcommand.

Test Plan

How did you test the new or updated feature?


If your changes are not user-facing and do not break anything, you can skip the following section. Otherwise, please briefly describe what has changed under the Release Notes section.

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

Copy link

vercel bot commented Jan 30, 2024

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

Name Status Preview Comments Updated (UTC)
mysten-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2024 3:13pm
sui-core ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2024 3:13pm
sui-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2024 3:13pm
4 Ignored Deployments
Name Status Preview Comments Updated (UTC)
explorer ⬜️ Ignored (Inspect) Visit Preview Jun 28, 2024 3:13pm
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Jun 28, 2024 3:13pm
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Jun 28, 2024 3:13pm
sui-typescript-docs ⬜️ Ignored (Inspect) Visit Preview Jun 28, 2024 3:13pm

@kklas
Copy link
Contributor Author

kklas commented Jan 30, 2024

The bigger question I'd have is how to upstream the tests https://github.com/kunalabs-io/sui-client-gen/blob/master/ts/tests/source.test.ts.

These e2e tests are very important. They cover many things, including function call arg encoding for all the different types, calling transactions, fetching objects from chain and various ways of decoding, generics, special types, serialization, upgraded packages, and a bunch of type inferrence. I wouldn't touch the generator without running the tests. It's almost impossible to develop without them.

So the test setup is as follows:

This test setup worked very well for me in my small repo but will probably be an issue here with CI. How do we integrate this here with your testing setup?

@sblackshear
Copy link
Collaborator

The bigger question I'd have is how to upstream the tests https://github.com/kunalabs-io/sui-client-gen/blob/master/ts/tests/source.test.ts.

These e2e tests are very important. They cover many things, including function call arg encoding for all the different types, calling transactions, fetching objects from chain and various ways of decoding, generics, special types, serialization, upgraded packages, and a bunch of type inferrence. I wouldn't touch the generator without running the tests. It's almost impossible to develop without them.

So the test setup is as follows:

This test setup worked very well for me in my small repo but will probably be an issue here with CI. How do we integrate this here with your testing setup?

Hmm, this sounds interesting/tricky. @Jordan-Mysten and @hayes-mysten would probably have the best ideas

@Jordan-Mysten
Copy link
Contributor

@sblackshear For testing, we should probably copy the localnet setup we use for our main products, where we spin up a local network + faucet, and test using that, it shouldn't be too hard to get that dialed in for this.

@kklas
Copy link
Contributor Author

kklas commented Jan 30, 2024

@Jordan-Mysten in that case will you guys do it or can you give me some pointers for where this code should be located and some examples?

I imagine ideally we'd have:

  • the fixture package gets published on the local network + the upgrade is pushed (to test the type name is generated correctly for types introduced in upgrades)
  • the code generated for the fixture package is commited in the repo so that any changes to the generator also show up in the PR (like a snapshot)
  • tests run against sui.js on main so that CI can catch changes to the SDK that would break the generated code (but perhaps we also need some way to pin it because the sui CLI and the SDK have different release cycles)

One problem might arise from the generated "snapshot" code commited to the repo because the package id is hard-coded in many places, so if you try to re-run the generator on a package published on local net it will generate always different ids (unless there's a way to set the published package id deterministically for the test environment?)

@stefan-mysten
Copy link
Contributor

stefan-mysten commented Jan 30, 2024

@kklas Thanks for this great work.

I promise to look more in-depth a bit later, but regarding testing, the CLI has a bunch of tests that use the TestClusterBuilder to spin up a network and work with it as needed. Maybe this can be useful: https://github.com/MystenLabs/sui/blob/main/crates/sui/tests/cli_tests.rs#L2128-L2167

@kklas
Copy link
Contributor Author

kklas commented Jan 30, 2024

Thanks @stefan-mysten. In that case I think it might be best to:

  • copy the whole test setup into the test directory of the sui-client-gen crate (including the whole typescript package for running the tests with jest / vitest, and the fixture move package)
  • start the test from rust where it
    • sets up the local network
    • publishes the fixture packages
    • generates the corresponding code with the tool based on gen.toml
    • does a type check with tsc on the generated code
    • runs the js tests with vitest against the generated code and the local network
    • the generated code is ephemeral and ignored via .gitignore
  • have a separate directory where the "snapshot" of the generated code against a known package would be commited which we can then compare against the one we generate with the current version
    • I think it would be fine to do this against system packages (0x1, 0x2, 0x3, 0xdee9) so that we don't have to have the ability to push the fixture package at a pre-determined address (although it would be great if we could!)

In this setup we don't have CI testing against the current version of sui.js but I think this should be OK because:

  • changes to sui.js that would brake the generated code are rare
  • the users anyways won't update sui.js in their projects immediately
  • if a breaking change to sui.js is detected / reported, bumping the version in the test setup and pushing a patch is fairly straightforward
  • we can always do a more fancy setup later

"#;

pub static LOADER: &str = r#"
import { compressSuiType, parseTypeName } from './util'
Copy link
Contributor

Choose a reason for hiding this comment

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

it might be cleaner to publish all the static/shared files as a new npm package rather than generating them out. The big downside with this is versioning, since now you have a dependency between the generator and the package that has the shared definitions. It wouldn't be much different than the dependency on @mysten/sui.js that already exists, so that might be fine

Copy link
Contributor Author

@kklas kklas Feb 1, 2024

Choose a reason for hiding this comment

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

There's 2 more downsides:

  • users have to install an additional dependency for the generated code (which is a small friction for adoption), and also manually keep it in sync with new versions of generated code
  • there's another npm package that you have to manage

Personally I don't see any advantages to doing it via a separate package (only downsides) so that's why I did it this way, but once it's upstreamed it's up to you. My recommendation is to generate it.

@hayes-mysten
Copy link
Contributor

Testing is a tricky problem for generators, especially when the outputs are inconsistent. I haven't had time to look into it too deeply, but what I would likely do would be:

  • set up an example dapp, with its own move code that needs publishing
  • Use something similar to the typescript SDKs e2e set which includes running localnet and publishing packages in CI
  • update the generator so that the majority of the generated code is stable across multiple runs.
    • this would basically just mean generating all the IDs into separate files, and then having IDs be imported rather than referenced directly inline in the rest of the generated code
  • check in everything from the generated code for your test dapp, except for the files that contain the IDs
    • this lets you run the build during development, but only see diffs if you change the generator
  • Have a full CI setup for your test dapp that works like any other JS library/app
    • run tsc build to type-check it
    • write tests that use various parts of the generated code to test the generated code works as intended
    • ensure that the tests are also type-checked to help catch any type issues in the generated code
    • potentially use something like https://github.com/arktypeio/arktype/tree/beta/ark/attest#readme to test the types more directly

@kklas
Copy link
Contributor Author

kklas commented Feb 1, 2024

@hayes-mysten so from what I understand, your setup is actually very similar to what I described above, with the difference being that the e2e tests would live in the SDK e2e directory instead of within the rust crate. I think that this could also work well, the main difference being we'd have to run the generator with cargo run during test setup, instead of natively by calling a rust method. On the plus side, we don't have to create a separate TS package within the crate to host the tests and testing against the current version of sui.js seems more feasable here if that's something we'd want to do. Everything else seems about the same. I used a similar setup for anchor-client-gen and it worked well with CI (although there you can have deterministic package ids).

check in everything from the generated code for your test dapp, except for the files that contain the IDs

Clever, I'd have to double check but I think that would work well. IDs are hard coded in some places but they can be easily imported (there's already a separate file with IDs).

potentially use something like https://github.com/arktypeio/arktype/tree/beta/ark/attest#readme to test the types more directly

This is cool, I didn't know about it.

set up an example dapp, with its own move code that needs publishing
write tests that use various parts of the generated code to test the generated code works as intended

We have this already pretty much with the current tests. Creating an example app is probably not necessary IMO because pretty much all of it should be covered with the existing tests unless perhaps you want to test that composition of generated code in a real life app works correctly or something (but I guess you can also do that with normal tests).

Copy link
Contributor

github-actions bot commented Apr 2, 2024

This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale label Apr 2, 2024
@stefan-mysten stefan-mysten added cli Command line tools and removed Stale labels Apr 2, 2024
@stefan-mysten
Copy link
Contributor

@kklas we still want to merge this, but sorry we dropped the ball here and thanks for your patience.
@hayes-mysten - from testing perspective, anything else you see that's needed?

@hayes-mysten
Copy link
Contributor

@stefan-mysten yes, we definitely need to add testing. I haven't had the time to set this up yet, but we definitely want to have testing that validates both the generated code, and that the generated code runs correctly, and that type-checking on the generated code with typescript works as expected. I've been pretty focused on work to get ready for a 1.0 release of the SDK, and the GraphQL migration, but I'll see if I can find some time in the next few weeks to make some progress here

@stefan-mysten
Copy link
Contributor

@stefan-mysten yes, we definitely need to add testing. I haven't had the time to set this up yet, but we definitely want to have testing that validates both the generated code, and that the generated code runs correctly, and that type-checking on the generated code with typescript works as expected. I've been pretty focused on work to get ready for a 1.0 release of the SDK, and the GraphQL migration, but I'll see if I can find some time in the next few weeks to make some progress here

Awseome. We definitely want this in, so looking forward to your support with testing here.

@hayes-mysten
Copy link
Contributor

Sorry it's taken me so long to get around to looking into the test set up. I'm going to try to start setting up something today

Copy link

vercel bot commented Jun 28, 2024

@kklas is attempting to deploy a commit to the Mysten Labs Team on Vercel.

A member of the Team first needs to authorize it.

@stefan-mysten
Copy link
Contributor

stefan-mysten commented Jun 28, 2024

@kklas, thanks for keeping working on this! What do you think it is left to get this ready to merge?

@kklas
Copy link
Contributor Author

kklas commented Jun 28, 2024

@hayes-mysten I've made the test run against localnet:

  • rebase
  • removed all hard-coded IDs in generated code and instead referenced PKG_V{X} constant in respective index.ts. This gets us close to dynamic env switching also -- you could do it in a hacky way already by changing pkg id constants to vars and changing them manually (although could get tricky for types introduced in upgrades)
  • created a prepare.ts script that publishes the package to localnet, generates the code, and then uses sed to change the package ID variables in index.ts for the relevant package in generated code. I've used tsup for the script, feel free to reorganize to better match the repo setup.
  • removed all unneeded packages and examples

What do you think it is left to get this ready to merge?

This is perhaps not a blocker here but having snapshot tests would be a good idea.

@stefan-mysten
Copy link
Contributor

What kind of snapshots are you thinking of? (need to read the code a bit, I lost a lot of the context over time).

@kklas
Copy link
Contributor Author

kklas commented Jun 28, 2024

Something like this:

  • generate code for the fixture package and commit to repo
  • on each change to generator, regenerate snapshot so that diff is visible in the PR and gets commited
  • run regenerate in CI and if there's a diff from what is in the repo, fail (diff wasn't commited)

@semgrep-code-mystenlabs
Copy link

Semgrep found 3 ssc-efa14576-9601-4ae6-939c-3da58aa25013 findings:

Risk: Affected versions of vite are vulnerable to Improper Handling Of Case Sensitivity / Exposure Of Sensitive Information To An Unauthorized Actor / Improper Access Control. The vulnerability arises when the Vite development server's option, server.fs.deny, can be circumvented on case-insensitive file systems through the utilization of case-augmented versions of filenames, as the matcher derived from config.server.fs.deny fails to prevent access to sensitive files when raw filesystem paths are requested with augmented casing.

Manual Review Advice: A vulnerability from this advisory is reachable if you host vite's development server on Windows, and you rely on server.fs.deny to deny access to certain files

Fix: Upgrade this library to at least version 4.5.2 at sui/examples/trading/frontend/pnpm-lock.yaml:4700.

Reference(s): GHSA-c24v-8rfc-w8vw, CVE-2023-34092, CVE-2024-23331

Ignore this finding from ssc-efa14576-9601-4ae6-939c-3da58aa25013.

Semgrep found 2 ssc-aff5e8de-c638-4356-8a93-120597e35ce9 findings:

Risk: Affected versions of @babel/traverse are vulnerable to Incomplete List Of Disallowed Inputs. An attacker can exploit a vulnerability in the internal Babel methods path.evaluate() or path.evaluateTruthy() by compiling specially crafted code, potentially resulting in arbitrary code execution during compilation.

Manual Review Advice: A vulnerability from this advisory is reachable if you use a 3rd party plugin that relies on the path.evaluate()or path.evaluateTruthy() internal Babel methods, or one of the known affected plugins (@babel/plugin-transform-runtime, Any 'polyfill provider' plugin that depends on @babel/helper-define-polyfill-provider, or @babel/preset-env when using its useBuiltIns option)

Fix: Upgrade this library to at least version 7.23.2 at sui/pnpm-lock.yaml:3959.

Reference(s): GHSA-67hx-6x53-jw92, CVE-2023-45133

Ignore this finding from ssc-aff5e8de-c638-4356-8a93-120597e35ce9.

Semgrep found 1 ssc-5a557c33-4191-4714-a574-8efb44cf209b finding:

Risk: Affected version of get-func-name is vulnerable to Uncontrolled Resource Consumption / Inefficient Regular Expression Complexity. The current regex implementation for parsing values in the module is susceptible to excessive backtracking, leading to potential DoS attacks.

Fix: Upgrade this library to at least version 2.0.1 at sui/pnpm-lock.yaml:16906.

Reference(s): GHSA-4q6p-r6v2-jvc5, CVE-2023-43646

Ignore this finding from ssc-5a557c33-4191-4714-a574-8efb44cf209b.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cli Command line tools
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants