Merge branch 'master' of https://github.com/cosmos/ethermint into aditya/ante-test

This commit is contained in:
Aditya Sripal 2018-08-16 15:37:14 -07:00
commit 9e5ddf87b2
6 changed files with 54 additions and 41 deletions

View File

@ -59,6 +59,8 @@ type Database struct {
// EXTCODESIZE calls. // EXTCODESIZE calls.
codeSizeCache *lru.Cache codeSizeCache *lru.Cache
storeCache *lru.Cache
Tracing bool Tracing bool
} }
@ -66,7 +68,7 @@ type Database struct {
// implements Ethereum's state.Database interface. An error is returned if the // implements Ethereum's state.Database interface. An error is returned if the
// latest state failed to load. The underlying storage structure is defined by // latest state failed to load. The underlying storage structure is defined by
// the Cosmos SDK IAVL tree. // the Cosmos SDK IAVL tree.
func NewDatabase(stateDB, codeDB dbm.DB) (*Database, error) { func NewDatabase(stateDB, codeDB dbm.DB, storeCacheSize int) (*Database, error) {
// Initialize an implementation of Ethereum state.Database and create a // Initialize an implementation of Ethereum state.Database and create a
// Cosmos SDK multi-store. // Cosmos SDK multi-store.
db := &Database{ db := &Database{
@ -93,7 +95,15 @@ func NewDatabase(stateDB, codeDB dbm.DB) (*Database, error) {
db.codeDB = codeDB db.codeDB = codeDB
db.ethTrieDB = ethtrie.NewDatabase(&core.EthereumDB{CodeDB: codeDB}) db.ethTrieDB = ethtrie.NewDatabase(&core.EthereumDB{CodeDB: codeDB})
db.codeSizeCache, _ = lru.New(codeSizeCacheSize) var err error
if db.codeSizeCache, err = lru.New(codeSizeCacheSize); err != nil {
return nil, err
}
if db.storeCache, err = lru.New(storeCacheSize); err != nil {
return nil, err
}
return db, nil return db, nil
} }
@ -133,6 +143,7 @@ func (db *Database) OpenTrie(root ethcmn.Hash) (ethstate.Trie, error) {
store: db.accountsCache, store: db.accountsCache,
accountsCache: db.accountsCache, accountsCache: db.accountsCache,
storageCache: db.storageCache, storageCache: db.storageCache,
storeCache: db.storeCache,
ethTrieDB: db.ethTrieDB, ethTrieDB: db.ethTrieDB,
empty: isRootEmpty(root), empty: isRootEmpty(root),
root: rootHashFromVersion(db.stateStore.LastCommitID().Version), root: rootHashFromVersion(db.stateStore.LastCommitID().Version),
@ -155,6 +166,7 @@ func (db *Database) OpenStorageTrie(addrHash, root ethcmn.Hash) (ethstate.Trie,
// an Ethereum trie because it will not be used upon commitment. // an Ethereum trie because it will not be used upon commitment.
return &Trie{ return &Trie{
store: db.storageCache, store: db.storageCache,
storeCache: db.storeCache,
prefix: addrHash.Bytes(), prefix: addrHash.Bytes(),
empty: isRootEmpty(root), empty: isRootEmpty(root),
root: rootHashFromVersion(db.stateStore.LastCommitID().Version), root: rootHashFromVersion(db.stateStore.LastCommitID().Version),

View File

@ -7,25 +7,17 @@ import (
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
ethstate "github.com/ethereum/go-ethereum/core/state" ethstate "github.com/ethereum/go-ethereum/core/state"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
dbm "github.com/tendermint/tendermint/libs/db"
) )
func newDatabase() *Database {
memDB := dbm.NewMemDB()
db, _ := NewDatabase(memDB, memDB)
return db
}
func TestDatabaseInterface(t *testing.T) { func TestDatabaseInterface(t *testing.T) {
require.Implements(t, (*ethstate.Database)(nil), new(Database)) require.Implements(t, (*ethstate.Database)(nil), new(Database))
} }
func TestDatabaseLatestVersion(t *testing.T) { func TestDatabaseLatestVersion(t *testing.T) {
testDB := newDatabase()
var version int64 var version int64
testDB := newTestDatabase()
version = testDB.LatestVersion() version = testDB.LatestVersion()
require.Equal(t, int64(0), version) require.Equal(t, int64(0), version)
@ -34,27 +26,13 @@ func TestDatabaseLatestVersion(t *testing.T) {
require.Equal(t, int64(1), version) require.Equal(t, int64(1), version)
} }
// func TestDatabaseOpenTrie(t *testing.T) {
// testDB := newDatabase()
// testTrie, err := testDB.OpenTrie(rootHashFromVersion(0))
// require.Nil(t, err)
// require.IsType(t, &Trie{}, testTrie)
// require.NotNil(t, testTrie.(*Trie).store)
// require.NotNil(t, testTrie.(*Trie).accountsCache)
// require.NotNil(t, testTrie.(*Trie).storageCache)
// require.NotNil(t, testTrie.(*Trie).ethTrieDB)
// require.False(t, testTrie.(*Trie).empty)
// }
func TestDatabaseCopyTrie(t *testing.T) { func TestDatabaseCopyTrie(t *testing.T) {
// TODO: Implement once CopyTrie is implemented // TODO: Implement once CopyTrie is implemented
t.SkipNow() t.SkipNow()
} }
func TestDatabaseContractCode(t *testing.T) { func TestDatabaseContractCode(t *testing.T) {
testDB := newDatabase() testDB := newTestDatabase()
testCases := []struct { testCases := []struct {
db *Database db *Database
@ -87,7 +65,7 @@ func TestDatabaseContractCode(t *testing.T) {
} }
func TestDatabaseContractCodeSize(t *testing.T) { func TestDatabaseContractCodeSize(t *testing.T) {
testDB := newDatabase() testDB := newTestDatabase()
testCases := []struct { testCases := []struct {
db *Database db *Database
@ -125,7 +103,7 @@ func TestDatabaseContractCodeSize(t *testing.T) {
} }
func TestDatabaseTrieDB(t *testing.T) { func TestDatabaseTrieDB(t *testing.T) {
testDB := newDatabase() testDB := newTestDatabase()
db := testDB.TrieDB() db := testDB.TrieDB()
require.Equal(t, testDB.ethTrieDB, db) require.Equal(t, testDB.ethTrieDB, db)

View File

@ -1,10 +1,13 @@
package state package state
import ( import (
"fmt"
"math/rand" "math/rand"
"time" "time"
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
dbm "github.com/tendermint/tendermint/libs/db"
) )
type ( type (
@ -21,3 +24,14 @@ type (
func init() { func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
func newTestDatabase() *Database {
memDB := dbm.NewMemDB()
testDB, err := NewDatabase(memDB, memDB, 100)
if err != nil {
panic(fmt.Sprintf("failed to create database: %v", err))
}
return testDB
}

View File

@ -8,6 +8,8 @@ import (
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
ethdb "github.com/ethereum/go-ethereum/ethdb" ethdb "github.com/ethereum/go-ethereum/ethdb"
ethtrie "github.com/ethereum/go-ethereum/trie" ethtrie "github.com/ethereum/go-ethereum/trie"
lru "github.com/hashicorp/golang-lru"
) )
const ( const (
@ -25,6 +27,8 @@ type Trie struct {
// ordering. // ordering.
storageCache store.CacheKVStore storageCache store.CacheKVStore
storeCache *lru.Cache
// Store is an IAVL KV store that is part of a larger store except it used // Store is an IAVL KV store that is part of a larger store except it used
// for a specific prefix. It will either be an accountsCache or a // for a specific prefix. It will either be an accountsCache or a
// storageCache. // storageCache.
@ -64,8 +68,13 @@ func (t *Trie) TryGet(key []byte) ([]byte, error) {
if t.IsStorageTrie() { if t.IsStorageTrie() {
key = t.prefixKey(key) key = t.prefixKey(key)
} }
keyStr := string(key)
return t.store.Get(key), nil if cached, ok := t.storeCache.Get(keyStr); ok {
return cached.([]byte), nil
}
value := t.store.Get(key)
t.storeCache.Add(keyStr, value)
return value, nil
} }
// TryUpdate implements the Ethereum state.Trie interface. It associates a // TryUpdate implements the Ethereum state.Trie interface. It associates a
@ -83,6 +92,7 @@ func (t *Trie) TryUpdate(key, value []byte) error {
} }
t.store.Set(key, value) t.store.Set(key, value)
t.storeCache.Add(string(key), value)
return nil return nil
} }
@ -98,6 +108,7 @@ func (t *Trie) TryDelete(key []byte) error {
} }
t.store.Delete(key) t.store.Delete(key)
t.storeCache.Remove(string(key))
return nil return nil
} }

View File

@ -8,20 +8,17 @@ import (
ethcmn "github.com/ethereum/go-ethereum/common" ethcmn "github.com/ethereum/go-ethereum/common"
ethstate "github.com/ethereum/go-ethereum/core/state" ethstate "github.com/ethereum/go-ethereum/core/state"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
dbm "github.com/tendermint/tendermint/libs/db"
) )
func newTestTrie() *Trie { func newTestTrie() *Trie {
memDB := dbm.NewMemDB() testDB := newTestDatabase()
testDB, _ := NewDatabase(memDB, memDB)
testTrie, _ := testDB.OpenTrie(rootHashFromVersion(0)) testTrie, _ := testDB.OpenTrie(rootHashFromVersion(0))
return testTrie.(*Trie) return testTrie.(*Trie)
} }
func newTestPrefixTrie() *Trie { func newTestPrefixTrie() *Trie {
memDB := dbm.NewMemDB() testDB := newTestDatabase()
testDB, _ := NewDatabase(memDB, memDB)
prefix := make([]byte, ethcmn.HashLength) prefix := make([]byte, ethcmn.HashLength)
rand.Read(prefix) rand.Read(prefix)

View File

@ -19,6 +19,7 @@ var (
cpuprofile = flag.String("cpu-profile", "", "write cpu profile `file`") cpuprofile = flag.String("cpu-profile", "", "write cpu profile `file`")
blockchain = flag.String("blockchain", "data/blockchain", "file containing blocks to load") blockchain = flag.String("blockchain", "data/blockchain", "file containing blocks to load")
datadir = flag.String("datadir", path.Join(os.Getenv("HOME"), ".ethermint"), "directory for ethermint data") datadir = flag.String("datadir", path.Join(os.Getenv("HOME"), ".ethermint"), "directory for ethermint data")
cachesize = flag.Int("cachesize", 1024*1024, "number of key-value pairs for the state stored in memory")
) )
func main() { func main() {
@ -51,7 +52,7 @@ func main() {
stateDB := dbm.NewDB("state", dbm.LevelDBBackend, *datadir) stateDB := dbm.NewDB("state", dbm.LevelDBBackend, *datadir)
codeDB := dbm.NewDB("code", dbm.LevelDBBackend, *datadir) codeDB := dbm.NewDB("code", dbm.LevelDBBackend, *datadir)
ethermintDB, err := state.NewDatabase(stateDB, codeDB) ethermintDB, err := state.NewDatabase(stateDB, codeDB, *cachesize)
if err != nil { if err != nil {
panic(fmt.Sprintf("failed to initialize geth Database: %v", err)) panic(fmt.Sprintf("failed to initialize geth Database: %v", err))
} }