-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
feat(store/v2): add support for iavl/v2 #22424
Changes from all commits
7b89c8f
a837b9b
906144b
ee21c4a
063a18f
c3415de
56ea0e5
200f7dd
e1f0574
bb2eeec
2f7ef1e
6b19d2b
84e5b38
37147bf
7a436e8
c815594
850914e
b59fe7f
d97ad63
e8e2f1b
8b7270d
a912d0f
f557fdd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,8 +25,8 @@ minimum-gas-prices = '0stake' | |
app-db-backend = 'goleveldb' | ||
|
||
[store.options] | ||
# State storage database type. Currently we support: "sqlite", "pebble" and "rocksdb" | ||
ss-type = 'sqlite' | ||
# State storage database type. Currently we support: "pebble" and "rocksdb" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Documentation update needed for SQLite removal The removal of SQLite support is not properly documented in the changelog or migration guides. While SQLite is mentioned in the store/v2 documentation as a supported backend, the removal is not documented. Based on ADR-065, SQLite is listed as one of the three default SS backends, which conflicts with the configuration comment change.
🔗 Analysis chainVerify documentation updates for removed SQLite support The comment has been updated to remove SQLite from supported database types. Please ensure this removal is properly documented in the project's documentation and changelog. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Check if the removal of SQLite support is documented
echo "Checking documentation for SQLite removal..."
rg -i "sqlite.*remov|deprecat.*sqlite" docs/
rg -i "sqlite.*remov|deprecat.*sqlite" CHANGELOG.md
Length of output: 199 Script: #!/bin/bash
# Let's check for any SQLite-related documentation or configuration files
echo "Checking for SQLite-related files and documentation..."
fd -t f -e md -e rst -e txt | xargs rg -i "sqlite"
# Check for SQLite in configuration files
fd -t f -e toml -e yaml -e conf | xargs rg -i "sqlite"
# Check if there are any migration guides
fd -t f -e md migration
Length of output: 884 Script: #!/bin/bash
# Let's check the content of the migration ADR and store v2 ADR
echo "Checking migration ADR content..."
cat docs/architecture/adr-041-in-place-store-migrations.md
echo -e "\nChecking store v2 ADR content..."
cat docs/architecture/adr-065-store-v2.md
Length of output: 24208 |
||
ss-type = 'pebble' | ||
# State commitment database type. Currently we support: "iavl" and "iavl-v2" | ||
sc-type = 'iavl' | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package iavlv2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add the tree test like iavl v1? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I implemented the tests, skipping snaphots for now. It needs to be filled out but that can be done in parallel with the performance tests I'm now doing. |
||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/cosmos/iavl/v2" | ||
ics23 "github.com/cosmos/ics23/go" | ||
|
||
corestore "cosmossdk.io/core/store" | ||
"cosmossdk.io/store/v2" | ||
"cosmossdk.io/store/v2/commitment" | ||
) | ||
|
||
var ( | ||
_ commitment.Tree = (*Tree)(nil) | ||
_ commitment.Reader = (*Tree)(nil) | ||
_ store.PausablePruner = (*Tree)(nil) | ||
) | ||
|
||
type Tree struct { | ||
tree *iavl.Tree | ||
} | ||
|
||
func NewTree(treeOptions iavl.TreeOptions, dbOptions iavl.SqliteDbOptions, pool *iavl.NodePool) (*Tree, error) { | ||
sql, err := iavl.NewSqliteDb(pool, dbOptions) | ||
if err != nil { | ||
return nil, err | ||
} | ||
tree := iavl.NewTree(sql, pool, treeOptions) | ||
return &Tree{tree: tree}, nil | ||
} | ||
|
||
func (t *Tree) Set(key, value []byte) error { | ||
_, err := t.tree.Set(key, value) | ||
return err | ||
} | ||
|
||
func (t *Tree) Remove(key []byte) error { | ||
_, _, err := t.tree.Remove(key) | ||
return err | ||
} | ||
|
||
func (t *Tree) GetLatestVersion() (uint64, error) { | ||
return uint64(t.tree.Version()), nil | ||
} | ||
|
||
func (t *Tree) Hash() []byte { | ||
return t.tree.Hash() | ||
} | ||
|
||
func (t *Tree) Version() uint64 { | ||
return uint64(t.tree.Version()) | ||
} | ||
|
||
func (t *Tree) LoadVersion(version uint64) error { | ||
if err := isHighBitSet(version); err != nil { | ||
return err | ||
} | ||
|
||
if version == 0 { | ||
return nil | ||
} | ||
return t.tree.LoadVersion(int64(version)) | ||
} | ||
|
||
func (t *Tree) Commit() ([]byte, uint64, error) { | ||
h, v, err := t.tree.SaveVersion() | ||
return h, uint64(v), err | ||
} | ||
|
||
func (t *Tree) SetInitialVersion(version uint64) error { | ||
if err := isHighBitSet(version); err != nil { | ||
return err | ||
} | ||
t.tree.SetShouldCheckpoint() | ||
return t.tree.SetInitialVersion(int64(version)) | ||
} | ||
|
||
func (t *Tree) GetProof(version uint64, key []byte) (*ics23.CommitmentProof, error) { | ||
if err := isHighBitSet(version); err != nil { | ||
return nil, err | ||
} | ||
return t.tree.GetProof(int64(version), key) | ||
} | ||
|
||
func (t *Tree) Get(version uint64, key []byte) ([]byte, error) { | ||
if err := isHighBitSet(version); err != nil { | ||
return nil, err | ||
} | ||
if int64(version) != t.tree.Version() { | ||
cloned, err := t.tree.ReadonlyClone() | ||
if err != nil { | ||
return nil, err | ||
} | ||
if err = cloned.LoadVersion(int64(version)); err != nil { | ||
return nil, err | ||
} | ||
return cloned.Get(key) | ||
} else { | ||
return t.tree.Get(key) | ||
} | ||
} | ||
|
||
func (t *Tree) Iterator(version uint64, start, end []byte, ascending bool) (corestore.Iterator, error) { | ||
if err := isHighBitSet(version); err != nil { | ||
return nil, err | ||
} | ||
if int64(version) != t.tree.Version() { | ||
return nil, fmt.Errorf("loading past version not yet supported") | ||
} | ||
return t.tree.Iterator(start, end, ascending) | ||
} | ||
|
||
func (t *Tree) Export(version uint64) (commitment.Exporter, error) { | ||
return nil, errors.New("snapshot import/export not yet supported") | ||
} | ||
|
||
func (t *Tree) Import(version uint64) (commitment.Importer, error) { | ||
return nil, errors.New("snapshot import/export not yet supported") | ||
} | ||
|
||
func (t *Tree) Close() error { | ||
return t.tree.Close() | ||
} | ||
|
||
func (t *Tree) Prune(version uint64) error { | ||
if err := isHighBitSet(version); err != nil { | ||
return err | ||
} | ||
|
||
return t.tree.DeleteVersionsTo(int64(version)) | ||
} | ||
|
||
// PausePruning is unnecessary in IAVL v2 due to the advanced pruning mechanism | ||
func (t *Tree) PausePruning(bool) {} | ||
|
||
func (t *Tree) WorkingHash() []byte { | ||
return t.tree.Hash() | ||
} | ||
|
||
func isHighBitSet(version uint64) error { | ||
if version&(1<<63) != 0 { | ||
return fmt.Errorf("%d too large; uint64 with the highest bit set are not supported", version) | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error handling in PebbleDB initialization
The current implementation discards potential initialization errors using a blank identifier (
_
). Since this is a critical storage component, proper error handling is essential.Consider this improvement: