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

Macro for setting the contract's state version in the compiled binary #2116

Closed
Tracked by #2087
kulikthebird opened this issue Apr 17, 2024 · 10 comments · Fixed by #2124
Closed
Tracked by #2087

Macro for setting the contract's state version in the compiled binary #2116

kulikthebird opened this issue Apr 17, 2024 · 10 comments · Fixed by #2124
Assignees

Comments

@kulikthebird
Copy link

kulikthebird commented Apr 17, 2024

The purpose of the new macro is to provide the contract's state version directly in the contract's binary. Once provided, the VM could implement the conditional migrate call procedure to reduce redundant migrate entry point calling.

Procedural attribute-like macro

A proc-macro that can be called on the migrate entry point only.

#[entry_point]
#[set_contract_state_version(3)]
pub fn migrate(deps: DepsMut, env: Env, info: MigrateInfo, _msg: MigrateContract) -> StdResult<Response> {
    // [...]
}
@aumetra
Copy link
Member

aumetra commented Apr 22, 2024

I personally think a good solution would be something like cw_contract_state_version as the name of a custom section, and the value is just the value of the version

(maybe as an integer, maybe we could also make the affordance and enforce it to be UTF-8 bytes, therefore allowing for more complex versions, such as SemVer-encoded versions)

@aumetra
Copy link
Member

aumetra commented Apr 22, 2024

Another thing to keep in mind: If we want to have tests for this (and we most definitely do), creating a WASM binary from WAT with a custom section requires the payload to be a string, simply because of how the WAT is defined.
The binary format has no such limitations.

For example, this works, but this does not, so if we want to write tests in WAT, then we pretty much have to choose strings.

Otherwise we can try to assemble these things ourselves by using wasm-encoder

@webmaster128
Copy link
Member

I would like the value to be readable using wasm-objdump (see notes here for the working title cw2++). This would then also require the value to be a string and not some big endian number.

@aumetra
Copy link
Member

aumetra commented Apr 23, 2024

Okay, now that we pretty much settled on using strings, should we enforce the usage of something like SemVer? Because that way it's nicely structured from a user point of view, and we can do easy comparisons whether the contract is newer, older, or the same version.

@webmaster128
Copy link
Member

In the context of state versioning, I don't see a value in using anything non-integer. It just adds complexity but what you need is incremental steps for migrations.

@aumetra
Copy link
Member

aumetra commented Apr 23, 2024

Fair, fair. So stringify integer inside the macro -> upon loading, check if the versioning from the last revision is old+1 (if it isn't, error out, I guess?) -> run migrations?

@webmaster128
Copy link
Member

Almost:

  1. If state_version_new_code != state_version_old_code, wasmd calls the migrate entry point of the contract. Otherwise the code is swapped but the migrate implementation is bypassed
  2. In fn migrate( the contract developer gets the old version and can do anything smart with that information. You can imagine an implementation in version 5 that is able to migrate from 2, 3 and 4 but not 1.

@aumetra
Copy link
Member

aumetra commented Apr 23, 2024

the contract developer gets the old version and can do anything smart with that information

Fair, I was thinking in terms of lock-step migration, but that makes sense.

@webmaster128
Copy link
Member

After #2124 what we also need is a function in the VM that can read the version from a contract by checksum. Wasmd could do that directly but then we'd have to copy the whole Wasm blob around. The VM can implement that more efficiently and in Rust.

@aumetra
Copy link
Member

aumetra commented Apr 25, 2024

The VM can implement that more efficiently and in Rust.

Yeah, it's actually also not that hard to implement. wasmparser and then just step through the components.

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

Successfully merging a pull request may close this issue.

5 participants
@webmaster128 @chipshort @kulikthebird @aumetra and others