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

During migration from legacy 20 byte address a 'no history for address' error occurs #758

Closed
iramiller opened this issue Feb 15, 2022 · 19 comments
Milestone

Comments

@iramiller
Copy link
Contributor

In testing 0.23 on a testnet with existing contract instance an error is thrown due to the way kvstore addresses are generated. Addresses are based on the current 32 byte length form, unfortunately some contracts were established with the prior 20 byte address form which is incompatible with this approach.

r := make([]byte, prefixLen+ContractAddrLen)

The above line always presumes the length will be 32 and it fails because it can't delete the history here:

prefixStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.GetContractCodeHistoryElementPrefix(contractAddr))

This occurred during testing on Provenance (using wasmd 0.23) with the following:

provenanced tx wasm migrate \
    tp15qkf84uddc0zjpkjrn64rln75w40plrtcq4kp3 \
    111 \
    '{}' \
    --chain-id pio-testnet-1 \
    --node tcp://rpc-0.test.provenance.io:26657 \
    [ ... ]

Error: rpc error: code = InvalidArgument desc = recovered: no history for tp15qkf84uddc0zjpkjrn64rln75w40plrtcq4kp3
stack:
goroutine 764913 [running]:
runtime/debug.Stack()
    runtime/debug/stack.go:24 +0x65
@iramiller
Copy link
Contributor Author

iramiller commented Feb 15, 2022

One potential solution here is to use:

	addrLen := len(contractAddr)
	r := make([]byte, prefixLen+addrLen)

Length assertions could be inserted to require 20 or 32 byte address forms (which are the only two allowed) however if this is done additional refactoring will be required as the methods do not currently return errors and a panic isn't really desirable.

As the purpose of this key is to lookup existing cached data ... if the address were invalid here then there would be no data matched so additional validity checks are likely not needed.

@alpe
Copy link
Contributor

alpe commented Feb 16, 2022

Can you give more context why you need 20 byte contract addresses in your scenario?
A mix of both address sizes adds some complexity that I would avoid. You can either migrate the 20 byte addresses to 32 bytes or set the ContractAddrLen to 20 bytes.
The later one is not possible currently without changing code as it is a constant. Just open an issue/ PR for this.

The contract address is deterministic and based on codeID and contractID. Unfortunately the contractID is not persisted but can be found with some smarter than brute force algorithm for a migration.

@the-frey
Copy link
Contributor

the-frey commented Feb 16, 2022

By migration you mean at the contract level right? We will run into this issue on Juno. as well (as I think we have 3-4 length 20 contracts instantiated when the chain first launched.

My concern is that if migrations to contracts are required, possibly either the original instantiators won't be contactable, or they won't have set an admin, so the contracts won't be migrate-able.

If it's at binary level then that's less of a concern.

@alpe
Copy link
Contributor

alpe commented Feb 16, 2022

Sorry, migration was ambiguous. I was referring to sdk upgrade . Contracts don't have access to the store outside their namespace.
This address "update" would also affect balances and others places where the contract address is used.

@the-frey
Copy link
Contributor

Right, I did wonder. So in summary if we have 20 byte contract addresses then before moving to mainline wasmd or wasmd 0.23 we would need a migration that ensures every existing contract with a 20 byte address is changed to 32?

@alpe
Copy link
Contributor

alpe commented Feb 16, 2022

To summarize, I can see these 3 options:

A) "upgrade" all contracts to 32 byte addresses and go with vanilla wasmd
B) we make ContractAddrLen a var so that every team can decide and set their contract address length (32byte would be default)
C) have a mixed setup with 20 and 32 byte addresses as @iramiller has in their testnet currently which require changes to vanilla wasmd

As mentioned before, C) is not my preferred option as it adds complexity.

@alpe
Copy link
Contributor

alpe commented Feb 16, 2022

btw @iramiller thanks for bringing this topic up. Happy to see this discussion.

@iramiller
Copy link
Contributor Author

The contract address is well known and used in several frontend applications... so while we could programmatically shift the state to a new 32 byte address that would break the application dependencies above the blockchain if we modify it. In this case there is a consortium of banks that all agreed on it. Certainly do able but the ask is to avoid that because these kinds of changes take more time than they should.

My fears about not supporting the 32 byte form are not well defined but are based on suspicions that future applications over IBC/interchain may see difficulties. By removing the constraint that the address will be 32 in length then existing ones continue to work and all future ones can be the proper 32 byte form.

@ethanfrey
Copy link
Member

To summarize, I can see these 3 options:

A) "upgrade" all contracts to 32 byte addresses and go with vanilla wasmd

Addresses are stored in many places and we cannot change them. Wasmd upgrades must work with immutable contracts.

