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

Allow EVM state to be flushed to disk every Nth block instead of every block #1532

Merged
merged 89 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
097dc40
experiment
pathornteng Oct 9, 2019
ea8a66b
fix unit tests
pathornteng Oct 9, 2019
de298e0
only save committed evmroot
pathornteng Oct 9, 2019
5fda6e4
allow flush interval for evm state to be configured in loom.yaml
pathornteng Oct 9, 2019
8c04bfc
fix unit test
pathornteng Oct 9, 2019
9180eb1
fix unit test
pathornteng Oct 9, 2019
4193068
save default root to evm.db
pathornteng Oct 9, 2019
a4863cf
address PR comment
pathornteng Oct 9, 2019
2af31ad
move EVMStateDB from readonlystate to state
pathornteng Oct 9, 2019
28376ff
refactor
pathornteng Oct 11, 2019
393c94e
clean up
pathornteng Oct 11, 2019
15a2264
update tg test
pathornteng Oct 11, 2019
0ca6a89
revert change
pathornteng Oct 11, 2019
7f92b44
only save default root once
pathornteng Oct 17, 2019
749052c
remove legacy evm dump commands and clean up
pathornteng Oct 17, 2019
fc265e7
Merge branch 'master' into in-memory-evmstate
pathornteng Oct 17, 2019
88aafca
fix unit tests
pathornteng Oct 17, 2019
8853c38
fix a unit test
pathornteng Oct 17, 2019
2861d52
add evmstore to pluginvm
pathornteng Oct 17, 2019
ccc4ffd
merge master
pathornteng Oct 18, 2019
8198833
simplify test
pathornteng Oct 18, 2019
56cfef7
Merge branch 'master' into in-memory-evmstate
pathornteng Oct 22, 2019
8a6be85
merge master
pathornteng Oct 30, 2019
1b7540c
simplify commit EVM root logic
pathornteng Nov 1, 2019
0b70a21
address PR comment
pathornteng Nov 4, 2019
3bfac5b
fix unit test
pathornteng Nov 4, 2019
e6ab7ca
address PR comment
pathornteng Nov 6, 2019
89f3fff
commit evm state in application commit
pathornteng Nov 7, 2019
b422604
refactor
pathornteng Nov 7, 2019
c03f7fa
revert tg branch
pathornteng Nov 7, 2019
5e3a4ab
fix unit test
pathornteng Nov 7, 2019
95f91e1
fix broken tests
pathornteng Nov 7, 2019
2e268ef
add dposv2-genesis
pathornteng Nov 8, 2019
82c887d
reset logs after each tx
pathornteng Nov 8, 2019
51c7eeb
remove unused code
pathornteng Nov 8, 2019
792072e
reset state after commit
pathornteng Nov 11, 2019
1dc0463
merge master
pathornteng Nov 18, 2019
24de625
commit state every tx
pathornteng Nov 21, 2019
fca3e54
fix condition
pathornteng Nov 21, 2019
8cf511c
Merge branch 'master' into in-memory-evmstate
pathornteng Nov 21, 2019
dd7f2d0
address PR comment
pathornteng Nov 22, 2019
1ec9fa0
address PR comment
pathornteng Nov 22, 2019
8bb11f0
use clone version of evm state for checktx
pathornteng Nov 22, 2019
6e87a27
merge master
pathornteng Nov 22, 2019
00475d4
finalise state after each tx
pathornteng Nov 23, 2019
43068fe
finalize state if tx succeeds
pathornteng Nov 23, 2019
cbebc15
revert finalise
pathornteng Nov 23, 2019
e47e0ce
revert snapshot if tx fails
pathornteng Nov 24, 2019
5abbc76
address PR comment
pathornteng Nov 25, 2019
3d6d1c8
copying state instead of reverting
pathornteng Nov 25, 2019
c4679f3
address PR comments
pathornteng Nov 25, 2019
bb65d19
fix unit tests
pathornteng Nov 25, 2019
ed9b1bb
fix truffle test
pathornteng Nov 26, 2019
9f8b531
address PR comments
pathornteng Nov 28, 2019
5603a9d
merge master
pathornteng Nov 28, 2019
7c64432
commit missing file
pathornteng Nov 28, 2019
cc2b16c
fix linter error
pathornteng Nov 28, 2019
388b818
address PR comment
pathornteng Dec 2, 2019
e022db9
Simplify
enlight Dec 2, 2019
e2c471a
Tweaks
enlight Dec 2, 2019
b4a243e
make evmstore thread-safe by removing its cache
pathornteng Dec 2, 2019
5c51fc6
fix unit test
pathornteng Dec 2, 2019
e7d93a1
add snapshot truffle test
pathornteng Dec 2, 2019
8576560
use level db batch in ethdb
pathornteng Dec 3, 2019
16cca33
use cache for logbatch
pathornteng Dec 3, 2019
ea2d726
fix wrong import repo
pathornteng Dec 3, 2019
eeeab35
address PR comments
pathornteng Dec 3, 2019
ed6c72d
Remove LoomEthDB.logContext
enlight Dec 3, 2019
b259464
Tweak the LoomEthDB batch a little bit
enlight Dec 3, 2019
548e35c
Increase delay before mapping accounts on Linux
enlight Dec 4, 2019
b53718b
Revert irrelevant changes
enlight Dec 4, 2019
9fe103f
Cleanup LogBatch and remove unused sortKeys func
enlight Dec 4, 2019
4952caa
Add a few comments
enlight Dec 4, 2019
7b0a764
Bump default number of cached EVM state roots to 500
enlight Dec 4, 2019
d6702e7
Don't reuse the cachingDB instance between EVMState instances
enlight Dec 4, 2019
d818dd9
Eliminate PruningIAVLStore
enlight Dec 4, 2019
d4824ff
Ensure that EVM & app state are in sync in Application.ReadOnlyState()
enlight Dec 4, 2019
7335869
Remove bogus implementation of MockStore.GetSnapshotAt
enlight Dec 6, 2019
c65d47f
Verify state roots in EVMState.GetSnapshot()
enlight Dec 6, 2019
6ecf12f
Remove unused Application.EvmStore field
enlight Dec 6, 2019
23f109e
Revert some modifications to the MultiWriterAppStore tests
enlight Dec 6, 2019
45224fc
Hack VersionedCachingStore to get the e2e tests passing
enlight Dec 9, 2019
e996c14
Check that EVMState isn't nil in Application.Commit()
enlight Dec 9, 2019
8b8a3cb
Check that EVMState isn't nil in Application.CheckTx()
enlight Dec 9, 2019
b41cb2a
address PR comments and make evm state snapshot panic if it calls Com…
pathornteng Dec 11, 2019
ad002bb
Add EvmStore.FlushInterval setting to loom.yml
enlight Dec 11, 2019
b1d871b
Switch back to go-ethereum/loomchain branch
enlight Dec 17, 2019
412d987
Add back a lost comment
enlight Dec 17, 2019
c69f3c2
Merge branch 'master' into in-memory-evmstate
enlight Jan 28, 2020
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
13 changes: 7 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ GO_LOOM_GIT_REV = HEAD
# Specifies the loomnetwork/transfer-gateway branch/revision to use.
TG_GIT_REV = HEAD
# loomnetwork/go-ethereum loomchain branch
ETHEREUM_GIT_REV = 1fb6138d017a4309105d91f187c126cf979c93f9
ETHEREUM_GIT_REV = in-memory-statedb
# use go-plugin we get 'timeout waiting for connection info' error
HASHICORP_GIT_REV = f4c3476bd38585f9ec669d10ed1686abd52b9961
LEVIGO_GIT_REV = c42d9e0ca023e2198120196f842701bb4c55d7b9
Expand Down Expand Up @@ -197,14 +197,15 @@ $(BINANCE_TGORACLE_DIR):
git clone -q git@github.com:loomnetwork/binance-tgoracle.git $@
cd $(BINANCE_TGORACLE_DIR) && git checkout master && git pull && git checkout $(BINANCE_TG_GIT_REV)

