From 58490067c97e072678540ba5a5fcb7c34b09e04a Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Wed, 14 Nov 2018 10:57:53 +0800 Subject: core: validate DKG set with correct nodeset in round-2 (#19) * vendor: sync consensus core * core: validate DKG set with correct nodeset in round-2 --- core/vm/evm.go | 11 +++++++++-- core/vm/governance.go | 24 +++++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) (limited to 'core/vm') diff --git a/core/vm/evm.go b/core/vm/evm.go index a75d0f1d3..865ab0d5b 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -18,11 +18,11 @@ package vm import ( "math/big" - "sync" "sync/atomic" "time" "github.com/dexon-foundation/dexon/common" + "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/params" ) @@ -39,6 +39,10 @@ type ( // GetHashFunc returns the nth block hash in the blockchain // and is used by the BLOCKHASH EVM op code. GetHashFunc func(uint64) common.Hash + // StateAtFunc returns the statedb given a root hash. + StateAtNumberFunc func(uint64) (*state.StateDB, error) + // GetRoundHeightFunc returns the round height. + GetRoundHeightFunc func(uint64) (uint64, bool) ) // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. @@ -81,6 +85,10 @@ type Context struct { Transfer TransferFunc // GetHash returns the hash corresponding to n GetHash GetHashFunc + // StateAtNumber returns the statedb given a root hash. + StateAtNumber StateAtNumberFunc + // GetRoundHeight returns the round height. + GetRoundHeight GetRoundHeightFunc // Message information Origin common.Address // Provides information for ORIGIN @@ -93,7 +101,6 @@ type Context struct { Time *big.Int // Provides information for TIME Randomness []byte // Provides information for RAND Difficulty *big.Int // Provides information for DIFFICULTY - RoundHeight sync.Map // Provides information of round height mapping. } // EVM is the Ethereum Virtual Machine base object and provides diff --git a/core/vm/governance.go b/core/vm/governance.go index 49141761f..b38733e1a 100644 --- a/core/vm/governance.go +++ b/core/vm/governance.go @@ -1467,11 +1467,22 @@ func (g *GovernanceContract) penalize() { g.contract.UseGas(g.contract.Gas) } -func (g *GovernanceContract) inDKGSet(nodeID coreTypes.NodeID) bool { +func (g *GovernanceContract) inDKGSet(round *big.Int, nodeID coreTypes.NodeID) bool { target := coreTypes.NewDKGSetTarget(coreCommon.Hash(g.state.CurrentCRS())) ns := coreTypes.NewNodeSet() - for _, x := range g.state.Nodes() { + configRound := big.NewInt(0) // If round < core.ConfigRoundShift, use 0. + if round.Uint64() >= core.ConfigRoundShift { + configRound = new(big.Int).Sub(round, big.NewInt(int64(core.ConfigRoundShift))) + } + + statedb, err := g.evm.Context.StateAtNumber(g.state.RoundHeight(configRound).Uint64()) + if err != nil { + panic(err) + } + + state := GovernanceStateHelper{statedb} + for _, x := range state.Nodes() { mpk, err := ecdsa.NewPublicKeyFromByteSlice(x.PublicKey) if err != nil { panic(err) @@ -1515,7 +1526,7 @@ func (g *GovernanceContract) addDKGComplaint(round *big.Int, comp []byte) ([]byt } // DKGComplaint must belongs to someone in DKG set. - if !g.inDKGSet(dkgComplaint.ProposerID) { + if !g.inDKGSet(round, dkgComplaint.ProposerID) { g.penalize() return nil, errExecutionReverted } @@ -1555,7 +1566,7 @@ func (g *GovernanceContract) addDKGMasterPublicKey(round *big.Int, mpk []byte) ( } // DKGMasterPublicKey must belongs to someone in DKG set. - if !g.inDKGSet(dkgMasterPK.ProposerID) { + if !g.inDKGSet(round, dkgMasterPK.ProposerID) { g.penalize() return nil, errExecutionReverted } @@ -1588,7 +1599,7 @@ func (g *GovernanceContract) addDKGFinalize(round *big.Int, finalize []byte) ([] } // DKGFInalize must belongs to someone in DKG set. - if !g.inDKGSet(dkgFinalize.ProposerID) { + if !g.inDKGSet(round, dkgFinalize.ProposerID) { g.penalize() return nil, errExecutionReverted } @@ -1757,13 +1768,12 @@ func (g *GovernanceContract) transferOwnership(newOwner common.Address) ([]byte, func (g *GovernanceContract) snapshotRound(round, height *big.Int) ([]byte, error) { // Validate if this mapping is correct. - rawHeight, ok := g.evm.Context.RoundHeight.Load(round) + realHeight, ok := g.evm.Context.GetRoundHeight(round.Uint64()) if !ok { g.penalize() return nil, errExecutionReverted } - realHeight := rawHeight.(uint64) if height.Cmp(new(big.Int).SetUint64(realHeight)) != 0 { g.penalize() return nil, errExecutionReverted -- cgit v1.2.3