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

Return empty store tree on non-existing version #7415

Merged
merged 27 commits into from
Oct 13, 2020
Merged

Return empty store tree on non-existing version #7415

merged 27 commits into from
Oct 13, 2020

Conversation

RiccardoM
Copy link
Contributor

@RiccardoM RiccardoM commented Sep 30, 2020

Description

This PR tries to fix the different store versions loading problem. It simply returns an empty tree when a store version does not exist. Closes: #7385.

This has been tested using the following procedure:

  1. Start a Desmos chain without the relationships module.
  2. Create an upgrade proposal that switches to a new Desmos version with the new relationships module registered
  3. Vote that upgrade proposal, and let it run.
  4. Try querying the relationships.

Everything seems fine. The new module can be queried without any problem, as well as the old ones.

TODO

If this change is OK, the following things still have to be done:

  • Change the store #GetImmutable documentation accordingly
  • Fix the unit tests properly
  • Add a CHANGELOG entry

Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

@codecov
Copy link

codecov bot commented Sep 30, 2020

Codecov Report

Merging #7415 into master will increase coverage by 0.01%.
The diff coverage is 93.75%.

@@            Coverage Diff             @@
##           master    #7415      +/-   ##
==========================================
+ Coverage   55.96%   55.98%   +0.01%     
==========================================
  Files         594      594              
  Lines       37270    37281      +11     
==========================================
+ Hits        20859    20870      +11     
+ Misses      14300    14294       -6     
- Partials     2111     2117       +6     

@alexanderbez
Copy link
Contributor

Nice! So how does this work under the following scenarios:

  • Querying an existing store at some previous non-pruned height H
  • Querying an existing store at some previous pruned height Hp
  • Querying an existing store at current height Hc
  • Querying a new store at some previous non-pruned height H
  • Querying a new store at some previous pruned height Hp
  • Querying a new store at current height Hc

/cc @erikgrinaker

@erikgrinaker
Copy link
Contributor

erikgrinaker commented Sep 30, 2020

Yeah, I don't really see how this can be right. If the app is at height 900 and the new store is at version 100 (such that version 1-100 in the new store map to heights 800-900 in the app) then surely querying height 850 for the new store will not work since there is no version 850 in the store.

Since you say that this works, then maybe the SDK ends up querying the latest version in this case (I'm not too familiar with the code), but the query requested height 850 not the latest height so it'll still be wrong.

@RiccardoM
Copy link
Contributor Author

RiccardoM commented Sep 30, 2020

Yeah, I don't really see how this can be right. If the app is at height 900 and the new store is at version 100 (such that version 1-100 in the new store map to heights 800-900 in the app) then surely querying height 850 for the new store will not work since there is no version 850 in the store.

Since you say that this works, then maybe the SDK ends up querying the latest version in this case (I'm not too familiar with the code), but the query requested height 850 not the latest height so it'll still be wrong.

I think in this case, since we're returning an empty tree when the version does not exist, then all the queries will just be empty (which is correct since the store didn't exist). Am I missing something?

Anyway I'll try testing all the cases described by @alexanderbez. Do you have any idea how I can get Hp properly to make sure it's pruned?

@erikgrinaker
Copy link
Contributor

I think in this case, since we're returning an empty tree when the version does not exist, then all the queries will just be empty (which is correct since the store didn't exist). Am I missing something?

I think so, because we're returning an empty store for the wrong heights.

In the example above, version 1-100 in the new store was created during heights 800-900. If I write "foo=850" at height 850, this will be stored at version 50 in the new store.

If I query foo as of height 850 it will return nothing, because the store has no version 850 - this is wrong, since the value at height 850 should be foo=850.

If I query foo as of height 50 it will return foo=850. This is wrong, since the store did not exist at all at height 50, and should return empty.

@RiccardoM
Copy link
Contributor Author

In the example above, version 1-100 in the new store was created during heights 800-900. If I write "foo=850" at height 850, this will be stored at version 50 in the new store.

If I query foo as of height 850 it will return nothing, because the store has no version 850 - this is wrong, since the value at height 850 should be foo=850.

If I query foo as of height 50 it will return foo=850. This is wrong, since the store did not exist at all at height 50, and should return empty.

