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

docs(pkg/triedb): Add trieDB readme #4103

Merged
merged 2 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,30 @@ Then start the three hosts:
./bin/gossamer --chain westend-local --charlie
```

## Standalone Packages

In addition to the core functionality provided by Gossamer, we have developed some standalone packages that can be used independently. These packages are located in the `pkg` directory and serve various utility purposes. Here’s an overview of some of these packages:

### Scale

To support parity's [scale type encoding](https://docs.substrate.io/reference/scale-codec/) in golang.
More details [here](./pkg/scale/README.md)

### Trie

The `trie` package includes multiple implementations of polkadot merkle tries. These implementations are useful for various applications requiring efficient data structures. Here are the key implementations:

#### In-Memory Trie

This implementation supports polkadot merkle tries that are stored entirely in memory. It includes features for backing up the trie using a database to ensure persistence.

#### TrieDB

An evolution of the in-memory trie, `TrieDB` introduces lazy loading capabilities from the underlying database. This approach optimizes performance and resource usage by loading data only as needed.

For more details on how to use `TrieDB`, refer to the specific [README](pkg/trie/triedb/README.md)


## Contribute

- Check out the [Contributing Guidelines](.github/CONTRIBUTING.md) and our
Expand Down
114 changes: 114 additions & 0 deletions pkg/trie/triedb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# trieDB


`triedb` is a library that acts as a layer over a key-value database, formatting those data into a radix-16 trie compatible with [polkadot spec](https://spec.polkadot.network/chap-state#sect-state-storage).
It offers functionalities for writing and reading operations and uses lazy loading to fetch data from the database, as well as a caching system to optimize searches.

## Main features

- **Writes**: Basic functions to manipulate data in the trie.
- **Reads**: Basic functions to get data from the trie.
- **Lazy Loading**: Load data on demand.
- **Caching**: Enhances search performance.
- **Compatibility**: Works with any database implementing the `db.RWDatabase` interface and any cache implementing the `cache.TrieCache` interface.
- **Merkle proofs**: Create and verify merkle proofs.
- **Iterator**: Traverse the trie keys in order.

## Usage

### Create a Trie

To create an empty trie:

```go
trie := triedb.NewEmptyTrieDB(db)
```

### Insert Data

To insert a key and its associated value:

```go
err := trie.Put([]byte("key"), []byte("value"))
```

### Get Data

To get the value associated with a key:

```go
value := trie.Get([]byte("key"))
```

> Note: value will be empty `[]byte()` if there is no value for that key in the DB


### Remove Data

To delete a key and its associated value:

```go
trie.Delete([]byte("key"))
```

### Commit Data

All modifications happen in memory until a commit is applied to the database. The commit is automatically applied whenever the root hash of the trie is calculated using:

```go
rootHash, err := trie.Hash()
if err != nil {
// handle error
}
```

or

```go
rootHash := trie.MustHash()
```

### Create a merkle proof

To create a merkle proof you will need a `db` previously created using a trie, the `trieVersion` (v0, v1), the `rootHash` for the trie in that db and an slice of `keys` for which the proof will be created.

```go
merkleProof, err := proof.NewMerkleProof(db, trieVersion, rootHash, keys)
```

### Verify merkle proofs

In order to verify a merkle proof you can execute the `Verify` method over a previously created proof specifying the `trieVersion`, `rootHash` and the `items` you want to check, doing the following:

```go
err = merkleProof.Verify(trieVersion, rootHash, items)
if err != nil {
fmt.Println("Invalid proof")
}
```

> Note: items is a slice of `proofItem` structure.

### Iterator

There are two ways to use the key iterator.
Iterating by keys

```go
trieIterator := triedb.NewTrieDBIterator(trie)

for key := iter.NextKey(); key != nil; key = iter.NextKey() {
fmt.Printf("key: %s", key)
}
```

Iterating by entries

```go
trieIterator := triedb.NewTrieDBIterator(trie)

for entry := iter.NextEntry(); entry != nil; entry = iter.NextEntry() {
fmt.Printf("key: %s, value: %s", entry.Key, entry.Value)
}
```

Loading