aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei-Ning Huang <aitjcize@gmail.com>2018-11-14 10:57:53 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-06-12 17:27:18 +0800
commit070647ec674c96582ebe93dadeefe017964c0488 (patch)
treecf14e337a1f306adc15ccafa4086f2745f8a4093
parentcbb7cc20f824fd96279a0c14eb5d0a2187347955 (diff)
downloadgo-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.go10
-rw-r--r--core/evm.go50
-rw-r--r--core/vm/evm.go11
-rw-r--r--core/vm/governance.go24
-rw-r--r--dex/governance.go6
-rw-r--r--light/lightchain.go12
-rw-r--r--params/config.go2
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/consensus.go15
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/constant.go6
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/interfaces.go4
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/lattice.go1
-rw-r--r--vendor/github.com/dexon-foundation/dexon-consensus/core/utils.go11
-rw-r--r--vendor/vendor.json34
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=",