validators-tool: $(TRANSFER_GATEWAY_DIR)
go build -tags gateway -o e2e/validators-tool $(PKG)/e2e/cmd

deps: $(PLUGIN_DIR) $(GO_ETHEREUM_DIR) $(SSHA3_DIR)
# Temp workaround for https://github.com/prometheus/procfs/issues/221
$(PROMETHEUS_PROCFS_DIR):
git clone -q git@github.com:prometheus/procfs $(PROMETHEUS_PROCFS_DIR)
cd $(PROMETHEUS_PROCFS_DIR) && git checkout master && git pull && git checkout d3b299e382e6acf1baa852560d862eca4ff643c8

validators-tool: $(TRANSFER_GATEWAY_DIR)
go build -tags gateway -o e2e/validators-tool $(PKG)/e2e/cmd

deps: $(PLUGIN_DIR) $(GO_ETHEREUM_DIR) $(SSHA3_DIR) $(PROMETHEUS_PROCFS_DIR)

go get \
golang.org/x/crypto/ed25519 \
google.golang.org/grpc \
Expand Down
80 changes: 72 additions & 8 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"time"

gcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/trie"
"github.com/loomnetwork/go-loom/config"
"github.com/loomnetwork/go-loom/util"
"github.com/loomnetwork/loomchain/eth/utils"
Expand Down Expand Up @@ -39,6 +41,7 @@ type ReadOnlyState interface {
Config() *cctypes.Config
EnabledFeatures() []string
GetMinBuildNumber() uint64
GetTrieDB() *trie.Database
pathornteng marked this conversation as resolved.
Show resolved Hide resolved
}