That makes sense. So, is there any way we can get the height at which the store was created? Or, maybe, we can set the new store height with the upgrade height and pad all the previous versions with empty stores? Could this be possible?

@erikgrinaker
Copy link
Contributor

Yeah, so I don't want to prescribe a solution for the SDK here, since I'm not on that team - I'll defer to @alexanderbez. But in IAVL 0.15.0-rc2 we implemented an initial version API which allows setting the initial version for a new IAVL store, via Options.InitialVersion and/or MutableTree.SetInitialVersion(). I have backported this to 0.14 on this branch, but not cut a release yet: https://github.com/cosmos/iavl/tree/0.14.x

It's definitely a viable solution to create a new store with a specific initial version, and then ignore missing version errors when attempting to fetch any previous versions (although this can have the effect of silently ignoring actual bugs that cause versions to go missing). It's also possible to pad out the store with empty versions, corresponding to the versions that exist in the other stores (which will depend on pruning settings).

@alexanderbez
Copy link
Contributor

It's definitely a viable solution to create a new store with a specific initial version, and then ignore missing version errors when attempting to fetch any previous versions (although this can have the effect of silently ignoring actual bugs that cause versions to go missing).

This is the route I'd like to attempt to go with.

  1. Set initial versions for new stores on upgrades. Maybe we can automatically do this in the root multi-store during LoadVersion so app devs don't have to worry about this during app construction. And,
  2. Ignore the store when the version is not available.

@RiccardoM
Copy link
Contributor Author

RiccardoM commented Sep 30, 2020

This is the route I'd like to attempt to go with.

  1. Set initial versions for new stores on upgrades. Maybe we can automatically do this in the root multi-store during LoadVersion so app devs don't have to worry about this during app construction. And,
  2. Ignore the store when the version is not available.

Do you have any hint how this can be achieved? Even high level ones, I'll try to do this tomorrow

@alexanderbez
Copy link
Contributor

Use the SetInitialVersion API. I think when loading stores, we can tell if a store is new (i.e. latest version is zero). If so, we can call SetInitialVersion on it. Would that work @erikgrinaker?

@erikgrinaker
Copy link
Contributor

I think so, yeah.

@RiccardoM
Copy link
Contributor Author

RiccardoM commented Oct 1, 2020

@alexanderbez @erikgrinaker Ok, I've tried implementing it as you said. I had to introduce a little hack to make it work properly: when using tree.LoadVersion, I ignore any error if the store has been added recently. This is to avoid the following error when using tree.SetInitialVersion:

initial version set to 2, but found earlier version 1

Apparently, when loading a specific version of the tree, the IAVL checks to make sure that the initial version of each store is not greater than any other previous versions of any store. If you have any other way of doing this without this magic trick that would be great. I think it might lead to some problems in the future to ignore all the errors.

I've added a test set name TestLoadStore inside store_test.go, but I was not able to find a way to prune a specific height to test such cases.

@erikgrinaker
Copy link
Contributor

initial version set to 2, but found earlier version 1

Doesn't this indicate that the fix doesn't work? It's too late to set the initial version if the tree already has a version in it.

I don't think you can call Version() until the tree has been loaded, it always returns 0 in that case. You may have to call Load() first, which will load the latest available version, but that may not be optimal here since we're given a specific version to load.

@RiccardoM
Copy link
Contributor Author

RiccardoM commented Oct 1, 2020

Doesn't this indicate that the fix doesn't work? It's too late to set the initial version if the tree already has a version in it.

I don't think you can call Version() until the tree has been loaded, it always returns 0 in that case. You may have to call Load() first, which will load the latest available version, but that may not be optimal here since we're given a specific version to load.

Ok, I've tried moving the SetInitialVersion after loading the store. I still have some doubts about the tests. Are they correct? Cause I don't think so to be honest

@alexanderbez
Copy link
Contributor

I believe the version should be set before loading the store. Somewhere in the root multi-store when we load all the versions on bootstrapping, we need to detect that a store is new (i.e. its version is zero) and the last commit id version is higher, so we call SetInitialVersion on that store when creating the IAVL store.

@RiccardoM
Copy link
Contributor Author

I believe the version should be set before loading the store. Somewhere in the root multi-store when we load all the versions on bootstrapping, we need to detect that a store is new (i.e. its version is zero) and the last commit id version is higher, so we call SetInitialVersion on that store when creating the IAVL store.

