Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
ad3e462
[WIP] pulls stateTrees into its own file
dylanlott May 26, 2023
5cca7b3
[WIP] Refactoring to use SMT trees
dylanlott Jun 1, 2023
c67edde
[WIP] adds pool support
dylanlott Jun 5, 2023
99d7b5b
[WIP] add accounts and params support
dylanlott Jun 5, 2023
7cafd6c
[WIP] implement ClearAll for treeStore
dylanlott Jun 5, 2023
1695338
[WIP] test_persistence is passing locally
dylanlott Jun 6, 2023
90d6a64
[WIP] updates comments and simplifies NewTreeStore function signature
dylanlott Jun 6, 2023
d0e72b6
adds comments
dylanlott Jun 8, 2023
9125183
changelogs
dylanlott Jun 8, 2023
7aa0e44
add stubbed out test case
dylanlott Jun 9, 2023
b3e1156
changelogs
dylanlott Jun 13, 2023
622778e
changelogs
dylanlott Jun 14, 2023
f917aa6
updates
dylanlott Jun 14, 2023
f35bc5b
refactors the sql handling into a separate package
dylanlott Jun 15, 2023
89de845
nits to comments in sql.go
Olshansk Jun 16, 2023
e64af30
Updated comment on tree ordering techdebt
Olshansk Jun 16, 2023
d434726
Change root hash calculation to use an SMT
h5law Jun 19, 2023
4256412
remove iota and use names
h5law Jun 19, 2023
a1036ed
Fail on err updating root tree for state hash
h5law Jun 19, 2023
51559ba
Give root store a nodeStore backend
h5law Jun 19, 2023
58a4deb
Iterate using map not names slice
h5law Jun 19, 2023
667a870
Update documentation
h5law Jun 20, 2023
8e214bf
Export tree names and allow tree access outside of treeStore
h5law Jun 20, 2023
ce707bc
Fix captitals
h5law Jun 20, 2023
a3ff4ab
Add unit test to cover StateTree accessors
h5law Jun 20, 2023
d4e1694
Address linter errors
h5law Jun 20, 2023
6a236ab
Address comments
h5law Jun 20, 2023
81985d4
remove dead code
dylanlott Jun 20, 2023
5fa8511
update comments
dylanlott Jun 20, 2023
5d2d1c1
updates
dylanlott Jun 20, 2023
eb3388b
updates
dylanlott Jun 20, 2023
e65a656
updates
dylanlott Jun 20, 2023
3be5d25
adds techdebt comment
dylanlott Jun 20, 2023
0aa8aad
spelling error for linter
dylanlott Jun 21, 2023
9a0207e
Merge branch 'persistence/tree-store' into persistence/root-hash-tree
h5law Jun 21, 2023
2e694e1
Change tree export method
h5law Jun 21, 2023
91b6ce6
Fix errors
h5law Jun 21, 2023
4de90bd
[WIP] pulls stateTrees into its own file
dylanlott May 26, 2023
0fa3984
[WIP] Refactoring to use SMT trees
dylanlott Jun 1, 2023
377ea5c
[WIP] adds pool support
dylanlott Jun 5, 2023
afbbcfd
[WIP] add accounts and params support
dylanlott Jun 5, 2023
25af7d4
[WIP] implement ClearAll for treeStore
dylanlott Jun 5, 2023
68bc5f0
[WIP] test_persistence is passing locally
dylanlott Jun 6, 2023
0878e89
[WIP] updates comments and simplifies NewTreeStore function signature
dylanlott Jun 6, 2023
428a71a
adds comments
dylanlott Jun 8, 2023
35632f1
changelogs
dylanlott Jun 8, 2023
141ab33
add stubbed out test case
dylanlott Jun 9, 2023
d0511c5
changelogs
dylanlott Jun 13, 2023
d74032d
changelogs
dylanlott Jun 14, 2023
1b277ce
updates
dylanlott Jun 14, 2023
3d5701d
refactors the sql handling into a separate package
dylanlott Jun 15, 2023
5a26797
nits to comments in sql.go
Olshansk Jun 16, 2023
61936e9
Updated comment on tree ordering techdebt
Olshansk Jun 16, 2023
905bcc6
remove dead code
dylanlott Jun 20, 2023
9403106
update comments
dylanlott Jun 20, 2023
a34ff05
updates
dylanlott Jun 20, 2023
52172a0
updates
dylanlott Jun 20, 2023
e3a3081
updates
dylanlott Jun 20, 2023
b3371d2
adds techdebt comment
dylanlott Jun 20, 2023
70537ca
spelling error for linter
dylanlott Jun 21, 2023
690a0ad
Merge branch 'main' into persistence/root-hash-tree
h5law Jun 21, 2023
1225e61
Merge branch 'persistence/tree-store' into persistence/root-hash-tree
h5law Jun 21, 2023
238d033
Merge branch 'main' into persistence/root-hash-tree
h5law Jun 22, 2023
3874051
Merge branch 'main' into persistence/root-hash-tree
h5law Jun 22, 2023
7581295
Expose treestore outside of persistence
h5law Jun 22, 2023
b0cb2c5
Change root tree fatal log line
h5law Jun 22, 2023
b168429
Fix leftover import
h5law Jun 22, 2023
d13e2ee
Merge branch 'main' into persistence/root-hash-tree
h5law Jun 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions persistence/docs/PROTOCOL_STATE_HASH.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ This document defines how Pocket V1 takes a snapshot of its world state. An intr

