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

Remove tendermint-db dependency #405

Merged
merged 2 commits into from
Mar 8, 2023
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
21 changes: 3 additions & 18 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,14 @@ module github.com/CosmWasm/wasmvm
go 1.18

require (
github.com/google/btree v1.0.0
github.com/stretchr/testify v1.8.1
github.com/tendermint/tm-db v0.6.7
)

require (
github.com/DataDog/zstd v1.4.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de // indirect
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/golang/protobuf v1.4.3 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/btree v1.0.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect
go.etcd.io/bbolt v1.3.6 // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
173 changes: 0 additions & 173 deletions go.sum

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions internal/api/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ import (
"runtime/debug"
"unsafe"

dbm "github.com/tendermint/tm-db"

"github.com/CosmWasm/wasmvm/types"
)

Expand Down Expand Up @@ -140,7 +138,7 @@ const frameLenLimit = 32768

// contract: original pointer/struct referenced must live longer than C.Db struct
// since this is only used internally, we can verify the code that this is the case
func buildIterator(callID uint64, it dbm.Iterator) (C.iterator_t, error) {
func buildIterator(callID uint64, it types.Iterator) (C.iterator_t, error) {
idx, err := storeIterator(callID, it, frameLenLimit)
if err != nil {
return C.iterator_t{}, err
Expand Down Expand Up @@ -246,7 +244,7 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV
s := copyU8Slice(start)
e := copyU8Slice(end)

var iter dbm.Iterator
var iter types.Iterator
gasBefore := gm.GasConsumed()
switch order {
case 1: // Ascending
Expand Down
8 changes: 4 additions & 4 deletions internal/api/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"fmt"
"sync"

dbm "github.com/tendermint/tm-db"
"github.com/CosmWasm/wasmvm/types"
)

// frame stores all Iterators for one contract call
type frame []dbm.Iterator
type frame []types.Iterator

// iteratorFrames contains one frame for each contract call, indexed by contract call ID.
var (
Expand Down Expand Up @@ -56,7 +56,7 @@ func endCall(callID uint64) {
// storeIterator will add this to the end of the frame for the given ID and return a reference to it.
// We start counting with 1, so the 0 value is flagged as an error. This means we must
// remember to do idx-1 when retrieving
func storeIterator(callID uint64, it dbm.Iterator, frameLenLimit int) (uint64, error) {
func storeIterator(callID uint64, it types.Iterator, frameLenLimit int) (uint64, error) {
iteratorFramesMutex.Lock()
defer iteratorFramesMutex.Unlock()

Expand All @@ -75,7 +75,7 @@ func storeIterator(callID uint64, it dbm.Iterator, frameLenLimit int) (uint64, e
// retrieveIterator will recover an iterator based on index. This ensures it will not be garbage collected.
// We start counting with 1, in storeIterator so the 0 value is flagged as an error. This means we must
// remember to do idx-1 when retrieving
func retrieveIterator(callID uint64, index uint64) dbm.Iterator {
func retrieveIterator(callID uint64, index uint64) types.Iterator {
iteratorFramesMutex.Lock()
defer iteratorFramesMutex.Unlock()
myFrame := iteratorFrames[callID]
Expand Down
15 changes: 7 additions & 8 deletions internal/api/iterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

dbm "github.com/tendermint/tm-db"

"github.com/CosmWasm/wasmvm/internal/api/testdb"
"github.com/CosmWasm/wasmvm/types"
)

Expand Down Expand Up @@ -68,8 +67,8 @@ func TestStoreIterator(t *testing.T) {
callID1 := startCall()
callID2 := startCall()

store := dbm.NewMemDB()
var iter dbm.Iterator
store := testdb.NewMemDB()
var iter types.Iterator
var index uint64
var err error

Expand Down Expand Up @@ -102,8 +101,8 @@ func TestStoreIterator(t *testing.T) {
func TestStoreIteratorHitsLimit(t *testing.T) {
callID := startCall()

store := dbm.NewMemDB()
var iter dbm.Iterator
store := testdb.NewMemDB()
var iter types.Iterator
var err error
const limit = 2

Expand All @@ -127,8 +126,8 @@ func TestRetrieveIterator(t *testing.T) {
callID1 := startCall()
callID2 := startCall()

store := dbm.NewMemDB()
var iter dbm.Iterator
store := testdb.NewMemDB()
var iter types.Iterator
var err error

iter, _ = store.Iterator(nil, nil)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestInitAndReleaseCache(t *testing.T) {
ReleaseCache(cache)
}

// wasmd expectes us to create the base directory
// wasmd expects us to create the base directory
// https://github.com/CosmWasm/wasmd/blob/v0.30.0/x/wasm/keeper/keeper.go#L128
func TestInitCacheWorksForNonExistentDir(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "wasmvm-testing")
Expand Down
10 changes: 5 additions & 5 deletions internal/api/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"

"github.com/CosmWasm/wasmvm/internal/api/testdb"
"github.com/CosmWasm/wasmvm/types"
)

Expand Down Expand Up @@ -255,13 +255,13 @@ const (
)

type Lookup struct {
db *dbm.MemDB
db *testdb.MemDB
meter MockGasMeter
}

func NewLookup(meter MockGasMeter) *Lookup {
return &Lookup{
db: dbm.NewMemDB(),
db: testdb.NewMemDB(),
meter: meter,
}
}
Expand Down Expand Up @@ -305,7 +305,7 @@ func (l Lookup) Delete(key []byte) {
}

// Iterator wraps the underlying DB's Iterator method panicing on error.
func (l Lookup) Iterator(start, end []byte) dbm.Iterator {
func (l Lookup) Iterator(start, end []byte) types.Iterator {
l.meter.ConsumeGas(RangePrice, "range")
iter, err := l.db.Iterator(start, end)
if err != nil {
Expand All @@ -316,7 +316,7 @@ func (l Lookup) Iterator(start, end []byte) dbm.Iterator {
}

// ReverseIterator wraps the underlying DB's ReverseIterator method panicing on error.
func (l Lookup) ReverseIterator(start, end []byte) dbm.Iterator {
func (l Lookup) ReverseIterator(start, end []byte) types.Iterator {
l.meter.ConsumeGas(RangePrice, "range")
iter, err := l.db.ReverseIterator(start, end)
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions internal/api/testdb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Testdb
This package contains an in memory DB for testing purpose only. The original code was copied from
https://github.com/tendermint/tm-db/tree/v0.6.7 to decouple project dependencies.

All credits and a big thank you go to the original authors!
195 changes: 195 additions & 0 deletions internal/api/testdb/memdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package testdb

import (
"bytes"
"fmt"
"sync"

"github.com/google/btree"
)

const (
// The approximate number of items and children per B-tree node. Tuned with benchmarks.
bTreeDegree = 32
)

// item is a btree.Item with byte slices as keys and values
type item struct {
key []byte
value []byte
}

// Less implements btree.Item.
func (i *item) Less(other btree.Item) bool {
// this considers nil == []byte{}, but that's ok since we handle nil endpoints
// in iterators specially anyway
return bytes.Compare(i.key, other.(*item).key) == -1
}

// newKey creates a new key item.
func newKey(key []byte) *item {
return &item{key: key}
}

// newPair creates a new pair item.
func newPair(key, value []byte) *item {
return &item{key: key, value: value}
}

// MemDB is an in-memory database backend using a B-tree for storage.
//
// For performance reasons, all given and returned keys and values are pointers to the in-memory
// database, so modifying them will cause the stored values to be modified as well. All DB methods
// already specify that keys and values should be considered read-only, but this is especially
// important with MemDB.
type MemDB struct {
mtx sync.RWMutex
btree *btree.BTree
}

// NewMemDB creates a new in-memory database.
func NewMemDB() *MemDB {
database := &MemDB{
btree: btree.New(bTreeDegree),
}
return database
}

// Get implements DB.
func (db *MemDB) Get(key []byte) ([]byte, error) {
if len(key) == 0 {
return nil, errKeyEmpty
}
db.mtx.RLock()
defer db.mtx.RUnlock()

i := db.btree.Get(newKey(key))
if i != nil {
return i.(*item).value, nil
}
return nil, nil
}

// Has implements DB.
func (db *MemDB) Has(key []byte) (bool, error) {
if len(key) == 0 {
return false, errKeyEmpty
}
db.mtx.RLock()
defer db.mtx.RUnlock()

return db.btree.Has(newKey(key)), nil
}

// Set implements DB.
func (db *MemDB) Set(key []byte, value []byte) error {
if len(key) == 0 {
return errKeyEmpty
}
if value == nil {
return errValueNil
}
db.mtx.Lock()
defer db.mtx.Unlock()

db.set(key, value)
return nil
}

// set sets a value without locking the mutex.
func (db *MemDB) set(key []byte, value []byte) {
db.btree.ReplaceOrInsert(newPair(key, value))
}

// SetSync implements DB.
func (db *MemDB) SetSync(key []byte, value []byte) error {
return db.Set(key, value)
}

// Delete implements DB.
func (db *MemDB) Delete(key []byte) error {
if len(key) == 0 {
return errKeyEmpty
}
db.mtx.Lock()
defer db.mtx.Unlock()

db.delete(key)
return nil
}

// delete deletes a key without locking the mutex.
func (db *MemDB) delete(key []byte) {
db.btree.Delete(newKey(key))
}

// DeleteSync implements DB.
func (db *MemDB) DeleteSync(key []byte) error {
return db.Delete(key)
}

// Close implements DB.
func (db *MemDB) Close() error {
// Close is a noop since for an in-memory database, we don't have a destination to flush
// contents to nor do we want any data loss on invoking Close().
// See the discussion in https://github.com/tendermint/tendermint/libs/pull/56
return nil
}

// Print implements DB.
func (db *MemDB) Print() error {
db.mtx.RLock()
defer db.mtx.RUnlock()

db.btree.Ascend(func(i btree.Item) bool {
item := i.(*item)
fmt.Printf("[%X]:\t[%X]\n", item.key, item.value)
return true
})
return nil
}

// Stats implements DB.
func (db *MemDB) Stats() map[string]string {
db.mtx.RLock()
defer db.mtx.RUnlock()

stats := make(map[string]string)
stats["database.type"] = "memDB"
stats["database.size"] = fmt.Sprintf("%d", db.btree.Len())
return stats
}

// Iterator implements DB.
// Takes out a read-lock on the database until the iterator is closed.
func (db *MemDB) Iterator(start, end []byte) (Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, errKeyEmpty
}
return newMemDBIterator(db, start, end, false), nil
}

// ReverseIterator implements DB.
// Takes out a read-lock on the database until the iterator is closed.
func (db *MemDB) ReverseIterator(start, end []byte) (Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, errKeyEmpty
}
return newMemDBIterator(db, start, end, true), nil
}

// IteratorNoMtx makes an iterator with no mutex.
func (db *MemDB) IteratorNoMtx(start, end []byte) (Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, errKeyEmpty
}
return newMemDBIteratorMtxChoice(db, start, end, false, false), nil
}

// ReverseIteratorNoMtx makes an iterator with no mutex.
func (db *MemDB) ReverseIteratorNoMtx(start, end []byte) (Iterator, error) {
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
return nil, errKeyEmpty
}
return newMemDBIteratorMtxChoice(db, start, end, true, false), nil
}
Loading