move
move copied to clipboard
Collision if your module has multiple dependencies with the same named address but different values
Say you have two packages:
[package]
name = 'DepA'
version = '1.0.0'
[dependencies.AptosFramework]
git = 'https://github.com/aptos-labs/aptos-core.git'
rev = 'main'
subdir = 'aptos-move/framework/aptos-framework'
[addresses]
admin = "0xaaaaaaaa"
[package]
name = 'DepB'
version = '1.0.0'
[dependencies.AptosFramework]
git = 'https://github.com/aptos-labs/aptos-core.git'
rev = 'main'
subdir = 'aptos-move/framework/aptos-framework'
[addresses]
admin = "0xbbbbbbb"
Now let's say you have a parent package that depends on both of them:
[package]
name = "MyProject"
version = "0.0.0"
[dependencies]
DepA = { git = "https://github.com/banool/testing.git", subdir = "dep_a", rev = "main" }
DepB = { git = "https://github.com/banool/testing.git", subdir = "dep_b", rev = "main" }
If you try to compile this, you will get an error that looks like this:
Move compilation failed: Unable to resolve packages for package 'MyProject': Unable to resolve named address 'admin' in package 'MyProject' when resolving dependencies: Attempted to assign a different value '0xbbbbbbb' to an a already-assigned named address '0xaaaaaaaa'
In other words, if you depend on two packages that use the same named address with different values, they will collide and compilation will fail.
This seems like a package ecosystem problem waiting to happen. Essentially in this setup, all named addresses exist within a global namespace. The two packages I depend on might be written by totally separate entities and they just independently chose to use the same name, e.g. admin
(which is quite common). If that's the case, I have to ask one of them to go use a different named address, like admin1 and admin2. Or I just don't use one of the packages.
I feel the solution would be to "scope down" named addresses, so that a named address exists only within a single package, so when you compile two dependent modules, their names won't collide, since as siblings, those named address should have no meaning to each other.
Alternatively, there could be some scheme where you namespace the named addresses, so you could do package::named_address
or something. But I don't know if this is actually necessary.
cc @SangyunOck
Hey @banool good question!
Agreed that it would be a package ecosystem problem if there was no way to extricate yourself from the situation that you describe.
The good news is that this problem can be resolved in packages today with address renaming (see: https://diem.github.io/move/packages.html#scoping-and-renaming-of-named-addresses for more details on how this all works). TL;DR: in your example for MyProject
I could rename the admin
named addresses coming from one of the packages to resolve that conflict, i.e.,
[package]
name = "MyProject"
version = "0.0.0"
[dependencies]
DepA = { git = "https://github.com/banool/testing.git", subdir = "dep_a", rev = "main", addr_subst = {"other_admin" = "admin" } }
DepB = { git = "https://github.com/banool/testing.git", subdir = "dep_b", rev = "main" }
You should then be able to compile MyProject
and it should work. You'll need to use the other_admin
named address to refer to the named address coming from DepA
in your Move code.
Hey, great to hear that there is a workaround!
Saying that, I don't quite understand why this is a problem in the first place. I would expect that named addresses are scoped to each package and resolved within each package independently.
cc @wrwg, we spoke offline about this.
The issue with scoping named addresses to the package only is that this greatly limits the power of them. In particular, two of the main reasons why we want named addresses to be exported are:
- I may have a package that defines a specific address that other packages should use and know about, e.g., the location of a specific resource (or module) that I have published. Exporting the named address allows other packages to use it without needing to know the exact value of the address.
- In the case of more generic libraries, I may want to allow packages that import me to specify the value for my named addresses -- and I as the package don't care what address value is used. In this case exporting the named addresses is also quite useful. This is, e.g., what is done in the Move standard library; the
Std
named address is defined but not assigned a value so that the users of the package can define that address later on.
Tim, I'm wondering whether this also works for the Move Model, or was that exactly the part were it didn't?
Also, we are currently looking at reactivating already existing code in the compiler to compile agains binary-only dependencies. This feature is more frequently requested since originally anticipated, and even if it makes not that much sense for protecting IP (Move can be easily decompiled), our users start to insist. In that context, we would probably want to deactivate for our usage of the package system the option to relocate packages. In that case, can't we just evaluate all those address aliases once and for all locally? Would this be a heavy rewrite of the package system?
[BTW welcome back to Move!]
Tim, I'm wondering whether this also works for the Move Model, or was that exactly the part were it didn't?
Absolutely correct. Anything that goes through the Move Model doesn't support address renaming since it needs to take all of the modules at the same time, and we cannot pull the trick we do with separate compilation to perform the address renaming.
To your second question, I don't fully understand so I might need an example or a bit more clarification, and in particular I'm not sure what is meant here:
In that context, we would probably want to deactivate for our usage of the package system the option to relocate packages.
If I had to hazard a guess, do you mean that you wouldn't permit unassigned named addresses in packages that can be assigned in a different package (the Move Stdlib case/case 2 above)? If so I don't think adding this restriction in would be too hard in the existing package system. Let me know if this isn't what you meant -- happy to dig in a bit more on this.
Thanks for the welcome back! Excited to be back working on Move :)
In that context, we would probably want to deactivate for our usage of the package system the option to relocate packages.
Adding to @tzakian's question on this -- note that addr_subst
does not let you relocate an address in a dependent package. It provides two features:
- Allows you to call an address by a different name in the dependee, so whether the dependent package is built from source, or exists as a binary should not come into play.
- Allows you to supply a numerical address for an unassigned address, but a prebuilt dependent package cannot have any unassigned addresses, so this case is unreachable.