aboutsummaryrefslogtreecommitdiffstats
path: root/core
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 /core
parentcbb7cc20f824fd96279a0c14eb5d0a2187347955 (diff)
downloadgo-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar
go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar.gz
go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar.bz2
go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar.lz
go-tangerine-070647ec674c96582ebe93dadeefe017964c0488.tar.xz
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
Diffstat (limited to 'core')
-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
4 files changed, 63 insertions, 32 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