feat: ADR-040: Implement BadgerDB backend (#9848)

## Description

Partially resolves: https://github.com/vulcanize/cosmos-sdk/issues/14

Implements a [BadgerDB](https://pkg.go.dev/github.com/dgraph-io/badger/v3)-based backend for the DB interface introduced by https://github.com/cosmos/cosmos-sdk/pull/9573 and specified by [ADR-040](https://github.com/cosmos/cosmos-sdk/blob/eb7d939f86c6cd7b4218492364cdda3f649f06b5/docs/architecture/adr-040-storage-and-smt-state-commitments.md). This uses Badger's "managed" mode for version management, and supports optimistically concurrent transactions (required one [patch](https://github.com/dgraph-io/badger/pull/1716) upstream to fix handling of write conflicts).

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - n/a
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [x] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
This commit is contained in:
2021-09-15 02:58:10 +00:00
committed by GitHub
parent 7e90194ec6
commit ae9834e60f
8 changed files with 654 additions and 40 deletions
+42 -33
View File
@@ -369,16 +369,19 @@ func DoTestReloadDB(t *testing.T, load Loader) {
dirname := t.TempDir()
db := load(t, dirname)
txn := db.Writer()
for i := 0; i < 100; i++ {
require.NoError(t, txn.Set(ikey(i), ival(i)))
}
require.NoError(t, txn.Commit())
first, err := db.SaveNextVersion()
require.NoError(t, err)
var firstVersions []uint64
txn = db.Writer()
for i := 0; i < 50; i++ { // overwrite some values
for i := 0; i < 10; i++ {
txn := db.Writer()
require.NoError(t, txn.Set(ikey(i), ival(i)))
require.NoError(t, txn.Commit())
ver, err := db.SaveNextVersion()
require.NoError(t, err)
firstVersions = append(firstVersions, ver)
}
txn := db.Writer()
for i := 0; i < 5; i++ { // overwrite some values
require.NoError(t, txn.Set(ikey(i), ival(i*10)))
}
require.NoError(t, txn.Commit())
@@ -386,45 +389,51 @@ func DoTestReloadDB(t *testing.T, load Loader) {
require.NoError(t, err)
txn = db.Writer()
for i := 100; i < 150; i++ {
require.NoError(t, txn.Set(ikey(i), ival(i)))
}
require.NoError(t, txn.Set(ikey(100), ival(100)))
require.NoError(t, txn.Commit())
db.Close()
// Reload and check each saved version
db.Close()
db = load(t, dirname)
view, err := db.ReaderAt(first)
// require.True(t, db.Versions().Equal(versions))
vset, err := db.Versions()
require.NoError(t, err)
for i := 0; i < 100; i++ {
v, err := view.Get(ikey(i))
require.NoError(t, err)
require.Equal(t, ival(i), v)
}
view.Discard()
require.Equal(t, last, vset.Last())
view, err = db.ReaderAt(last)
require.NoError(t, err)
for i := 0; i < 50; i++ {
v, err := view.Get(ikey(i))
require.NoError(t, err)
require.Equal(t, ival(i*10), v)
txn = db.Writer()
for i := 10; i < 15; i++ {
require.NoError(t, txn.Set(ikey(i), ival(i+10)))
}
for i := 50; i < 100; i++ {
require.NoError(t, txn.Commit())
for i := 0; i < 10; i++ {
view, err := db.ReaderAt(firstVersions[i])
require.NoError(t, err)
val, err := view.Get(ikey(i))
require.NoError(t, err)
require.Equal(t, ival(i), val)
view.Discard()
}
view, err := db.ReaderAt(last)
require.NoError(t, err)
for i := 0; i < 10; i++ {
v, err := view.Get(ikey(i))
require.NoError(t, err)
require.Equal(t, ival(i), v)
if i < 5 {
require.Equal(t, ival(i*10), v)
} else {
require.Equal(t, ival(i), v)
}
}
view.Discard()
// Load working version
view = db.Reader()
for i := 100; i < 150; i++ {
v, err := view.Get(ikey(i))
require.NoError(t, err)
require.Equal(t, ival(i), v)
}
val, err := view.Get(ikey(100))
require.NoError(t, err)
require.Equal(t, ival(100), val)
view.Discard()
require.NoError(t, db.Close())