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

Implement decoupled state commitments and storage #11

Merged
merged 16 commits into from
Jun 11, 2021
Merged

Implement decoupled state commitments and storage #11

merged 16 commits into from
Jun 11, 2021

Conversation

roysc
Copy link
Collaborator

@roysc roysc commented May 4, 2021

Introduces a new CommitKVStore to implement ADR-040 proposal of decoupled commitment/data concerns.

Adapted from store/ll-smt branch (see cosmos#8507).

Description

Introduces the decoupled.Store type composed of:

  • A tm-db interface for mapping state storage (SS) (as key → value)
  • A "state commitment" (SC) store for computing Merkle root hashes (storing hash(key) → hash(key, value))
    • This is an iavl.Store held as a CommitKVStore reference, which will later be refactored to use an SMT store
  • A tm-db interface for an inverted index, mapping SC values back to SS keys (hash(key, value) → key)

closes: #1


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. N/A, no modules
  • 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

Copy link
Collaborator

@i-norden i-norden left a comment

Choose a reason for hiding this comment

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

Looking good. In addition to the comments, as you know we need to replace tm-db with tm-dbv2 and remove IAVL usage. In addition to that the next step is to flesh out how the decoupling will be handled at the multistore level. I think what we want to do is have the multistore map StoreKeys to a Store tuple (SCKVStore, SSKVStore).

if err != nil {
panic(err.Error())
}
s.sc.Set(key, kvHash[:]) // TODO: key or hash(key)?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Need an err := here. But actually I don't think we need this Set, the key, value and hash(key, value), key will be sufficient

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is where the state commitment mapping is set; Set() has no return value

Copy link
Collaborator

Choose a reason for hiding this comment

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

Got it, we don't need the err check below then.

// Direct KV mapping (SS)
data dbm.DB
// Inverted index of SC values to SS keys
inv dbm.DB
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does the second bucket need to move through a separate tm-db interface?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm using PrefixDBs to separate the two into different namespaces. Collisions are unlikely since the inverted index uses a hash as key, but I think it's still desired.

@roysc roysc requested a review from ashwinphatak May 6, 2021 13:30
@roysc roysc changed the title [WIP] skeleton of decoupled.Store [WIP] Implement decoupled state commitments and storage May 6, 2021
if err != nil {
panic(err.Error())
}
s.sc.Set(key, kvHash[:]) // TODO: key or hash(key)?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Got it, we don't need the err check below then.

if err != nil {
panic(err.Error())
}
err = s.inv.Set(kvHash[:], key)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We're deviating pretty hard from the simple behavior expected from a KVStore. A KVStore Set is expected to Set that key-value, it isn't expected to generate and Set two other kv pairs. I think this logic makes more sense at a higher level.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Per standup discussion, let's run this by Cosmos to see if this is the intended semantics, or where it's more appropriate to put this logic.

}

func (s *Store) Iterator(start, end []byte) types.Iterator {
iter, err := s.data.Iterator(start, end)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think methods such as this one also highlight the issue with wrapping 3 distinct KVStores with a single KVStore- when we ask for an Iterator on this wrapping KVStore we are only getting the iterator for one of the underlying KVStores.

if err != nil {
panic(err.Error())
}
kvHash := sha256.Sum256(append(key, value...))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of looking up the value and hashing it and the key to reconstruct hash(key, value) we could lookup the hash(key, value) from the SC before deleting it. This appears preferable since both approaches require a DB lookup but this approach doesn't require a hashing step. What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That does indeed make more sense

tzdybal and others added 13 commits May 14, 2021 19:36
* Initial SMT store type

SMT (Sparse Merkle Tree) is intended to replace IAVL. New type
implements same interfaces as iavl.Store.

* Add iteration support to SMT

Sparse Merkle Tree does not support iteration over keys in order.
To provide drop-in replacement for IAVL, Iterator and ReverseIterator
has to be implemented.
SMT Store implementation use the underlying KV store to:
 - maintain a list of keys (under a prefix)
 - iterate over a keys
Values are stored only in SMT.

* Migrate to smt v0.1.1

* Extra test for SMT iterator

* CommitStore implementation for SMT store

* Use interface instead of concrete type

* Add telemetry to SMT store

* SMT: version->root mapping, cleanup

* SMT proofs - initial code

* Tests for SMT store ProofOp implementation

* Fix linter errors

* Use simple 1 byte KV-store prefixes

* Improve assertions in tests

* Use mutex properly

* Store data in ADR-040-compatible way

SMT stores:
 * key -> hash(key, value)

KV store stores:
 * key->value in "bucket 1",
 * hash(key, value) -> key in "bucket 2".
Outline of new store following ADR-040 pattern of decoupled
commitment/data concerns

Largely adapted from store/ll-smt branch
@roysc
Copy link
Collaborator Author

roysc commented May 28, 2021

This should be a MVP state store for #1.
Requires changes from the corresponding branch on tm-db: https://github.com/roysc/tm-db/tree/implement-adr-40 - (which just patches in minimal versioning support)

@roysc roysc requested a review from i-norden May 28, 2021 11:20
@roysc roysc changed the base branch from master to adr-40 June 1, 2021 13:39
roysc added 3 commits June 9, 2021 18:08
- Move tm-db code in from external repo
- Refactor store/ and types/ packages
- leaves out IAVL and multistore code pending confirmed deprecation
- some hacks to glue existing tmdb usage and get compile/tests working
- Update to new db interface
- Use smt as SC structure
- Refactor smt to BasicKVStore
@roysc
Copy link
Collaborator Author

roysc commented Jun 9, 2021

Moving this work to a PR on the main repo: cosmos#9485

@roysc roysc closed this Jun 9, 2021
@roysc roysc reopened this Jun 9, 2021
@roysc roysc closed this Jun 11, 2021
@roysc roysc reopened this Jun 11, 2021
@roysc roysc merged commit 4667744 into vulcanize:adr-40 Jun 11, 2021
@roysc roysc deleted the implement-adr-040 branch June 11, 2021 18:39
@i-norden i-norden changed the title [WIP] Implement decoupled state commitments and storage Implement decoupled state commitments and storage Aug 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Epic 1: Hook state store into SDK
4 participants