type State interface {
Expand All @@ -59,6 +62,7 @@ type StoreState struct {
validators loom.ValidatorSet
getValidatorSet GetValidatorSet
config *cctypes.Config
trieDB *trie.Database
}

var _ = State(&StoreState{})
Expand Down Expand Up @@ -100,6 +104,11 @@ func (s *StoreState) WithOnChainConfig(config *cctypes.Config) *StoreState {
return s
}

func (s *StoreState) WithTrieDB(trieDB *trie.Database) *StoreState {
s.trieDB = trieDB
return s
}

func (s *StoreState) Range(prefix []byte) plugin.RangeData {
return s.store.Range(prefix)
}
Expand Down Expand Up @@ -140,15 +149,32 @@ func (s *StoreState) Context() context.Context {
return s.ctx
}

func (s *StoreState) GetTrieDB() *trie.Database {
return s.trieDB
}

const (
featurePrefix = "feature"
MinBuildKey = "minbuild"
)

var (
vmPrefix = []byte("vm")
rootKey = []byte("vmroot")
// This is the prefix of versioning Patricia roots
evmRootPrefix = []byte("evmroot")
)

func featureKey(featureName string) []byte {
return util.PrefixKey([]byte(featurePrefix), []byte(featureName))
}

func evmRootKey(blockHeight int64) []byte {
b := make([]byte, 8)
binary.BigEndian.PutUint64(b, uint64(blockHeight))
return util.PrefixKey(vmPrefix, []byte(evmRootPrefix), b)
}

func (s *StoreState) EnabledFeatures() []string {
featuresFromState := s.Range([]byte(featurePrefix))
enabledFeatures := make([]string, 0, len(featuresFromState))
Expand Down Expand Up @@ -233,6 +259,7 @@ func (s *StoreState) WithContext(ctx context.Context) State {
ctx: ctx,
validators: s.validators,
getValidatorSet: s.getValidatorSet,
trieDB: s.trieDB,
}
}

Expand All @@ -243,6 +270,7 @@ func (s *StoreState) WithPrefix(prefix []byte) State {
ctx: s.ctx,
validators: s.validators,
getValidatorSet: s.getValidatorSet,
trieDB: s.trieDB,
}
}

Expand Down Expand Up @@ -362,6 +390,9 @@ type Application struct {
config *cctypes.Config
childTxRefs []evmaux.ChildTxRef // links Tendermint txs to EVM txs
ReceiptsVersion int32
TrieDB *trie.Database
FlushInterval int64 // commit Patricia trie to disk every N blocks
lastSavedEVMRoot []byte
}

var _ abci.Application = &Application{}
Expand Down Expand Up @@ -505,7 +536,7 @@ func (a *Application) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginB
a.curBlockHeader,
a.curBlockHash,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)
contractUpkeepHandler, err := a.CreateContractUpkeepHandler(upkeepState)
if err != nil {
panic(err)
Expand All @@ -525,7 +556,7 @@ func (a *Application) BeginBlock(req abci.RequestBeginBlock) abci.ResponseBeginB
a.curBlockHeader,
nil,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)

validatorManager, err := a.CreateValidatorManager(state)
if err != registry.ErrNotFound {
Expand Down Expand Up @@ -593,7 +624,7 @@ func (a *Application) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock {
a.curBlockHeader,
nil,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)

validatorManager, err := a.CreateValidatorManager(state)
if err != registry.ErrNotFound {
Expand Down Expand Up @@ -648,7 +679,7 @@ func (a *Application) CheckTx(txBytes []byte) abci.ResponseCheckTx {
a.curBlockHeader,
a.curBlockHash,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)

// Receipts & events generated in CheckTx must be discarded since the app state changes they
// reflect aren't persisted.
Expand Down Expand Up @@ -685,7 +716,7 @@ func (a *Application) DeliverTx(txBytes []byte) abci.ResponseDeliverTx {
a.curBlockHeader,
a.curBlockHash,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)

var r abci.ResponseDeliverTx

Expand Down Expand Up @@ -718,7 +749,7 @@ func (a *Application) processTx(storeTx store.KVStoreTx, txBytes []byte, isCheck
a.curBlockHeader,
a.curBlockHash,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)

receiptHandler := a.ReceiptHandlerProvider.Store()
defer receiptHandler.DiscardCurrentReceipt()
Expand Down Expand Up @@ -771,7 +802,7 @@ func (a *Application) deliverTx2(storeTx store.KVStoreTx, txBytes []byte) abci.R
a.curBlockHeader,
a.curBlockHash,
a.GetValidatorSet,
).WithOnChainConfig(a.config)
).WithOnChainConfig(a.config).WithTrieDB(a.TrieDB)

