-
Notifications
You must be signed in to change notification settings - Fork 431
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
Add integration-test
for possible migration pattern
#1909
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1909 +/- ##
==========================================
+ Coverage 53.69% 53.71% +0.01%
==========================================
Files 223 223
Lines 7043 7043
Branches 3121 3121
==========================================
+ Hits 3782 3783 +1
+ Misses 3261 3260 -1 ☔ View full report in Codecov by Sentry. |
My personal take on the migration pattern: While this approach works, it is only feasible for trivial storage migrations. As shown in the example, we are migrating a simple, Packed, layoutful storage with 1-2 primitive fields. In production contracts, storage is much more complex, it can have multiple custom data types, Mappings, Lazy fields. Migrating this type of storage using raw operations on the storage cells is tedious and error-prone. While storage migration is an "advanced" concept, we should still discourage developers from raw storage operations, and leave it for use only for some niche use cases, similar to how solidity devs are not advised to use EVM opcodes on a regular basis. What I am proposing instead is to look into #1388 and define a migration API for the developers to work with the concrete storage layouts instead. The concept is very similar to the database migration in ORM libraries like this: https://www.sea-ql.org/SeaORM/docs/next/migration/writing-migration/ While this is obviously more work, I strongly believe, that if we "market" the "native" contract's upgradeability, we should also provide a safe workflow with it to lower the entry point of using the feature. |
🦑 📈 ink! Example Contracts ‒ Changes Report 📉 🦑These are the results when building the
Link to the run | Last update: Thu Oct 26 11:34:47 CEST 2023 |
See IIP-3 #1981 for a suggestion to make this better, specifically to allow multi-step data migration and contract upgrades, without the risk of bricking the contract. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great example!
integration-tests/upgradeable-contracts/set-code-hash-migration/lib.rs
Outdated
Show resolved
Hide resolved
Please add an entry here: https://github.com/paritytech/ink/tree/master/integration-tests/upgradeable-contracts. |
…n/lib.rs Co-authored-by: Michael Müller <michi@parity.io>
🦑 📈 ink! Example Contracts ‒ Changes Report 📉 🦑These are the results when building the
Link to the run | Last update: Wed Jan 31 13:34:18 CET 2024 |
* WIP * Update versions * WIP * WIP migration * WIP * Make test pass * Move e2e tests mod to own file * Update comment * Update example for new e2e API * Update integration-tests/upgradeable-contracts/set-code-hash-migration/lib.rs Co-authored-by: Michael Müller <michi@parity.io> * Top level gitignore * Fix tests update comments * Update upgradeable contracts README.md * spelling --------- Co-authored-by: Michael Müller <michi@parity.io>
* init call_v2 methods and types * add e2e tests to basic-contract-caller example * Add storage_deposit * Fix basic-contract-caller e2e tests * Remove `basic_contract_caller` integration test, moved to #1909 * WIP adding cross_contract_calls test * Add `integration-test` for possible migration pattern (#1909) * WIP * Update versions * WIP * WIP migration * WIP * Make test pass * Move e2e tests mod to own file * Update comment * Update example for new e2e API * Update integration-tests/upgradeable-contracts/set-code-hash-migration/lib.rs Co-authored-by: Michael Müller <michi@parity.io> * Top level gitignore * Fix tests update comments * Update upgradeable contracts README.md * spelling --------- Co-authored-by: Michael Müller <michi@parity.io> * Add `basic-contract-caller` E2E test (#2085) * add e2e tests to basic-contract-caller example * Fix basic-contract-caller e2e tests * Remove `call_builder` change * Remove `basic_contract_caller` integration test, moved to #1909 * Revert "Remove `basic_contract_caller` integration test, moved to #1909" This reverts commit 8f3ab31. * fmt * Only need one .gitignore * WIP adding create v2 API * Revert "WIP adding create v2 API" This reverts commit bd83e18. * WIP e2e tests * Add CallV2 builder methods * Pass weight limit as params * Allow deprecated * Add storage_deposit_limit * Clippy * Use struct update syntax * Remove space * CHANGELOG * fmt * Import OtherContract directly instead of reexporting * Make other_contract pub * Revert prev * docs * top level gitignore for integration-tests * Remove unused setters * Use ContractRef * integration-test comments * Rename to `call_v2` * Comments and builder method * SP * comments * fix doc test --------- Co-authored-by: Michael Müller <michi@parity.io>
Here I add an example that performs a storage migration with the following flow:
migration
contract with a messagemigrate
which performs the storage migration.migration
contract.incrementer
contract.migrate
on themigration
contract, passing the code hash of the new updated incrementer contract from3.
This must happen as a single message, because following the storage migration, the contract would not be able to be called again, since it will fail to load the migrated storage.I imagine that a similar pattern could be applied using
delegate_call
instead ofset_code_hash
?The
migrate
message looks like:Note the use of
&self
instead than&mut self
, ensuring that the storage will not be written to automatically following the invocation.I have added this to demonstrate how we might perform a migration as it stands, without having to add any extra hooks in the language, as mentioned here #1388 (comment).
Also to demonstrate that it would still be possible to do a migration without using
_reserved: Option<()>
trick for schema evolution as suggested by @athei in relation to #1897