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

Make it possible to build against on-chain dependencies #14178

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from

Conversation

kklas
Copy link
Contributor

@kklas kklas commented Oct 10, 2023

Description

Context https://gist.github.com/kklas/d9edad7875548fae57b0c86bc8871fea

Unresolved issues and discussion points:

(1) Due to how dependencies are resolved, some address mappings don't propagate properly through the graph when the same package exists as on-chain and source (transitive) dependency. This happens becuase the dependency graph treats packages of the same name and version as the same regradless of their location so sometimes the on-chain package ends up in the resulting package_table and since those don't have address names defined, it can cause undefined address name errors in the parent source packages. I alleviated this a bit by adding names for system packages ("std", "sui", "sui_system", and "deepbook") to the generated manifest in 2623a91 but this doesn't solve the problem for all packages. It could be perhapse solved by keeping track of all the instances of the same package during dependency resolution and then resolving the addresses by collecting them from all. This is simple in principle but could get tricky to implement because overrides and address renamings also need to be respected. This could also be solved with a source discovery service where we could fetch the names from. In any case, the user can always do an override with a source package to go around this issue.

(2) There is now a conflict between old and new lockfiles. The old ones will use non-resolved names, so when building a package with the new binary and dependencies have lockfiles it will cause an incosistency. This is because lockfiles are only regenerated based on manifest and dependency manifest digests, which don't change here. This can be solved by bumping the lockfile version or forcing lockfile regeneration on resulting lockfile contents change https://github.com/MystenLabs/sui/blob/main/external-crates/move/tools/move-package/src/resolution/dependency_graph.rs#L240-L241

(3) Lockfiles don't store package's original name, so when loading dependency graph from lockfiles, error messages will print out resolved names instead of original which will be confusing to the user. I illustrated this issue in b5c3093. This can be solved by adding original package names to lockfiles.

(4) I've made only an in-memory cache for on-chain dependencies and each is fetched once per run for simplicity and seems fast enough. They can easilly be cached to disk in ~/.move though with a bit of consideration about consistency. System packages can also be embedded in the binary to avoid RPC fetching.

(5) The version field can now be removed from all manifests in this repo. Building with the old binary will cause an error in that case. LMK if you want me to do that. Otherwise it will just cause an extra field warning when building with the new binary.

(6) To avoid confusion with variable names, the custom_resolve_pkg_name hook should perhaps be called resolve_pkg_identifier hook and identifier should be used in place of pkg_name and resolved_name etc.

(7) move-analyzer doesn't work with both custom hooks and bytecode dependencies. I've managed to make it work with custom with a hacky solution where I've copied the whole crate to a new one and made it use the hooks (it required, among other things, to make it use tokio). But it still didn't work because it has some issues probably with interpreting the bytecode and while the server works it throws errors. I didn't dig deeper.

(8) sui move test doesn't work with on-chain packages. This is because of two separate reasons:

  • First is that often the MoveStdlib package (0x1) ends up being included as an on-chain dependency which means that #[test_only] modules aren't included, but the test runner requires the std::unit_test module and fails with Compilation in test mode requires passing the UnitTest module in the Move stdlib as a dependency
  • The second is due to the topo sort in external-crates/move/tools/move-unit-test/src/test_runner.rs:83 that relies on move-bytecode-utils/src/dependency_graph.rs stack trace. Similar why publish was failing (and fixed in 6b28139) it is because the compiler doesn't return the bytecode modules in the result and the graph construction fails due to missing dependency.

Both of these can fortunately be solved by doing an appropriate override, but the second issue means that we can't do unit tests when on-chain / bytecodes are present until this is resolved (it's very solveable though). The first issue can be solved by including the source for 0x1 instead of bytecode (and also probably for 0x2, 0x3 and other framework packages) but there's some work to figure out how to embed the source code in the binary (and which version of it as there may be discrepencies between networks).

Test Plan

Unit and integration tests.


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

@vercel
Copy link

vercel bot commented Oct 10, 2023

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 Nov 24, 2023 4:21pm
sui-core ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 24, 2023 4:21pm
sui-typescript-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 24, 2023 4:21pm
3 Ignored Deployments
Name Status Preview Comments Updated (UTC)
explorer ⬜️ Ignored (Inspect) Visit Preview Nov 24, 2023 4:21pm
multisig-toolkit ⬜️ Ignored (Inspect) Visit Preview Nov 24, 2023 4:21pm
sui-kiosk ⬜️ Ignored (Inspect) Visit Preview Nov 24, 2023 4:21pm