receiptHandler := a.ReceiptHandlerProvider.Store()
defer receiptHandler.DiscardCurrentReceipt()
Expand Down Expand Up @@ -829,6 +860,39 @@ func (a *Application) Commit() abci.ResponseCommit {
committedBlockCount.With(lvs...).Add(1)
commitBlockLatency.With(lvs...).Observe(time.Since(begin).Seconds())
}(time.Now())

state := NewStoreState(
context.Background(),
a.Store,
a.curBlockHeader,
a.curBlockHash,
a.GetValidatorSet,
)
curHeight := a.curBlockHeader.GetHeight()

flushInterval := a.FlushInterval
if flushInterval == 0 {
cfg := state.Config()
flushInterval = int64(cfg.GetAppStore().GetIAVLFlushInterval())
} else if flushInterval == -1 {
flushInterval = 0
}

// Only commit Patricia tree every N blocks
pathornteng marked this conversation as resolved.
Show resolved Hide resolved
if flushInterval == 0 || curHeight%flushInterval == 0 {
evmRoot := state.Get(util.PrefixKey(vmPrefix, rootKey))
if len(evmRoot) > 0 && bytes.Compare(a.lastSavedEVMRoot, evmRoot) != 0 {
ethDB := store.NewLoomEthDB(state, nil)
a.TrieDB.SetDiskDB(ethDB)
if err := a.TrieDB.Commit(gcommon.BytesToHash(evmRoot), false); err != nil {
panic(err)
}
a.lastSavedEVMRoot = evmRoot
a.TrieDB = trie.NewDatabase(ethDB)
a.Store.Set(evmRootKey(curHeight), evmRoot)
}
}

appHash, _, err := a.Store.SaveVersion()
if err != nil {
panic(err)
Expand Down Expand Up @@ -893,5 +957,5 @@ func (a *Application) ReadOnlyState() State {
a.lastBlockHeader,
nil, // TODO: last block hash!
a.GetValidatorSet,
)
).WithTrieDB(a.TrieDB)
}
2 changes: 1 addition & 1 deletion cmd/loom/db/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func newDumpEVMStateFromEvmDB() *cobra.Command {
nil,
)

srcStateDB := gstate.NewDatabase(evm.NewLoomEthdb(state, nil))
srcStateDB := gstate.NewDatabase(store.NewLoomEthDB(state, nil))
srcStateDBTrie, err := srcStateDB.OpenTrie(evmRoot)
if err != nil {
fmt.Printf("cannot open trie, %s\n", evmRoot.Hex())
Expand Down
5 changes: 4 additions & 1 deletion cmd/loom/loom.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/prometheus/client_golang/prometheus/push"
"github.com/tendermint/tendermint/libs/db"

"github.com/ethereum/go-ethereum/trie"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
"github.com/gogo/protobuf/proto"
"github.com/loomnetwork/go-loom"
Expand Down Expand Up @@ -836,7 +837,7 @@ func loadApp(
return evm.NewLoomVm(state, eventHandler, receiptHandlerProvider.Writer(), createABM, cfg.EVMDebugEnabled), nil
})
}
evm.LogEthDbBatch = cfg.LogEthDbBatch
store.LogEthDBBatch = cfg.LogEthDbBatch

deployTxHandler := &vm.DeployTxHandler{
Manager: vmManager,
Expand Down Expand Up @@ -1126,6 +1127,8 @@ func loadApp(
GetValidatorSet: getValidatorSet,
EvmAuxStore: evmAuxStore,
ReceiptsVersion: cfg.ReceiptsVersion,
TrieDB: trie.NewDatabase(nil),
FlushInterval: cfg.AppStore.IAVLFlushInterval,
}, nil
}

Expand Down
6 changes: 5 additions & 1 deletion evm/evm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"testing"
"time"