Can you please point me to where this should happen then? I'm not familiar with the multi store but I get dig into this having a starting place where to look at (method name).

@erikgrinaker
Copy link
Contributor

It occurred to me that another option would be to simply set the initial version to H and then explicitly save an empty version at the upgrade height. It might be more intuitive that the store exists from the upgrade height onwards (inclusive), but don't know if this would complicate the implementation. Don't have any strong opinions on this though, just an idea.

@RiccardoM
Copy link
Contributor Author

It occurred to me that another option would be to simply set the initial version to H and then explicitly save an empty version at the upgrade height. It might be more intuitive that the store exists from the upgrade height onwards (inclusive), but don't know if this would complicate the implementation. Don't have any strong opinions on this though, just an idea.

@alexanderbez Do you have any opinion on this? Should we leave it as it is setting the initial value to H + 1, or should we make it H and save an empty commit?

@alexanderbez
Copy link
Contributor

I don't see any immediate benefit to having an empty commit. I think the H+1 approach should be fine. Glad we figured it out.

@erikgrinaker
Copy link
Contributor

@RiccardoM IAVL 0.14.1 is out: https://github.com/cosmos/iavl/releases/tag/v0.14.1

@RiccardoM
Copy link
Contributor Author

@erikgrinaker @alexanderbez @amaurymartiny I think this is now ready to be merged. I'm also working on another branch to port this to v0.39.1 as well

Copy link
Contributor

@alexanderbez alexanderbez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one minor nit, otherwise LGTM 👍

store/types/store.go Outdated Show resolved Hide resolved
RiccardoM and others added 3 commits October 12, 2020 15:47
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
# Conflicts:
#	store/iavl/store.go
#	store/types/store.go
@erikgrinaker
Copy link
Contributor

I've released IAVL 0.15.0-rc4, which now errors when attempting to load a non-existing version from an empty tree. This change may affect this PR. See: cosmos/iavl#317