B) we make ContractAddrLen a var so that every team can decide and set their contract address length (32byte would be default)

They don't want 20 bytes. They want 32, but want backwards support for 20 bytes. Note that various components in the sdk (notably ibc) choked on 32 bytes addresses when Provenance and Juno made these choices.

C) have a mixed setup with 20 and 32 byte addresses as @iramiller has in their testnet currently which require changes to vanilla wasmd

As mentioned before, C) is not my preferred option as it adds complexity.

It is more complex for wasmd, but it is needed complexity and part of the follow up from our decision to move to 32 byte contract addresses (which I think everyone on this thread commented on and supported). I agree with @iramiller that we need to support this on the sdk side.

I also know that Alex is very busy with Tgrade work right now, but I would ask if there is interest in an external PR to add this as this is a critical fix needed for both your chains.

@the-frey
Copy link
Contributor

👍 to everything in that summary.

I'd love to pitch in, but I think my knowledge of the wasmd/SDK internals is likely not up to the task 😞

@iramiller
Copy link
Contributor Author

We have a fork with this change which we are running now on our testnet for evaluation... it would be straight forward to contribute this solution... in addition if this solution needs to develop further we are interested in helping out cosmwasm with testing these changes and we would want to see those included in our network before we cut our next release.

@channa-figure
Copy link
Contributor

Here is a compare link for what we did to solve this issue. This is the change @iramiller was referring to.

v0.22.0...provenance-io:migration-address-length

@albertchon
Copy link
Contributor

albertchon commented Feb 17, 2022

What is the downside for a fork to just change the ContractAddrLen to 20 bytes?

Why was this change made to begin with? Can't seem to find an explanation for this

@iramiller
Copy link
Contributor Author

Originally the sdk assigned 20 byte addresses but a switch to 32 was made for new addresses based on new key types. Existing addresses were maintained.

The cosmwasm system is taking this differently with the current implementation breaking all existing contracts when it blocks support for existing addresses.

More details here: https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md

@ethanfrey
Copy link
Member

@albertchon when preparing the PR to update to 0.45 we had number of discussions of the two teams we knew using forks with 0.45 - Juno and Provenance.

You can see the discussion here on a PR proposal from the Juno team.

This was also heavily promoted by the Cosmos SDK team. Well before 0.43 came out, Robert was asking me to migrate to the new module account hash algorithm.

@ethanfrey
Copy link
Member

I agree with @iramiller that we should support both and new addresses are 32 bytes

@ethanfrey ethanfrey added this to the v0.24.0 milestone Feb 22, 2022
@ethanfrey
Copy link
Member

Note: the first 2 commits of this PR #763 seem to address a few items required for this issue

@the-frey
Copy link
Contributor

the-frey commented Mar 2, 2022

@channa-figure / @iramiller would you put in a PR to wasmd with your solution? On the current Juno testnet we've moved off our fork and onto mainline wasmd, so we can test a point release/pre-release as well if it's in this repo. Otherwise a bit of faff to change to your fork, test, then change back to mainline 🙂

@ethanfrey
Copy link
Member

Closed by #772

daeMOn63 added a commit to fetchai/fetchd that referenced this issue Mar 16, 2022
bring back support to 20bytes long contract address (see: CosmWasm/wasmd#758)
daeMOn63 added a commit to fetchai/fetchd that referenced this issue Mar 23, 2022
* feat: upgrade fetchd to dorado version

Dependencies:

- bump cosmos-sdk to v0.45.1
- bump tendermint to v0.34.16
- bump wasmd to v0.23.0
- integrate ibc-go v2.0.3

Modules:

- update app and commands to integrate new feegrant and authz modules
- remove airdrop module

Commands:

- removed capricorn migration commands (stake-reconciliation-migrate and
  capricorn-migrate)

Remaining changes are only compatibility fixes with the new cosmos-sdk
version

* fix: missing ptr dereference in initAppConfig

* Update networks.md with dorado -rc1

* docs: add gas prices for testnet networks

* chores: bump ibc-go version (#205)

* fix: add back reconciliation command

* fix: bump wasmd to v0.24

bring back support to 20bytes long contract address (see: CosmWasm/wasmd#758)

* chores: wakeup CI

* fix: bump go requirements to 1.17 to allow wasmvm to build (#208)

* Dorado migration (#204)

* fix: bump go requirements to 1.17 to allow wasmvm to build

* feat: add dorado-migrate command

* chores: fmt

* feat: add initial nanonomx supply to dorado-migrate command

* docs: remove redundant info

* chores: switch cosmos-sdk to proper tagged version

* docs: update software versions

Co-authored-by: Ian Harris <[email protected]>
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

No branches or pull requests

6 participants