"github.com/ethereum/go-ethereum/trie"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
ethvm "github.com/ethereum/go-ethereum/core/vm"
Expand Down Expand Up @@ -40,7 +42,9 @@ func mockState() loomchain.State {
header := abci.Header{}
header.Height = BlockHeight
header.Time = blockTime
return loomchain.NewStoreState(context.Background(), store.NewMemStore(), header, nil, nil)
memDB := store.NewMemStore()
trieDB := trie.NewDatabase(store.NewLoomEthDB(memDB, nil))
return loomchain.NewStoreState(context.Background(), memDB, header, nil, nil).WithTrieDB(trieDB)
}

func TestProcessDeployTx(t *testing.T) {
Expand Down
38 changes: 15 additions & 23 deletions evm/loomevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/loomnetwork/loomchain/features"
"github.com/loomnetwork/loomchain/receipts"
"github.com/loomnetwork/loomchain/receipts/handler"
"github.com/loomnetwork/loomchain/store"
"github.com/loomnetwork/loomchain/vm"
"github.com/pkg/errors"
)
Expand All @@ -38,12 +39,6 @@ type StateDB interface {
Commit(bool) (common.Hash, error)
}

type ethdbLogContext struct {
blockHeight int64
contractAddr loom.Address
callerAddr loom.Address
}

// TODO: this doesn't need to be exported, rename to loomEvmWithState
type LoomEvm struct {
*Evm
Expand All @@ -54,21 +49,26 @@ type LoomEvm struct {
// TODO: this doesn't need to be exported, rename to newLoomEvmWithState
func NewLoomEvm(
loomState loomchain.State, accountBalanceManager AccountBalanceManager,
logContext *ethdbLogContext, debug bool,
logContext *store.EthDBLogContext, debug bool,
) (*LoomEvm, error) {
p := new(LoomEvm)
p.db = NewLoomEthdb(loomState, logContext)
p.db = store.NewLoomEthDB(loomState, logContext)
oldRoot, err := p.db.Get(rootKey)
if err != nil {
return nil, err
}

trieDB := loomState.GetTrieDB()
trieDB.SetDiskDB(p.db)
sdb := state.NewDatabase(p.db)
sdb.SetTrieDB(trieDB)

var abm *evmAccountBalanceManager
if accountBalanceManager != nil {
abm = newEVMAccountBalanceManager(accountBalanceManager, loomState.Block().ChainID)
p.sdb, err = newLoomStateDB(abm, common.BytesToHash(oldRoot), state.NewDatabase(p.db))
p.sdb, err = newLoomStateDB(abm, common.BytesToHash(oldRoot), sdb)
} else {
p.sdb, err = state.New(common.BytesToHash(oldRoot), state.NewDatabase(p.db))
p.sdb, err = state.New(common.BytesToHash(oldRoot), sdb)
}
if err != nil {
return nil, err
Expand All @@ -83,9 +83,9 @@ func (levm LoomEvm) Commit() (common.Hash, error) {
if err != nil {
return root, err
}
if err := levm.sdb.Database().TrieDB().Commit(root, false); err != nil {
return root, err
}
// if err := levm.sdb.Database().TrieDB().Commit(root, false); err != nil {
// return root, err
// }
if err := levm.db.Put(rootKey, root[:]); err != nil {
return root, err
}
Expand Down Expand Up @@ -146,11 +146,7 @@ func (lvm LoomVm) accountBalanceManager(readOnly bool) AccountBalanceManager {
}

func (lvm LoomVm) Create(caller loom.Address, code []byte, value *loom.BigUInt) ([]byte, loom.Address, error) {
logContext := &ethdbLogContext{
blockHeight: lvm.state.Block().Height,
contractAddr: loom.Address{},
callerAddr: caller,
}
logContext := store.NewEthDBLogContext(lvm.state.Block().Height, loom.Address{}, caller)
levm, err := NewLoomEvm(lvm.state, lvm.accountBalanceManager(false), logContext, lvm.debug)
if err != nil {
return nil, loom.Address{}, err
Expand Down Expand Up @@ -209,11 +205,7 @@ func (lvm LoomVm) Create(caller loom.Address, code []byte, value *loom.BigUInt)
}

func (lvm LoomVm) Call(caller, addr loom.Address, input []byte, value *loom.BigUInt) ([]byte, error) {
logContext := &ethdbLogContext{
blockHeight: lvm.state.Block().Height,
contractAddr: addr,
callerAddr: caller,
}
logContext := store.NewEthDBLogContext(lvm.state.Block().Height, addr, caller)
levm, err := NewLoomEvm(lvm.state, lvm.accountBalanceManager(false), logContext, lvm.debug)
if err != nil {
return nil, err
Expand Down
Loading