### Infrastructural Components

| Component | Data Type | Implementation Options - Examples | Implementation Selected - Current | Example | Use Case |
| --------------------- | ------------------------------------- | ------------------------------------------------------ | --------------------------------- | ------------------- | -------------------------------------------------------------------------------- |
| Data Tables | SQL Database / Engine | MySQL, SQLite, PostgreSQL | PostgresSQL | Validator SQL Table | Validating & updating information when applying a transaction |
| Merkle Trees | Merkle Trie backed by Key-Value Store | Celestia's SMT, Libra's JMT, Cosmos' IAVL, Verkle Tree | Celestia's SMT | Fisherman Trie | Maintains the state of all account based trees |
| Blocks | Serialization Codec | Amino, Protobuf, Thrift, Avro | Protobuf | Block protobuf | Serialized and inserted into the Block Store |
| Objects (e.g. Actors) | Serialization Codec | Amino, Protobuf, Thrift, Avro | Protobuf | Servicer protobuf | Serialized and inserted into the corresponding Tree |
| Block Store | Key Value Store | LevelDB, BadgerDB, RocksDB, BoltDB | BadgerDb | Block Store | Maintains a key-value store of the blockchain blocks |
| Transaction Indexer | Key Value Store | LevelDB, BadgerDB, RocksDB, BoltDB | BadgerDB | Tx Indexer | Indexes transactions in different ways for fast queries, presence checks, etc... |
| Component | Data Type | Implementation Options - Examples | Implementation Selected - Current | Example | Use Case |
| --------------------- | ------------------------------------- | ------------------------------------------------------ | ----------------------------------- | ------------------- | -------------------------------------------------------------------------------- |
| Data Tables | SQL Database / Engine | MySQL, SQLite, PostgreSQL | PostgresSQL | Validator SQL Table | Validating & updating information when applying a transaction |
| Merkle Trees | Merkle Trie backed by Key-Value Store | Celestia's SMT, Libra's JMT, Cosmos' IAVL, Verkle Tree | Pocket's SMT (Forked from Celestia) | Fisherman Trie | Maintains the state of all account based trees |
| Blocks | Serialization Codec | Amino, Protobuf, Thrift, Avro | Protobuf | Block protobuf | Serialized and inserted into the Block Store |
| Objects (e.g. Actors) | Serialization Codec | Amino, Protobuf, Thrift, Avro | Protobuf | Servicer protobuf | Serialized and inserted into the corresponding Tree |
| Block Store | Key Value Store | LevelDB, BadgerDB, RocksDB, BoltDB | BadgerDb | Block Store | Maintains a key-value store of the blockchain blocks |
| Transaction Indexer | Key Value Store | LevelDB, BadgerDB, RocksDB, BoltDB | BadgerDB | Tx Indexer | Indexes transactions in different ways for fast queries, presence checks, etc... |

### Block Proto

Expand All @@ -40,8 +40,6 @@ The block protobuf that is serialized and store in the block store can be found

An individual Merkle Tree is created for each type of actor, record or data type. Each of these is backed by its own key-value store.