Copy link
Contributor

@rvantonder rvantonder left a comment

Choose a reason for hiding this comment

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

High-level: Thinking about how we can chop this out to make iterative progress, it looks like quite a few commits could be factored out and merged cleanly on their own as preparation for the core changes--especially the ones propagating info for error messages and code shuffling (54a97f3). So, re: discussion points:

(1) & (2) I don't have good recommendations on these yet, will chew on it a bit more.

(3) I think this is a separable problem + solution that could work nicely, ando go in a separate PR for prep

(4) Seems reasonable--the default expectation for devs right now is to compile against source, so that is always an available fallback while we're working towards a v0 for compiling against on-chain deps. I.e., perf considerations can be a fast follow

(5) I think this is OK--we need to take care of removing references from docs / code in the Sui repo and also communicate the change in Changelogs, etc. though. Emitting a warning instead of a hard error in a next release would be a bit more user-friendly, followed by a hard error in a subsequent release.

(6) Sounds good--these renames seem like another set of candidate changes that would be great to separate and merge before the core functional changes.

To summarize, I wonder if we can create separate PR(s) for the mechanical changes required, with the core changes following up. My sense is that might make it easier to think / reason about the core code changes and dealing with (1) and (2), and also to give room for input from @amnn.

Comment on lines 581 to 594
let (src_deps, bytecode_deps): (Vec<_>, Vec<_>) = deps_package_paths
.clone()
.into_iter()
.partition_map(|(p, b)| if b { Either::Left(p) } else { Either::Right(p) });
// If bytecode dependency is not empty, do not allow renaming
if !bytecode_deps.is_empty() {
if let Some(pkg_name) = resolution_graph.contains_renaming() {
anyhow::bail!(
"Found address renaming in package '{}' when \
building with bytecode dependencies -- this is currently not supported",
pkg_name
)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

High-level comment: Any thoughts on introducing an enum / variant to distinguish between source and bytecode dependencies? E.g., something like Source/LocalSource and Bytecode/OnChainBytecode dependencies?

Conceptually I'd love if we can discriminate at the type-level, though I'm not sure how this trickles down into the implementation changes--I think you have a better intuition on that at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This commit in particular I have cherry picked from upstream so I'm also not super familiar with details here. I'd rather leave it as is and perhaps do this change some other time.

)>,
) -> Result<(
/* sources */ PackagePaths,
/* deps */ Vec<PackagePaths>,
/* deps */ Vec<(PackagePaths, bool)>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto for: Thoughts on using an enum type to discriminate paths/dependencies to replace something like src_flag : bool?

@@ -128,7 +127,7 @@ impl PartialEq for Package {
// comparing packages during insertion of externally resolved ones - an internally resolved
// existing package in the graph would not be recognized as a potential different version of
// the externally resolved one)
self.kind == other.kind && self.version == other.version
Copy link
Contributor

Choose a reason for hiding this comment

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

High-level comment on this commit: I'm a big fan of putting up this PR separately before everything else since it's clean / self-contained. We need to cover our bases with how this affects users / manifests that contain version. I.e., great if it's vestigial and we can conceptually remove it. To go along with that change, for example, we need to remove references to version in the sui repo in examples and elsewhere: https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/+file:Move%5C.toml+version+-repo:diem+-repo:aptos&patternType=standard&sm=1&groupBy=repo and communicate the change in the changelog

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To go along with that change, for example, we need to remove references to version in the sui repo in examples and elsewhere

As far as I'm concerned we can do that but we need to consider is that old versions of the tool will then error when building packages against master because version field is mandatory.

Comment on lines 74 to 83
pub(crate) fn custom_resolve_pkg_name(
pkg_path: &PathBuf,
manifest: &SourceManifest,
) -> anyhow::Result<Symbol> {
if let Some(hooks) = &*HOOKS.lock().unwrap() {
hooks.custom_resolve_pkg_name(pkg_path, manifest)
} else {
Ok(manifest.package.name)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems reasonable!

Comment on lines 140 to 142
/// Original dependency name as defined in parent manifest since it can be different from the
/// resolved name. Used for printing user-friendly error messages.
pub dep_orig_name: PM::PackageName,
Copy link
Contributor

Choose a reason for hiding this comment

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

This commit looks like something great we can ship outright as preparation for compiling against on-chain dependencies, i.e., in separate PR. That would help reduce the footprint / size of the core feature and PR at the end!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This issue only happens when custom_resolve_pkg_name hook is used and returns something that's different than the manifest so it might not make sense to ship it before the hook code (that PR would be confusing).

@kklas
Copy link
Contributor Author

kklas commented Oct 16, 2023

High-level: Thinking about how we can chop this out to make iterative progress

It should be possible to merge each of these commits on their own. A cool thing is that everything is fully backwards compatible until custom Sui hooks get implemented. But I think everything should probably be commited within the same version cutoff and some consideration be taken about the rollout (because e.g. of (2), (3), (5)).

The downside of splitting up the PR is that there is some overhead in getting indiviual PRs to be mergable, but I can do that if you think this will make the overall process easier. Here's how I think commits can be groupped up into separate PRs:

1
[cherry-pick][move] enable bytecode as dependencies

2
[move-package] remove version from manifest package section and dependency
[move-package] fix tests for version removal

3
[move-package] fix docstring ascii being parsed as doctest

4
[move-package] add custom_resolve_pkg_name hook
[on-chain-deps] add tests for custom_resolve_pkg_name hook

5
[on-chain-deps] use original package names in resolution error messages
[on-chain-deps] use original root pkg name in dependency graph error messages
[on-chain-deps] use original root pkg name in resolution graph error messages
[on-chain-deps] add a test for pkg name resolution conflict from lockfiles

6
[on-chain-deps] collect overrides from collect_graphs

7
[on-chain-deps] add resolve_version hook
[on-chain-deps] add tests for version resolution
[on-chain-deps] use versions in dimanod_problem_dep_transitive_nested_override test

8
[on-chain-deps][refactor] store orig pkg name with DependencyGraphInfo to simplify function calls

9
[on-chain-deps] change Custom dependency to OnChain

10
[on-chain-deps] implement sui package hooks
[on-chain-deps] add addresses for system packages to generated manifest
[on-chain-deps] exclude on-chain dependencies from source verification

These can be amended to some existing commits:
[on-chain-deps] remove pkg_path param from name and version hooks
[on-chain-deps] run cargo format

@kklas
Copy link
Contributor Author

kklas commented Oct 16, 2023

I've added unresolved issue / discussion point (7).

@rvantonder
Copy link
Contributor

rvantonder commented Oct 24, 2023

Thanks for your patience!

The downside of splitting up the PR is that there is some overhead in getting indiviual PRs to be mergable, but I can do that if you think this will make the overall process easier.

So I'd love if we could tackle this bit-by-bit and make it a bit more digestible for review; I do think we'll need to do that to make progress here (reviewing it all is a bit intimidating for me to review personally 😅) and the codebase can shift and cause conflicts (which looks like already happened).

A cool thing is that everything is fully backwards compatible until custom Sui hooks get implemented. [... some consideration be taken about the rollout (because e.g. of (2), (3), (5)) ]

That is great. I think it's reasonable to bundle if it doesn't have user-visible impact and turns out to be relatively small (something like less than 1KLOC change. this isn't a hard and fast rule, I'm just trying to give an idea). Considering the user-visible impact of (2), that might not be the case. Side question: do we strictly need (2) to enable on-chain dependencies? If not, we might consider punting on this so it's not blocking the actual functionality.

But I think everything should probably be commited within the same version cutoff

I agree with the convenience but it might be a bit difficult to pull off in practice, I think we have some options here:

  • guard the new functionality behind a flag, allowing incremental implementation / iteration without affecting functionality until it's complete (my personal preference). Overhead is including the flag, but it makes things manageable without burden / pressure to review for a particular version cutoff.
  • structure review with separate PRs that build on each other, with review / approval allowing to merge PRs into a base PR until it's all ready, and a final approval of the base PR. This will need some overhead to set up, and also to avoid making intermediate changes between PRs, because that will probably require a lot of rebasing on your part. It will help make review manageable though.

I'm not very confident about a big PR with separate commits, because it makes review very difficult to isolate and incorporate changes that come with feedback.

I'm also curious, to what extent you think some of the discussion points could be helped by having a feature flag on the implementation. E.g., to explicitly warn on known limitations.

Let me know your thoughts!

@kklas
Copy link
Contributor Author

kklas commented Oct 24, 2023

Considering the user-visible impact of (2), that might not be the case. Side question: do we strictly need (2) to enable on-chain dependencies?

Yes, it is stricly a problem to enable on-chain deps because once you enable the custom hooks, the "package name" gets overwritten with its "original-id" hence the inconsistency. Not a problem though untill the on-chain resolution hooks get implemetned.

guard the new functionality behind a flag

I don't think even this will be necessary because everything's backwards compatible until you add the on-chain resolution hooks. Except perhaps the version field removal which will throw "unrecognized field in manifest" warnings, but even then we can get rid of those by registering "version" as a custom field with the hook (similar to "published-at").

structure review with separate PRs that build on each other,

I'm not a fan of this approach because you still then need to merge the base PR into main which will require another look / review / rebase. Kinda defeats the purpose of creating multiple PRs.

I'm also curious, to what extent you think some of the discussion points could be helped by having a feature flag

(1) - if you do an appropriate override it will fix the problem
(2) - this needs to be fixed before we can enable on-chain resolution hooks because builds will break
(3) - this is a problem when you have on-chain deps in your graph and there's a dependency conflict error
(4) - is fine
(5) - it's up to you, we can define "version" as custom manifest field to make the warning go away
(6) - it's up to you
(7) - is a problem only when there are on-chain deps in the graph
(8) - is a problem when on-chain hooks are enabled and also probably needs to be fixed

(1) , (3), (4), (6) are only a problem when user has on-chain deps in manifest / graph
(2), (7), (8) are a problem when the on-chain resolution hooks are enabled
(5) is a problem when the commit lands

@rvantonder @amnn I'm happy to start publishing separate PRs for this, but I'd like to first have some general plan or agreement on how we're going to go about these unresolved issues, because I'd like to avoid the situation where we have to change the code landed in these PRs after the fact based on how we're going to solve these.

@rvantonder
Copy link
Contributor

rvantonder commented Oct 25, 2023

Thanks for the detailed breakdown, that's really helpful and clear! About resolving outstanding issues, like move-analyzer choking--that's tricky! For this, and maybe other issues that cause friction, it seems like there are two routes: (a) go deeper down the rabbit hole to resolve things (like with move-analyzer) or (b) punt for now and accept that compiling with on-chain dependencies might lead to a poor user experience here (we can explicitly list known limitation of compiling against on-chain dependencies, and mark it as an experimental mode for compiling). Right now, I don't think we have dedicated resources to devote to resolving issues in move-analyzer ourselves, but maybe in the future 🥲 . So I'm not opposed to (b), for example, as long as we're upfront about the limitations / state of implementation.

I'm not a fan of this approach because you still then need to merge the base PR into main which will require another look / review / rebase.

Yep, makes sense!

@kklas
Copy link
Contributor Author

kklas commented Oct 25, 2023

So I'm not opposed to (b), for example, as long as we're upfront about the limitations / state of implementation.

I agree with this. Something with bad UX is still better than nothing. I'm actually using the toolchain from this PR to build a package with on-chain deps, and although it's a bit inconvenient without move-analyzer it's alright.

Anyway, I have found another issue marked with (8). I will look into it further when I find some time.

@rvantonder
Copy link
Contributor

Anyway, I have found another issue marked with (8).

Gotcha, this one seems like a bit of a bummer. In an event, I think we're agreed on "on-chain deps support in an imperfect state is better than nothing" and as long as the code path is relatively clean for supporting that, I think it's reasonable to go ahead with PRs that start chopping up the feature for review.

…dency

Removed `version` field from `[package]` section and from dependency
specification (`DepName = { .. version = "..." }`). Version is vestigial
and this is preparation for the version resolution hook to be
introduced.
Introduced the `custom_resolve_pkg_name` hook. This hook is called
during dependency graph resolution and has the effect of changing the
package name to the value returned from the hook (instead of the one
defined in its manifest).
When using pkg name resolution, dependency error messages during graph
resolution will print resolved names instead of the original ones as
defined in manifests which will be confusing to the user. This commit
makes it so that original package names are used. This is achieved by
storing the original name in the `Dependency` struct which is the edge
between two packages in the graph. This way the original name can
always be recovered.
…messages

Store original name of the root package in the `DependencyGraph` so that
it can be used for displaying error messages in the resolution graph.
Moved `collect_overrides` functionality to a more natural place. This is
used for resolve_version hook implementation later so that the manifest
doesn't have to be parsed again.
Implemented the version resolution hook. This hook is called during
dependency graph resolution and returns an arbitrary version (`Symbol`)
for a package. This is then used by the resolved to check that two
different instances of the same package are of the same version.

The version hook effectively makes it possible to reference the same
package in different locations (e.g., git, local, or on-chain). As long
as their name and version matches, they will be considered the same
package (respective of the address renaming and override flag).

When the version hook isn't used (returns `None`), packages will be
differentiated as they were before the introduction of the hook based
on their location (dependency kind in parent manifest).
…_override test

This test makes more sense with version resolution.
…files

This test highlights the problem of error messages using resolved pkg
names instead of original when dependnecy lock files are present. This
can be resolved by storing original pkg names in lockfiles.
Hooks should only rely on manifest (or possibly lockfile).
Refactor `Custom` dependency to `OnChain` so that RPC doesn't have to be
passed in manually for every dependency in the manifest.
Implements `resolve_on_chain_dependency`, `custom_resolve_pkg_name`, and
`resolve_version` hooks for Sui so that on-chain dependencies are
supported.

This is achieved by resolving dependency names to their `original_id`
(the id if package version 1) and their version to their on-chain
version when the `published-at` field is present in their manifest.
In effect, this consolidates the dependency graph so that on-chain and
source transitive dependencies can get deduplicated by changing the
names of source dependencies to their `original_id` and assigning them
their on-chain version.

On-chain dependencies are resolved by fetching their contents from the
RPC to their respective location in `~/.move/` directory. RPC from
current active environment is used.
This alleviates a bit the problem where the dependency graph picks an on-chain
package as dependency for a source package (instead of source) when both
are present in the graph which causes undefined address name errors.
It does not solve the problem for all packages, but in the worst case,
user can use an override until a proper solution is worked out.
rvantonder pushed a commit that referenced this pull request Jan 16, 2024
…ssages (#15708)

## Description 

Pass down original name of the root package during dependency resolution
so that it's displayed correctly in error messages (instead of resolved
name). This commit only affects the printed error messages and not
functionality of the toolchain.

This is part of the work to enable compiling against on-chain
dependencies #14178.

@amnn @rvantonder

## Test Plan 

Unit tests.

---
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
rvantonder pushed a commit that referenced this pull request Jan 19, 2024
…gs (#15750)

## Description 

Store original name of the root package in the `DependencyGraph` so that
it can be used for displaying error messages in the resolution graph.
This commit only affects the printed error messages and not
functionality of the toolchain.

This is part of the work to enable compiling against on-chain
dependencies #14178.

cc @rvantonder @amnn 

## Test Plan 

Added a unit test

---
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
rvantonder pushed a commit that referenced this pull request Jan 23, 2024
## Description 

Moved `collect_overrides` functionality to a more natural place. This is
used for resolve_version hook implementation later so that the manifest
doesn't have to be parsed again.

This is part of the work to enable compiling against on-chain
dependencies #14178.

## Test Plan 

It's a pure refactor. Ran unit tests.

---
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
rvantonder pushed a commit that referenced this pull request Jan 31, 2024
## Description 

Implemented the version resolution hook. This hook is called during
dependency graph resolution and returns an arbitrary version (`Symbol`)
for a package. This is then used by the resolved to check that two
different instances of the same package are of the same version.

The version hook effectively makes it possible to reference the same
package in different locations (e.g., git, local, or on-chain). As long
as their name and version matches, they will be considered the same
package (respective of the address renaming and override flag).

When the version hook isn't used (returns `None`), packages will be
differentiated as they were before the introduction of the hook based on
their location (dependency kind in parent manifest).

This is part of the work to enable compiling against on-chain
dependencies #14178.

## Test Plan 

Added unit tests

---
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
rvantonder pushed a commit that referenced this pull request Feb 2, 2024
…kg_id` (pure refactor) (#16037)

## Description 

This is the famed rename from `name` to `identifier`, and boy am I glad
we went for this because the code is 10x more readable now. In summary,
it changes `*_pkg_name` -> `*_pkg_id` and `*_pkg_original_name` ->
`*_pkg_name`.

In the second commit, I've found additional places where (what is now)
`pkg_id` was being used in error messages instead of name so I switched
those around. These don't show up in the unit tests because there aren't
any that trigger those edge cases but it should be fine because it's
clear from the code that these affect only error messages (in a good
way) and not functionality of the resolver.

The only thing that remains is that we still use the `name = <...>`
field in the lockfile for (what is now) `id`. I didn't want to touch
this here because it would be a breaking change for the lockfile. In the
next PR I'll be adding the additional fields to the lockfile that we
discussed and switch this around.

This is part of the work to enable compiling against on-chain
dependencies #14178.

## Test Plan 

Unit tests

---
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
@kklas
Copy link
Contributor Author

kklas commented Feb 2, 2024

@rvantonder @amnn so for adding package names and root resolved id and version to the lockfile, I had something like this in mind:

image

In summary we:

  • add a new root field at the top level of lockfile which will contain the resolved id and version of the root package
    • this is needed just for the external resolver and will be leveraged here to load the corract thata into the graph (for non-external we resolve them via hooks with manifest)
  • in the dependencies field of each package (and root):
    • the name field will be renamed to id because that's what effectively is since after the id resolution hook has landed
    • another field is added called name which will store the original package name (as defined in its manifest) for error messages (a note on this below [1])
      • this will be used here and other similar places in read_from_lock to load the correct data into the graph (edges)
  • in each package section we rename the name field to id that uniquely identifies a package

[1] Now a question may arise: "why are package names stored in the dependencies section of each parent package instead of the package itself?". The reason for that is that package names are, in the graph, stored in edges betwee the nodes (packages). It was done this way in the "id resolution hook" PR because it's a more natural solution implementation wise (storing them in the package would be possible in principle but a way more intrusive implementation), and also because in principle it is the more correct solution. To illustrate this I will give an example.

Suppose we're resolving a graph with both a source and on-chain transitive dependency to Foo package. In case of the source dependency we can defenitively load its name from the manifest as Foo (and there is a consistency check for that in resolved_graph.rs here), but when the same dependency is loaded from an on-chain reference, its name doesn't exist (on-chain) and there's nothing we can check against. So in case of on-chain dependencies we allow for arbitrary names in the parent manifest, and store this name in the edge in the graph (Dependency struct here) instead of the node (Package struct here) so that this info is retained for constructing correct error messages (and possibly other things in the future).

Therefore, when constructing the lockfile, it is also more natural store the dependency names in the edges (dependencies list of each packages) instead of the package section, and retain this information so that the graph can be faithfully reconstructed from the lockfile.

@rvantonder
Copy link
Contributor

Thanks @kklas, I quickly went over that and sounds reasonable to me, in general! I'll go over it a bit more deeply considering our plans to add more to the lock file here. My overarching comment is that we want to namespace resolution by network (chain identifier), so there will be a multiplicity of move packages we track in the lock file going forward.

@rvantonder
Copy link
Contributor

Update this side @kklas: we're going over some designs for the Move.lock around tracking addresses and this overlaps a bit. Will report back once we have more clarity from our internal discussions, soon!

bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
…fest sections (#15148)

## Description 

This PR removes the version field both from package section and
dependency items in manifest (e.g. `SomeDep = { local = "../dep",
version = "0.0.1" }`).

Why is this safe to do?

Well, the version field in the package section isn't used anywhere. It's
not read anywhere in the codebase and thus not propagated through the
toolchain.

As for the version in dependency item, what it does it makes the
dependency graph throw a version conflict when the same package is
referenced with two different versions in the dependnecy graph. There
are 3 types of dependencies (`Local`, `Git`, and `Custom`) out of which
only `Local` and `Git` are used on Sui. Since referencing a different
version of a dependency is already possible with git and local by
specifying a different location, this version field isn't useful.

I've also added `version` as a custom field in Sui hooks in order to
make the `unknown field name found` warning go away when compiling
packages with `sui move`. This should be removed once all `version`
fields are removed from all manifests in this repo. This will be a
breaking change for users running the old version of the toolchain so
it's probably best to do that a bit later.

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

cc @amnn @rvantonder 

## Test Plan 

Unit tests.

Some tests (like the `diamond_problem_dep_dev_override_with_reg`) were
using the `version` field to create a version conflict while using a
package in the same location. I've refactored those tests to instead
refer to the same package in different location.

---
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

`Move.toml` files no longer require a `version` field in the `[package]`
section and will warn at the presence of a `version` field in a
`[dependency]` definition. Full PR description:
MystenLabs/sui#15148.
bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
## Description

Adds a `custom_resolve_pkg_name` hook in order to allow for the
dependency graph to discriminate between packages based on a dynamically
resolved symbol (returned by the hook) rather than just package name.
When the hook isn't defined it returns the package manifest name when so
this doesn't affect Sui package resolution currently. This will make it
possible to consolidate source and on-chain packages (which don't have a
name) within a single graph.

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

## Test Plan 

Added unit tests.

---
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
bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
…ssages (#15708)

## Description 

Pass down original name of the root package during dependency resolution
so that it's displayed correctly in error messages (instead of resolved
name). This commit only affects the printed error messages and not
functionality of the toolchain.

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

@amnn @rvantonder

## Test Plan 

Unit tests.

---
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
bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
…gs (#15750)

## Description 

Store original name of the root package in the `DependencyGraph` so that
it can be used for displaying error messages in the resolution graph.
This commit only affects the printed error messages and not
functionality of the toolchain.

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

cc @rvantonder @amnn 

## Test Plan 

Added a unit test

---
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
bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
## Description 

Moved `collect_overrides` functionality to a more natural place. This is
used for resolve_version hook implementation later so that the manifest
doesn't have to be parsed again.

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

## Test Plan 

It's a pure refactor. Ran unit tests.

---
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
bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
## Description 

Implemented the version resolution hook. This hook is called during
dependency graph resolution and returns an arbitrary version (`Symbol`)
for a package. This is then used by the resolved to check that two
different instances of the same package are of the same version.

The version hook effectively makes it possible to reference the same
package in different locations (e.g., git, local, or on-chain). As long
as their name and version matches, they will be considered the same
package (respective of the address renaming and override flag).

When the version hook isn't used (returns `None`), packages will be
differentiated as they were before the introduction of the hook based on
their location (dependency kind in parent manifest).

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

## Test Plan 

Added unit tests

---
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
bmwill pushed a commit to move-language/move-sui that referenced this pull request Apr 18, 2024
…kg_id` (pure refactor) (#16037)

## Description 

This is the famed rename from `name` to `identifier`, and boy am I glad
we went for this because the code is 10x more readable now. In summary,
it changes `*_pkg_name` -> `*_pkg_id` and `*_pkg_original_name` ->
`*_pkg_name`.

In the second commit, I've found additional places where (what is now)
`pkg_id` was being used in error messages instead of name so I switched
those around. These don't show up in the unit tests because there aren't
any that trigger those edge cases but it should be fine because it's
clear from the code that these affect only error messages (in a good
way) and not functionality of the resolver.

The only thing that remains is that we still use the `name = <...>`
field in the lockfile for (what is now) `id`. I didn't want to touch
this here because it would be a breaking change for the lockfile. In the
next PR I'll be adding the additional fields to the lockfile that we
discussed and switch this around.

This is part of the work to enable compiling against on-chain
dependencies MystenLabs/sui#14178.

## Test Plan 

Unit tests

---
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
amnn pushed a commit that referenced this pull request Sep 11, 2024
## Description 

This PR fixes multiple issues caused by bytecode dependencies not being
included in `CompiledPackage`:
- multiple functionalities failing due to topo sort in `Modules`
panicking on missing dependencies
- running `move test` on packages with bytecode deps failing due to them
not being included in VM storage
- source verification failing because bytecode deps aren't handled
- commands such as publish and upgrade failing due to bytecode deps not
being referenced in the construction of transaction blocks

Summary of changes:
- removed `move_bytecode_utils::dependency_graph` module and instead
added a `compute_topological_order` method to `Modules`. Replaced all
calls to `compute_dependency_graph` with a direct call to
`compute_topological_order` (2 in total)
- added bytecode deps to VM storage for test runs by loading them from
`ResolvedGraph`
- include bytecode deps in `sui_move_build::CompiledPackage` and fix
various module fetching methods to return modules from bytecode deps
also
- include bytecode deps in `local_modules` function to fix
`LocalDependencyNotFound` errors in source verification

This is part of the work to enable compiling against on-chain
dependencies #14178.

cc @rvantonder @amnn

## Test Plan 

Added unit tests for `move test` and source verification.

---
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
suiwombat pushed a commit that referenced this pull request Sep 16, 2024
## Description 

This PR fixes multiple issues caused by bytecode dependencies not being
included in `CompiledPackage`:
- multiple functionalities failing due to topo sort in `Modules`
panicking on missing dependencies
- running `move test` on packages with bytecode deps failing due to them
not being included in VM storage
- source verification failing because bytecode deps aren't handled
- commands such as publish and upgrade failing due to bytecode deps not
being referenced in the construction of transaction blocks

Summary of changes:
- removed `move_bytecode_utils::dependency_graph` module and instead
added a `compute_topological_order` method to `Modules`. Replaced all
calls to `compute_dependency_graph` with a direct call to
`compute_topological_order` (2 in total)
- added bytecode deps to VM storage for test runs by loading them from
`ResolvedGraph`
- include bytecode deps in `sui_move_build::CompiledPackage` and fix
various module fetching methods to return modules from bytecode deps
also
- include bytecode deps in `local_modules` function to fix
`LocalDependencyNotFound` errors in source verification

This is part of the work to enable compiling against on-chain
dependencies #14178.

cc @rvantonder @amnn

## Test Plan 

Added unit tests for `move test` and source verification.

---
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
amnn pushed a commit that referenced this pull request Sep 23, 2024
…rate `name` field to store manifest name (#19387)

## Description

As discussed in
#14178 (comment)
(second and third point), a few changes to the lockfile:
- the `name` field in `dependencies` is renamed to `id` to better
reflect the meaning in the dependency graph (the packages are
discriminated by their identifier, as resolved by the hook, which is not
necessarily their manifest name)
- added a `name` field which will store the dependency manifest name
(this is needed to show user-friendly error messages using the package
manifest name instead of identifier which may be confusing)
- bumped lockfile version to 3

This is part of the work to enable compiling against on-chain
dependencies #14178.

cc @rvantonder @amnn

## Test plan 

All changes are covered by existing unit 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: 
- [x] CLI: Introduce lock file version 3, which renames a dependency's
`name` field to `id` and introduces a separate `name` field that stores
the package's name from its manifest for improved error reporting. Older
lock files will be ignored when resolving dependencies so that this
information is always available.
- [ ] Rust SDK:
- [ ] REST API:
amnn pushed a commit that referenced this pull request Sep 26, 2024
…9540)

## Description 

Refactor `Custom` dependency to `OnChain` (in the manifest) and
streamline it. It now requires only the `id` field which specifies
dependency's on-chain id (e.g. `Foo = { id = "0x123" }`. `Custom`
dependencies aren't supported on Sui so this should be a fairly safe
change.

This is part of the work to enable compiling against on-chain
dependencies #14178.

cc @rvantonder @amnn

## Test plan 

Updated existing unit 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: 
- [x] CLI: Remove legacy support for custom package hooks, replacing it
with initial logic for on-chain dependencies.
- [ ] Rust SDK:
- [ ] REST API:
amnn pushed a commit that referenced this pull request Sep 27, 2024
… graph (#19595)

## Description 

Small fix to correctly load dependency version when using external
resolver. Changed `echo` in `successful_package_batch_response.sh` to
`printf` for more consistent handling of `\0` across systems (it fails
on my machine).

This is part of the work to enable compiling against on-chain
dependencies #14178.

cc @rvantonder @amnn

## Test plan 

Updated the unit test to have a dependency with `version` field.

---

## 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:
- [ ] REST API:
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.

2 participants