feat: migrate tainted wasmd#641
Conversation
- Added v15 upgrade handler and constants for wasm migration. - Implemented Migrator for handling field order changes in ContractInfo. - Updated run-node.sh and upgrade-test.sh scripts for enhanced functionality. - Improved wasm deployment and state querying scripts for better error handling.
There was a problem hiding this comment.
Pull request overview
This PR adds a v15 upgrade path to migrate “tainted” CosmWasm ContractInfo state caused by a protobuf field-order mismatch (wasmd v0.61.4 → v0.61.5), and updates the upgrade testing / wasm helper scripts to better exercise and validate the migration during local upgrade runs.
Changes:
- Add v15 upgrade wiring and bump wasm module consensus version to run a new v4→v5
ContractInfofield-order migration. - Introduce a wasm store migrator that rewrites legacy-encoded
ContractInfoentries into the corrected schema. - Improve upgrade/wasm scripts (deploy, post-upgrade queries, proposal submission flow), and add example upgrade-test invocations.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/wasm_command.txt | Adds an example command sequence for running the upgrade test with wasm deploy + post checks. |
| scripts/wasm/wasm-write-state.sh | Adds structured post-upgrade queries (all/raw/smart) with summarized pass/fail reporting. |
| scripts/wasm/wasm-deploy.sh | Improves tx inclusion waiting + more robust extraction of code_id / contract address. |
| scripts/wasm/stargate-after-upgrade.sh | Improves extraction of code_id / contract address and makes --label conditional. |
| scripts/upgrade-test.sh | Makes old/new binary install more flexible and improves fork/upgrade orchestration. |
| scripts/run-node.sh | Adjusts genesis setup + supports halt-height and configurable self-delegation. |
| custom/wasm/module.go | Bumps wasm consensus version and registers the new v4→v5 migration. |
| custom/wasm/migrations/v4/types.go | Adds legacy protobuf types to decode v0.61.4 ContractInfo layout. |
| custom/wasm/migrations/v4/store.go | Implements the v4→v5 in-place KV migration for ContractInfo. |
| app/upgrades/v15/upgrades.go | Adds the v15 upgrade handler (runs module migrations). |
| app/upgrades/v15/constants.go | Registers the v15 upgrade metadata in the upgrades registry. |
| app/app.go | Adds v15 to the app’s upgrade list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Unmarshal using LEGACY schema (field 7 = ibc2_port_id, field 8 = extension) | ||
| var legacyInfo LegacyContractInfo | ||
| if err := cdc.Unmarshal(iter.Value(), &legacyInfo); err != nil { | ||
| // Skip if unmarshal fails (shouldn't happen in normal operation) | ||
| continue | ||
| } |
There was a problem hiding this comment.
This migration silently continues on unmarshal errors. If any ContractInfo entry is malformed, it will be left unmigrated (potentially preserving the exact failure this migration is meant to fix) with no visibility. Consider returning an error (fail the upgrade) or at least logging and counting failures so operators know the state is inconsistent.
| func (m Migrator) Migrate4to5(ctx sdk.Context, storeService corestoretypes.KVStoreService, cdc codec.BinaryCodec) error { | ||
| store := storeService.OpenKVStore(ctx) | ||
| prefixStore := prefix.NewStore(runtime.KVStoreAdapter(store), types.ContractKeyPrefix) | ||
|
|
||
| iter := prefixStore.Iterator(nil, nil) | ||
| defer iter.Close() | ||
|
|
||
| for ; iter.Valid(); iter.Next() { | ||
| // Unmarshal using LEGACY schema (field 7 = ibc2_port_id, field 8 = extension) | ||
| var legacyInfo LegacyContractInfo | ||
| if err := cdc.Unmarshal(iter.Value(), &legacyInfo); err != nil { | ||
| // Skip if unmarshal fails (shouldn't happen in normal operation) | ||
| continue | ||
| } | ||
|
|
||
| // Convert to NEW schema (field 7 = extension, field 8 = ibc2_port_id) | ||
| newInfo := types.ContractInfo{ | ||
| CodeID: legacyInfo.CodeID, | ||
| Creator: legacyInfo.Creator, | ||
| Admin: legacyInfo.Admin, | ||
| Label: legacyInfo.Label, | ||
| IBCPortID: legacyInfo.IBCPortID, | ||
| IBC2PortID: legacyInfo.IBC2PortID, // Moved from field 7 to field 8 | ||
| } | ||
|
|
There was a problem hiding this comment.
The new ContractInfo field-order migration is consensus-critical, but there are no unit tests covering the marshal/unmarshal swap logic. Adding a focused test that round-trips a LegacyContractInfo-encoded value through Migrate4to5 and asserts the resulting types.ContractInfo has the correct Extension/IBC2PortID values would help prevent regressions.
|
Looks good. I see no weaknesses implementation wise. However, can we rename the upgrade to Also I don't think we should merge this test yet fixing upgrade handler into main. I would rather fork the development branch at HEAD~1 and tag HEAD with v4.0.0-rc.4 - then merge HEAD~1 instead |
already change to v14rc4 and point the pr to the testnet branch |
Summary of changes
Before migration - query smart failed
After migration - query smart passed
Report of required housekeeping
(FOR ADMIN) Before merging