diff options
author | Wei-Ning Huang <aitjcize@gmail.com> | 2018-11-14 10:57:53 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-12 17:27:18 +0800 |
commit | 070647ec674c96582ebe93dadeefe017964c0488 (patch) | |
tree | cf14e337a1f306adc15ccafa4086f2745f8a4093 | |
parent | cbb7cc20f824fd96279a0c14eb5d0a2187347955 (diff) | |
download | go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar.gz go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar.zst go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.zip |
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
-rw-r--r-- | core/blockchain.go | 10 | ||||
-rw-r--r-- | core/evm.go | 50 | ||||
-rw-r--r-- | core/vm/evm.go | 11 | ||||
-rw-r--r-- | core/vm/governance.go | 24 | ||||
-rw-r--r-- | dex/governance.go | 6 | ||||
-rw-r--r-- | light/lightchain.go | 12 | ||||
-rw-r--r-- | params/config.go | 2 | ||||
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go | 15 | ||||
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go | 6 | ||||
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go | 4 | ||||
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go | 1 | ||||
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go | 11 | ||||
-rw-r--r-- | vendor/vendor.json | 34 |
13 files changed, 101 insertions, 85 deletions
diff --git a/core/blockchain.go b/core/blockchain.go index 3c9e9701d..3b71cb64b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2165,7 +2165,11 @@ func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscript return bc.scope.Track(bc.logsFeed.Subscribe(ch)) } -// GetRoundHeightMap returns the mapping between round and height. -func (bc *BlockChain) GetRoundHeightMap() sync.Map { - return bc.roundHeightMap +// GetRoundHeight returns the height of a given round. +func (bc *BlockChain) GetRoundHeight(round uint64) (uint64, bool) { + h, ok := bc.roundHeightMap.Load(round) + if !ok { + return 0, false + } + return h.(uint64), true } diff --git a/core/evm.go b/core/evm.go index 5e8cf9063..80b0eaa7a 100644 --- a/core/evm.go +++ b/core/evm.go @@ -18,11 +18,10 @@ package core import ( "math/big" - "reflect" - "sync" "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/consensus" + "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" "github.com/dexon-foundation/dexon/core/vm" ) @@ -36,8 +35,14 @@ type ChainContext interface { // GetHeader returns the hash corresponding to their hash. GetHeader(common.Hash, uint64) *types.Header - // GetRoundHeightMap returns the mapping between round and height. - GetRoundHeightMap() sync.Map + // StateAt returns the statedb given a root hash. + StateAt(common.Hash) (*state.StateDB, error) + + // GetHeaderByNumber returns the header given a block number. + GetHeaderByNumber(number uint64) *types.Header + + // GetRoundHeight returns the mapping between round and height. + GetRoundHeight(uint64) (uint64, bool) } // NewEVMContext creates a new context for use in the EVM. @@ -50,24 +55,29 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author beneficiary = *author } - var roundHeight sync.Map - if !reflect.ValueOf(chain).IsNil() { - roundHeight = chain.GetRoundHeightMap() + return vm.Context{ + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + StateAtNumber: StateAtNumberFn(chain), + GetRoundHeight: chain.GetRoundHeight, + Origin: msg.From(), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: new(big.Int).SetUint64(header.Time), + Randomness: header.Randomness, + Difficulty: new(big.Int).Set(header.Difficulty), + GasLimit: header.GasLimit, + GasPrice: new(big.Int).Set(msg.GasPrice()), } +} - return vm.Context{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHash: GetHashFn(header, chain), - Origin: msg.From(), - Coinbase: beneficiary, - BlockNumber: new(big.Int).Set(header.Number), - Time: new(big.Int).SetUint64(header.Time), - Randomness: header.Randomness, - Difficulty: new(big.Int).Set(header.Difficulty), - RoundHeight: roundHeight, - GasLimit: header.GasLimit, - GasPrice: new(big.Int).Set(msg.GasPrice()), +// StateAtNumberFn returns a StateAtNumberFunc which allows the retrieval of +// statedb at a given block height. +func StateAtNumberFn(chain ChainContext) func(n uint64) (*state.StateDB, error) { + return func(n uint64) (*state.StateDB, error) { + header := chain.GetHeaderByNumber(n) + return chain.StateAt(header.Root) } } 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 diff --git a/dex/governance.go b/dex/governance.go index 92a8789b3..0251d2afd 100644 --- a/dex/governance.go +++ b/dex/governance.go @@ -24,8 +24,6 @@ import ( "github.com/dexon-foundation/dexon/rpc" ) -const configActivationOffset = 2 - type DexconGovernance struct { b *DexAPIBackend chainConfig *params.ChainConfig @@ -68,10 +66,10 @@ func (d *DexconGovernance) getGovState() *vm.GovernanceStateHelper { } func (d *DexconGovernance) getGovStateAtRound(round uint64) *vm.GovernanceStateHelper { - if round < configActivationOffset { + if round < dexCore.ConfigRoundShift { round = 0 } else { - round -= configActivationOffset + round -= dexCore.ConfigRoundShift } ctx := context.Background() blockHeight, err := d.getRoundHeight(ctx, round) diff --git a/light/lightchain.go b/light/lightchain.go index 645f41ef0..f4a6b7a27 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -534,8 +534,12 @@ func (self *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEven return self.scope.Track(new(event.Feed).Subscribe(ch)) } -// GetRoundHeightMap returns the mapping between round and height. -func (self *LightChain) GetRoundHeightMap() sync.Map { - // TODO(w): fix this. - return sync.Map{} +// StateAt returns a new mutable state based on a particular point in time. +func (self *LightChain) StateAt(root common.Hash) (*state.StateDB, error) { + return nil, nil +} + +// GetRoundHeight returns the height of a given round. +func (self *LightChain) GetRoundHeight(round uint64) (uint64, bool) { + return 0, false } diff --git a/params/config.go b/params/config.go index 60180de90..d66ee5610 100644 --- a/params/config.go +++ b/params/config.go @@ -220,7 +220,7 @@ type dexconConfigSpecMarshaling struct { // String implements the stringer interface, returning the consensus engine details. func (d *DexconConfig) String() string { - return fmt.Sprintf("{GenesisCRSText: %v Owner: %v BlockReward: %v BlockGasLimit: %v NumChains: %v LambdaBA: %v LambdaDKG: %v K: %v PhiRatio: %v NotarySetSize: %v DKGSetSize: %v RoundInterval: %v MinBlockInterval: %v", + return fmt.Sprintf("{GenesisCRSText: %v Owner: %v BlockReward: %v BlockGasLimit: %v NumChains: %v LambdaBA: %v LambdaDKG: %v K: %v PhiRatio: %v NotarySetSize: %v DKGSetSize: %v RoundInterval: %v MinBlockInterval: %v}", d.GenesisCRSText, d.Owner, d.BlockReward, diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go index d12d30a6a..3d46c5c8b 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go @@ -315,11 +315,7 @@ func NewConsensus( logger common.Logger) *Consensus { // TODO(w): load latest blockHeight from DB, and use config at that height. - var ( - round uint64 - // round 0 and 1 are decided at beginning. - roundToNotify = round + 2 - ) + var round uint64 logger.Debug("Calling Governance.Configuration", "round", round) config := gov.Configuration(round) nodeSetCache := NewNodeSetCache(gov) @@ -366,7 +362,6 @@ func NewConsensus( authModule: authModule, event: common.NewEvent(), logger: logger, - roundToNotify: roundToNotify, } validLeader := func(block *types.Block) (bool, error) { @@ -416,9 +411,9 @@ func NewConsensus( // Run starts running DEXON Consensus. func (con *Consensus) Run(initBlock *types.Block) { - con.logger.Debug("Calling Governance.NotifyRoundHeight for genesis rounds", - "block", initBlock) - notifyGenesisRounds(initBlock, con.gov) + // The block past from full node should be delivered already or known by + // full node. We don't have to notify it. + con.roundToNotify = initBlock.Position.Round + 1 initRound := initBlock.Position.Round con.logger.Debug("Calling Governance.Configuration", "round", initRound) initConfig := con.gov.Configuration(initRound) @@ -1004,7 +999,7 @@ func (con *Consensus) preProcessBlock(b *types.Block) (err error) { func (con *Consensus) deliverBlock(b *types.Block) { con.logger.Debug("Calling Application.BlockDelivered", "block", b) con.app.BlockDelivered(b.Hash, b.Position, b.Finalization.Clone()) - if b.Position.Round+roundShift == con.roundToNotify { + if b.Position.Round == con.roundToNotify { // Only the first block delivered of that round would // trigger this noitification. con.logger.Debug("Calling Governance.NotifyRoundHeight", diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go index 9a61c0abb..563a321f5 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go @@ -17,9 +17,9 @@ package core -// round shift refers to the difference between block's round and config round -// derived from its state. +// ConfigRoundShift refers to the difference between block's round and config +// round derived from its state. // // For example, when round shift is 2, a block in round 0 should derive config // for round 2. -const roundShift uint64 = 2 +const ConfigRoundShift uint64 = 2 diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go index 3a9c0752a..e07476d44 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go @@ -111,8 +111,8 @@ type Governance interface { // Return the genesis node set if round == 0. NodeSet(round uint64) []crypto.PublicKey - // NotifyRoundHeight notifies governance contract to generate configuration - // for that round with the block on that consensus height. + // NotifyRoundHeight notifies governance contract the consensus height of + // the first block of the given round. NotifyRoundHeight(targetRound, consensusHeight uint64) //// DKG-related methods. diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go index dcb3368fd..108f2887b 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go @@ -282,7 +282,6 @@ func (l *Lattice) PurgeBlocks(blocks []*types.Block) error { func (l *Lattice) AppendConfig(round uint64, config *types.Config) (err error) { l.lock.Lock() defer l.lock.Unlock() - l.pool.resize(config.NumChains) if err = l.data.appendConfig(round, config); err != nil { return diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go index 9159be858..6b9ce634f 100644 --- a/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go @@ -159,14 +159,3 @@ func DiffUint64(a, b uint64) uint64 { } return b - a } - -// notifyGenesisRounds notifies governance to generate configs based on genesis -// state. -func notifyGenesisRounds(initBlock *types.Block, gov Governance) { - if initBlock.Position.Round != 0 || !initBlock.IsGenesis() { - return - } - for round := uint64(0); round < roundShift; round++ { - gov.NotifyRoundHeight(round, 0) - } -} diff --git a/vendor/vendor.json b/vendor/vendor.json index 83d579652..711396aec 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -105,50 +105,50 @@ { "checksumSHA1": "ev84RyegNbt2Pr/sK26LK9LoQNI=", "path": "github.com/dexon-foundation/dexon-consensus/common", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { - "checksumSHA1": "9HDUFD7awHgKX5BhFZQAqr5e8Mo=", + "checksumSHA1": "CDbhowufKnHipqNsFhQymXdlAyY=", "path": "github.com/dexon-foundation/dexon-consensus/core", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "vNsaBvsrXJF+W6K5DCLpgy1rUZY=", "path": "github.com/dexon-foundation/dexon-consensus/core/blockdb", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "tQSbYCu5P00lUhKsx3IbBZCuSLY=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "p2jOAulavUU2xyj018pYPHlj8XA=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/dkg", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "6Pf6caC8LTNCI7IflFmglKYnxYo=", "path": "github.com/dexon-foundation/dexon-consensus/core/crypto/ecdsa", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "Kzw8b6kQLSApzVHO2WvmxrBfixA=", "path": "github.com/dexon-foundation/dexon-consensus/core/types", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "ovChyW9OfDGnk/7CDAR+A5vJymc=", "path": "github.com/dexon-foundation/dexon-consensus/core/types/dkg", - "revision": "86838fe70789292de0851f82426e5241c0f0cc96", - "revisionTime": "2018-11-13T07:26:09Z" + "revision": "01642721a7768218e7f9a5be8f0829eb8ae7c7b1", + "revisionTime": "2018-11-13T08:28:24Z" }, { "checksumSHA1": "TAkwduKZqLyimyTPPWIllZWYFuE=", |