From 1a97dbb9b707291f0bf0348adc5ea446cee4c18e Mon Sep 17 00:00:00 2001 From: lizhefeng Date: Wed, 20 Mar 2019 19:02:23 -0700 Subject: [PATCH] Commit contract states in a deterministic way (#790) --- .../execution/evm/evmstatedbadapter.go | 44 ++++++++++++++++++- tools/executiontester/executiontester.go | 2 +- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/action/protocol/execution/evm/evmstatedbadapter.go b/action/protocol/execution/evm/evmstatedbadapter.go index 29c0417186..f889febe4f 100644 --- a/action/protocol/execution/evm/evmstatedbadapter.go +++ b/action/protocol/execution/evm/evmstatedbadapter.go @@ -8,8 +8,10 @@ package evm import ( "bytes" + "encoding/hex" "fmt" "math/big" + "sort" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -571,11 +573,24 @@ func (stateDB *StateDBAdapter) setContractState(addr hash.Hash160, key, value ha // CommitContracts commits contract code to db and update pending contract account changes to trie func (stateDB *StateDBAdapter) CommitContracts() error { - for addr, contract := range stateDB.cachedContract { + addrStrs := make([]string, 0) + for addr := range stateDB.cachedContract { + addrStrs = append(addrStrs, hex.EncodeToString(addr[:])) + } + sort.Strings(addrStrs) + + for _, addrStr := range addrStrs { + var addr hash.Hash160 + addrBytes, err := hex.DecodeString(addrStr) + if err != nil { + return errors.Wrap(err, "failed to decode address hash") + } + copy(addr[:], addrBytes) if _, ok := stateDB.suicided[addr]; ok { // no need to update a suicide account/contract continue } + contract := stateDB.cachedContract[addr] if err := contract.Commit(); err != nil { stateDB.logError(err) return errors.Wrap(err, "failed to commit contract") @@ -588,14 +603,39 @@ func (stateDB *StateDBAdapter) CommitContracts() error { } } // delete suicided accounts/contract + addrStrs = make([]string, 0) for addr := range stateDB.suicided { + addrStrs = append(addrStrs, hex.EncodeToString(addr[:])) + } + sort.Strings(addrStrs) + + for _, addrStr := range addrStrs { + var addr hash.Hash160 + addrBytes, err := hex.DecodeString(addrStr) + if err != nil { + return errors.Wrap(err, "failed to decode address hash") + } + copy(addr[:], addrBytes) if err := stateDB.sm.DelState(addr); err != nil { stateDB.logError(err) return errors.Wrapf(err, "failed to delete suicide account/contract %x", addr[:]) } } // write preimages to DB - for k, v := range stateDB.preimages { + addrStrs = make([]string, 0) + for addr := range stateDB.preimages { + addrStrs = append(addrStrs, hex.EncodeToString(addr[:])) + } + sort.Strings(addrStrs) + + for _, addrStr := range addrStrs { + var k common.Hash + addrBytes, err := hex.DecodeString(addrStr) + if err != nil { + return errors.Wrap(err, "failed to decode address hash") + } + copy(k[:], addrBytes) + v := stateDB.preimages[k] h := make([]byte, len(k)) copy(h, k[:]) stateDB.cb.Put(PreimageKVNameSpace, h, v, "failed to put hash %x preimage %x", k, v) diff --git a/tools/executiontester/executiontester.go b/tools/executiontester/executiontester.go index e15906ede5..de1557a14b 100644 --- a/tools/executiontester/executiontester.go +++ b/tools/executiontester/executiontester.go @@ -49,7 +49,7 @@ func main() { cfg.Plugins[config.GatewayPlugin] = true cfg.Chain.EnableAsyncIndexWrite = false cfg.Genesis.ActionGasLimit = 10000000 - cfg.Genesis.BlockInterval = 2 + cfg.Genesis.BlockInterval = 2 * time.Second itxsvr, err := itx.NewServer(cfg) if err != nil { log.L().Fatal("Failed to start itxServer.", zap.Error(err))