@erikgrinaker erikgrinaker mentioned this pull request Oct 14, 2020
9 tasks
alessio pushed a commit that referenced this pull request Oct 16, 2020
@clevinson clevinson mentioned this pull request Oct 19, 2020
31 tasks
clevinson added a commit that referenced this pull request Oct 19, 2020
* Update Encoding Doc for 0.40 (#7430)

* Remove deprecated docs and add first guidelines to protobuf migration

* Add conventions

* Reorder and add more FAQ doc

* Update guidelines for pb msg definitions

* Use commit hash in github links

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* docs: Update "Basics" section (#7416)

* Prettier

* docs: Update "Basics" section

* appcli -> appd

* Better wording

* Fix to appCodec

* Add gRPC mention

* Add grpc

* Reference simapp code

* Update docs/basics/accounts.md

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>

* Add section about gRPC query services

* Optional LegacyQuerierHandler

* Clearer docs

* Update docs/basics/app-anatomy.md

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>

* Update docs/basics/app-anatomy.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Address comments

* Address comments

* Update docs/basics/accounts.md

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Fix misbehaviour handling for solo machine (#7515)

* add timestamp to SignatureAndData

Add timestamp field to signature and data. Add ValidateBasic check for timestamp. Add ValidateBasic test. Update misbehaviour handler to use supplied timestamp.

* fix typo

* add timestamp check

* fix lint

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* update solo machine specs (#7512)

* update solo machine specs

* update concepts

* self review fixes

* Apply suggestions from code review

* add note on upgarding solo machines

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Corrected 'unsafe-reset-all' help text (#7504)

* Merge PR #7415: Return empty store tree on non-existing version

* tendermint: update sdk to rc5 (#7527)

* update sdk to rc5

* Update baseapp/params.go

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Bump github.com/spf13/cobra from 1.0.0 to 1.1.0 (#7553)

Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](spf13/cobra@v1.0.0...v1.1.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* remove test_utils.go in tm client (#7522)

* remove test_utils from tm client

* fix build

* fix lint?

* fix lint?

* apply @fedekunze review suggestion

* add tests as per @alessio suggestion

* fix typo

* ibc: cleanup channel types test (#7521)

* Update Building Modules documentation (#7473)

* Update module-manager.md

* Update modules #messages doc

* Fix typo

* Update message implementation example link

* Update messages-and-queries.md#queries doc

* Update querier.md

* Update handler.md

* Update links in beginblock-endblock.md

* Update keeper.md

* Update invariants.md

* Update genesis.md

* Update module-interfaces.md#transaction-commands

* Update module-interfaces.md#query-commands

* Update module-interfaces.md#flags

* Update module-interfaces.md#rest

* Update structure.md

* Update module-interfaces.md#grpc

* Update errors.md

* Update module-interfaces.md#grpc-gateway-rest

* Add more info on swagger

* Address comments

* Fix go.sum

* Fix app-anatomy.md

* Update docs/building-modules/module-interfaces.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/querier.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/querier.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/module-interfaces.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/module-interfaces.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Address part of review comments

* Update old ref of RegisterQueryService

* Add example code for Manager

* Update queriers.md to query-services.md and refs

* Add new query-services.md

* Revert "Update old ref of RegisterQueryService"

This reverts commit 1ea1ea8.

* Update keeper.md

* Update handler.md

* Update handler.md

* Update messages-and-queries.md

* Update docs/basics/app-anatomy.md

Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>

* Update docs/building-modules/intro.md

Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>

* Fix typo

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>

* client: add GetAccount and GetAccountWithHeight to AccountRetriever (#7558)

* client: add GetAccount and GetAccountWithHeight to AccountRetriever

* update ADR

* address comments from review

* Add the option of emitting amino encoded json from the CLI (#7221)

* Add the option of emitting amino encoded json

* Update AMINO JSON serialization with ConvertTxToStdTx

* Make the Amino flag more self documenting by serializing the BroadcastRequest type instead of StdTx

* Handle amino encoding error

* Update x/auth/client/cli/tx_multisign.go

Co-authored-by: Alessio Treglia <alessio@tendermint.com>

* Update x/auth/client/cli/tx_sign.go

Co-authored-by: Alessio Treglia <alessio@tendermint.com>

* Apply suggestions from code review

Co-authored-by: Alessio Treglia <alessio@tendermint.com>

* Fix go format

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* ibc: update solo machine client command (#7579)

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* docs: Revert SPEC-SPEC and update x/{auth,bank,evidence,slashing} (#7407)

* Revert some changes from #7404

* Update x/slashing

* Address review comments

* Small tweak

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* remove id in localhost (#7577)

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Christopher Goes <cwgoes@pluranimity.org>

* update changelog

* Update CHANGELOG.md

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>

* Fix solomachine cmds (#7581)

* fix solo machine cli cmds

* polish

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* simapp: use tmjson on InitChainer (#7514)

Co-authored-by: Alessio Treglia <alessio@tendermint.com>

* [IAVL]: Bump to v0.15.0-rc4 (#7549)

* iavl 0.15.0-rc4 version bump

* update comments on error modes for store.LoadStore

* update CONFIO_URL in makefile

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* Handle nil *Any in UnpackAny and add panic handler for tx decoding (#7594)

* Handle nil any in UnpackAny

* Add test

* Add flag back

* Update runTx signature

* Update Simulate signature

* Update calls to Simulate

* Add txEncoder in baseapp

* Fix TestTxWithoutPublicKey

* Wrap errors

* Use amino in baseapp tests

* Add txEncoder arg to Check & Deliver

* Fix gas in test

* Fix remaining base app tests

* Rename to amionTxEncoder

* Update codec/types/interface_registry.go

Co-authored-by: Aaron Craelius <aaron@regen.network>

* golangci-lint fix

Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
Co-authored-by: Aaron Craelius <aaron@regen.network>
Co-authored-by: Cory Levinson <cjlevinson@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com>
Co-authored-by: Neeraj Murarka <njmurarka@users.noreply.github.com>
Co-authored-by: Riccardo Montagnin <riccardo.montagnin@gmail.com>
Co-authored-by: Marko <marbar3778@yahoo.com>
Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zaki Manian <zaki@manian.org>
Co-authored-by: Alessio Treglia <alessio@tendermint.com>
Co-authored-by: Christopher Goes <cwgoes@pluranimity.org>
Co-authored-by: Aaron Craelius <aaron@regen.network>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Post upgrade with x/upgrade queries not working
4 participants