Note that the order in which the trees are defined (found in `persistence/state.go`) is important since it determines how the state hash is computed. _TODO(#361): Consider specifying the oder in a `.proto` `enum` rather than a `.go` `iota`._

**Actor Merkle Trees**:

- Applications
Expand Down Expand Up @@ -71,8 +69,8 @@ This flow shows the interaction between the `PostgresDB` and `MerkleTrees` liste
3. Serialize each record using the corresponding underlying protobuf
4. Insert the serialized record into the corresponding tree (which is back by a key-value store)
5. Compute the root hash of each tree
6. Aggregate all the root hashes by concatenating them together
7. Compute the new `stateHash` by taking a hash of the concatenated hash list
6. Insert the name of the tree and its root hash into the root tree
7. Compute the new `stateHash` by hex encoding the root tree's root hash

```mermaid
sequenceDiagram
Expand All @@ -89,15 +87,15 @@ sequenceDiagram
end
P->>+PKV: GetRoot()
PKV->>-P: rootHash
P->>P: rootTree.Update(stateTreeName, rootHash)
end

P->>P: stateHash = hash(concat(rootHashes))
P->>P: stateHash = hex(rootTree.Root())

activate P
deactivate P
```

_IMPORTANT: The order in which the `rootHashes` are concatenated is based on the definition in which the trees are ordered in within `state.go`._

## Store Block (Commit)

When the `Commit(proposer, quorumCert)` function is invoked, the current context is committed to disk. The `PersistenceContext` does the following:
Expand Down
4 changes: 4 additions & 0 deletions persistence/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ func (m *persistenceModule) GetTxIndexer() indexer.TxIndexer {
return m.txIndexer
}

func (m *persistenceModule) GetTreeStore() modules.TreeStoreModule {
return m.stateTrees
}

func (m *persistenceModule) GetNetworkID() string {
return m.networkId
}
Expand Down
6 changes: 3 additions & 3 deletions persistence/test/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ func TestStateHash_DeterministicStateWhenUpdatingAppStake(t *testing.T) {
// logic changes, these hashes will need to be updated based on the test output.
// TODO: Add an explicit updateSnapshots flag to the test to make this more clear.
stateHashes := []string{
"6a30f096c86793de894388aad171e84c5ce766cbd82c5a5d36ca53d6c99ac041",
"c5840401da7028948f6d025867249fb9f9a9e738b36158669a64746e5b4f3ed2",
"209a2bda7e9a4495f45281e726777b33f54ac61868c8d8a059719cb5cefd2f75",
"fb1c1b2da242eb6148884e1f11c184c673963b6fcb59feea4ea51c9840e4b56c",
"9ae40f9fd0864c01760c19d6688d1c7bba5ad746fc3f7123cf071b142c2a302a",
"5c13743e9d29e83cbff1301e3750c7583e365b2c3fd81b643ed8db985f46268f",
}

stakeAmount := initialStakeAmount
Expand Down
43 changes: 30 additions & 13 deletions persistence/trees/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,47 @@ func (t *treeStore) setupTrees() error {
return t.setupInMemory()
}

t.merkleTrees = make(map[merkleTree]*smt.SMT, int(numMerkleTrees))
t.nodeStores = make(map[merkleTree]kvstore.KVStore, int(numMerkleTrees))
nodeStore, err := kvstore.NewKVStore(fmt.Sprintf("%s/%s_nodes", t.treeStoreDir, RootTreeName))
if err != nil {
return err
}
t.rootTree = &stateTree{
name: RootTreeName,
tree: smt.NewSparseMerkleTree(nodeStore, smtTreeHasher),
nodeStore: nodeStore,
}
t.merkleTrees = make(map[string]*stateTree, len(stateTreeNames))

for tree := merkleTree(0); tree < numMerkleTrees; tree++ {
nodeStore, err := kvstore.NewKVStore(fmt.Sprintf("%s/%s_nodes", t.treeStoreDir, merkleTreeToString[tree]))
for i := 0; i < len(stateTreeNames); i++ {
nodeStore, err := kvstore.NewKVStore(fmt.Sprintf("%s/%s_nodes", t.treeStoreDir, stateTreeNames[i]))
if err != nil {
return err
}
t.nodeStores[tree] = nodeStore
t.merkleTrees[tree] = smt.NewSparseMerkleTree(nodeStore, smtTreeHasher)
t.merkleTrees[stateTreeNames[i]] = &stateTree{
name: stateTreeNames[i],
tree: smt.NewSparseMerkleTree(nodeStore, smtTreeHasher),
nodeStore: nodeStore,
}
}

return nil
}

func (t *treeStore) setupInMemory() error {
t.merkleTrees = make(map[merkleTree]*smt.SMT, int(numMerkleTrees))
t.nodeStores = make(map[merkleTree]kvstore.KVStore, int(numMerkleTrees))

for tree := merkleTree(0); tree < numMerkleTrees; tree++ {
nodeStore := kvstore.NewMemKVStore()
t.rootTree = &stateTree{
name: RootTreeName,
tree: smt.NewSparseMerkleTree(nodeStore, smtTreeHasher),
nodeStore: nodeStore,
}
t.merkleTrees = make(map[string]*stateTree, len(stateTreeNames))
for i := 0; i < len(stateTreeNames); i++ {
nodeStore := kvstore.NewMemKVStore() // For testing, `smt.NewSimpleMap()` can be used as well
t.nodeStores[tree] = nodeStore
t.merkleTrees[tree] = smt.NewSparseMerkleTree(nodeStore, smtTreeHasher)
t.merkleTrees[stateTreeNames[i]] = &stateTree{
name: stateTreeNames[i],
tree: smt.NewSparseMerkleTree(nodeStore, smtTreeHasher),
nodeStore: nodeStore,
}
}

return nil
}
Loading