aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm
diff options
context:
space:
mode:
authorWei-Ning Huang <w@byzantine-lab.io>2019-07-25 20:41:46 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-09-17 16:57:31 +0800
commit174f6bfcdf4e2c7fea3a071653908b477ad9a3b3 (patch)
tree7990bd656bd9cc7ef3014534ad2fee5163da3790 /core/vm
parenta9a85fa746c727063015d6e70881426ce8b3a3fb (diff)
downloadgo-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.tar
go-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.tar.gz
go-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.tar.bz2
go-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.tar.lz
go-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.tar.xz
go-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.tar.zst
go-tangerine-174f6bfcdf4e2c7fea3a071653908b477ad9a3b3.zip
core: add GovUtil to unify governance state related access
Add GovUtil so we could use the same logic in everywhere that requires access to governance state, such as configuration and CRS.
Diffstat (limited to 'core/vm')
-rw-r--r--core/vm/oracle.go2
-rw-r--r--core/vm/oracle_contracts.go102
-rw-r--r--core/vm/oracle_contracts_test.go4
-rw-r--r--core/vm/utils.go92
4 files changed, 137 insertions, 63 deletions
diff --git a/core/vm/oracle.go b/core/vm/oracle.go
index ee28343ae..8c8a3006c 100644
--- a/core/vm/oracle.go
+++ b/core/vm/oracle.go
@@ -45,7 +45,7 @@ type OracleContract interface {
var OracleContracts = map[common.Address]func() OracleContract{
GovernanceContractAddress: func() OracleContract {
return &GovernanceContract{
- coreDKGUtils: &defaultCoreDKGUtils{},
+ coreDKGUtil: &defaultCoreDKGUtil{},
}
},
RandomContractAddress: func() OracleContract {
diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go
index e850811ff..a2c7d7814 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -29,6 +29,7 @@ import (
"github.com/tangerine-network/go-tangerine/accounts/abi"
"github.com/tangerine-network/go-tangerine/common"
+ "github.com/tangerine-network/go-tangerine/core/state"
"github.com/tangerine-network/go-tangerine/core/types"
"github.com/tangerine-network/go-tangerine/crypto"
"github.com/tangerine-network/go-tangerine/params"
@@ -529,6 +530,16 @@ func (s *GovernanceState) QualifiedNodes() []*nodeInfo {
}
return nodes
}
+func (s *GovernanceState) FinedNodes() []*nodeInfo {
+ var nodes []*nodeInfo
+ for i := int64(0); i < int64(s.LenNodes().Uint64()); i++ {
+ node := s.Node(big.NewInt(i))
+ if node.Fined.Cmp(big.NewInt(0)) > 0 {
+ nodes = append(nodes, node)
+ }
+ }
+ return nodes
+}
// mapping(address => uint256) public nodesOffsetByAddress;
func (s *GovernanceState) NodesOffsetByAddress(addr common.Address) *big.Int {
@@ -1274,47 +1285,19 @@ func (s *GovernanceState) emitDKGReset(round *big.Int, blockHeight *big.Int) {
})
}
-func getRoundState(evm *EVM, round *big.Int) (*GovernanceState, error) {
- gs := &GovernanceState{evm.StateDB}
- height := gs.RoundHeight(round).Uint64()
- if round.Uint64() > dexCore.ConfigRoundShift {
- if height == 0 {
- return nil, errExecutionReverted
- }
- }
- statedb, err := evm.StateAtNumber(height)
- return &GovernanceState{statedb}, err
-}
-
-func getConfigState(evm *EVM, round *big.Int) (*GovernanceState, error) {
- configRound := big.NewInt(0)
- if round.Uint64() > dexCore.ConfigRoundShift {
- configRound = new(big.Int).Sub(round, big.NewInt(int64(dexCore.ConfigRoundShift)))
- }
- return getRoundState(evm, configRound)
-}
-
-type coreDKGUtils interface {
+type coreDKGUtil interface {
NewGroupPublicKey(*GovernanceState, *big.Int, int) (tsigVerifierIntf, error)
}
type tsigVerifierIntf interface {
VerifySignature(coreCommon.Hash, coreCrypto.Signature) bool
}
-// GovernanceContract represents the governance contract of DEXCON.
-type GovernanceContract struct {
- evm *EVM
- state GovernanceState
- contract *Contract
- coreDKGUtils coreDKGUtils
-}
-
-// defaultCoreDKGUtils implements coreDKGUtils.
-type defaultCoreDKGUtils struct {
+// defaultCoreDKGUtil implements coreDKGUtil.
+type defaultCoreDKGUtil struct {
gpk atomic.Value
}
-func (c *defaultCoreDKGUtils) NewGroupPublicKey(
+func (c *defaultCoreDKGUtil) NewGroupPublicKey(
state *GovernanceState, round *big.Int, threshold int) (tsigVerifierIntf, error) {
var gpk *dkgTypes.GroupPublicKey
var err error
@@ -1337,6 +1320,23 @@ func (c *defaultCoreDKGUtils) NewGroupPublicKey(
return gpk, nil
}
+// GovernanceContract represents the governance contract of DEXCON.
+type GovernanceContract struct {
+ evm *EVM
+ state GovernanceState
+ contract *Contract
+ coreDKGUtil coreDKGUtil
+ util GovUtil
+}
+
+func (g *GovernanceContract) StateAt(height uint64) (*state.StateDB, error) {
+ return g.evm.StateAtNumber(height)
+}
+
+func (g *GovernanceContract) GetHeadGovState() (*GovernanceState, error) {
+ return &g.state, nil
+}
+
func (g *GovernanceContract) Address() common.Address {
return GovernanceContractAddress
}
@@ -1358,7 +1358,7 @@ func (g *GovernanceContract) useGas(gas uint64) ([]byte, error) {
}
func (g *GovernanceContract) configNotarySetSize(round *big.Int) *big.Int {
- s, err := getConfigState(g.evm, round)
+ s, err := g.util.GetConfigState(round.Uint64())
if err != nil {
return big.NewInt(0)
}
@@ -1366,34 +1366,15 @@ func (g *GovernanceContract) configNotarySetSize(round *big.Int) *big.Int {
}
func (g *GovernanceContract) getNotarySet(round *big.Int) map[coreTypes.NodeID]struct{} {
- crsRound := g.state.CRSRound()
- var crs common.Hash
- cmp := round.Cmp(crsRound)
- if round.Cmp(big.NewInt(int64(dexCore.DKGDelayRound))) <= 0 {
- state, err := getRoundState(g.evm, big.NewInt(0))
- if err != nil {
- return map[coreTypes.NodeID]struct{}{}
- }
- crs = state.CRS()
- for i := uint64(0); i < round.Uint64(); i++ {
- crs = crypto.Keccak256Hash(crs[:])
- }
- } else if cmp > 0 {
+ crs := g.util.CRS(round.Uint64())
+ if crs == (common.Hash{}) {
return map[coreTypes.NodeID]struct{}{}
- } else if cmp == 0 {
- crs = g.state.CRS()
- } else {
- state, err := getRoundState(g.evm, round)
- if err != nil {
- return map[coreTypes.NodeID]struct{}{}
- }
- crs = state.CRS()
}
target := coreTypes.NewNotarySetTarget(coreCommon.Hash(crs))
ns := coreTypes.NewNodeSet()
- state, err := getConfigState(g.evm, round)
+ state, err := g.util.GetConfigState(round.Uint64())
if err != nil {
return map[coreTypes.NodeID]struct{}{}
}
@@ -2000,7 +1981,7 @@ func (g *GovernanceContract) proposeCRS(nextRound *big.Int, signedCRS []byte) ([
threshold := coreUtils.GetDKGThreshold(&coreTypes.Config{
NotarySetSize: uint32(g.state.NotarySetSize().Uint64())})
- dkgGPK, err := g.coreDKGUtils.NewGroupPublicKey(&g.state, nextRound, threshold)
+ dkgGPK, err := g.coreDKGUtil.NewGroupPublicKey(&g.state, nextRound, threshold)
if err != nil {
return nil, errExecutionReverted
}
@@ -2137,7 +2118,7 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
new(big.Int).Mul(big.NewInt(100), resetCount))
roundHeight := g.state.RoundHeight(round)
- gs, err := getConfigState(g.evm, round)
+ gs, err := g.util.GetConfigState(round.Uint64())
if err != nil {
return nil, err
}
@@ -2167,7 +2148,7 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
// If 2f + 1 of DKG set is finalized, check if DKG succeeded.
if g.state.DKGFinalizedsCount().Uint64() >= threshold {
- gpk, err := g.coreDKGUtils.NewGroupPublicKey(&g.state, nextRound, tsigThreshold)
+ gpk, err := g.coreDKGUtil.NewGroupPublicKey(&g.state, nextRound, tsigThreshold)
if gpk, ok := gpk.(*dkgTypes.GroupPublicKey); ok {
if len(gpk.QualifyNodeIDs) < coreUtils.GetDKGValidThreshold(&coreTypes.Config{
NotarySetSize: uint32(g.configNotarySetSize(nextRound).Uint64())}) {
@@ -2191,7 +2172,7 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
g.fineFailStopDKG(tsigThreshold)
// Update CRS.
- state, err := getRoundState(g.evm, round)
+ state, err := g.util.GetStateAtRound(round.Uint64())
if err != nil {
return nil, errExecutionReverted
}
@@ -2208,7 +2189,7 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
prevCRS = crypto.Keccak256Hash(prevCRS[:])
}
- dkgGPK, err := g.coreDKGUtils.NewGroupPublicKey(state, round,
+ dkgGPK, err := g.coreDKGUtil.NewGroupPublicKey(state, round,
coreUtils.GetDKGThreshold(&coreTypes.Config{
NotarySetSize: uint32(g.configNotarySetSize(round).Uint64())}))
if err != nil {
@@ -2251,6 +2232,7 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
g.evm = evm
g.state = GovernanceState{evm.StateDB}
g.contract = contract
+ g.util = GovUtil{g}
// Parse input.
method, exists := GovernanceABI.Sig2Method[string(input[:4])]
diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go
index ef6b9bde8..f0b045ac8 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/oracle_contracts_test.go
@@ -237,7 +237,7 @@ func (g *GovernanceContractTestSuite) SetupTest() {
func (g *GovernanceContractTestSuite) TearDownTest() {
OracleContracts[GovernanceContractAddress] = func() OracleContract {
return &GovernanceContract{
- coreDKGUtils: &defaultCoreDKGUtils{},
+ coreDKGUtil: &defaultCoreDKGUtil{},
}
}
}
@@ -1176,7 +1176,7 @@ func (g *GovernanceContractTestSuite) TestResetDKG() {
}
OracleContracts[GovernanceContractAddress] = func() OracleContract {
return &GovernanceContract{
- coreDKGUtils: mock,
+ coreDKGUtil: mock,
}
}
diff --git a/core/vm/utils.go b/core/vm/utils.go
new file mode 100644
index 000000000..0cc6343cc
--- /dev/null
+++ b/core/vm/utils.go
@@ -0,0 +1,92 @@
+package vm
+
+import (
+ "errors"
+ "math/big"
+
+ "github.com/tangerine-network/go-tangerine/common"
+ "github.com/tangerine-network/go-tangerine/core/state"
+ "github.com/tangerine-network/go-tangerine/crypto"
+ "github.com/tangerine-network/go-tangerine/log"
+ dexCore "github.com/tangerine-network/tangerine-consensus/core"
+)
+
+type GovUtilInterface interface {
+ GetHeadGovState() (*GovernanceState, error)
+ StateAt(height uint64) (*state.StateDB, error)
+}
+
+type GovUtil struct {
+ Intf GovUtilInterface
+}
+
+func (g GovUtil) GetRoundHeight(round uint64) uint64 {
+ gs, err := g.Intf.GetHeadGovState()
+ if err != nil {
+ return 0
+ }
+ return gs.RoundHeight(big.NewInt(int64(round))).Uint64()
+}
+
+func (g GovUtil) GetStateAtRound(round uint64) (*GovernanceState, error) {
+ height := g.GetRoundHeight(round)
+
+ if round != 0 && height == 0 {
+ log.Error("Governance state incorrect", "round", round, "got height", height)
+ return nil, errors.New("incorrect governance state")
+ }
+
+ s, err := g.Intf.StateAt(height)
+ if err != nil {
+ return nil, err
+ }
+ return &GovernanceState{StateDB: s}, nil
+}
+
+func (g GovUtil) GetConfigState(round uint64) (*GovernanceState, error) {
+ if round < dexCore.ConfigRoundShift {
+ round = 0
+ } else {
+ round -= dexCore.ConfigRoundShift
+ }
+ return g.GetStateAtRound(round)
+}
+
+func (g *GovUtil) CRSRound() uint64 {
+ gs, err := g.Intf.GetHeadGovState()
+ if err != nil {
+ return 0
+ }
+ return gs.CRSRound().Uint64()
+}
+
+func (g GovUtil) CRS(round uint64) common.Hash {
+ if round <= dexCore.DKGDelayRound {
+ s, err := g.GetStateAtRound(0)
+ if err != nil {
+ return common.Hash{}
+ }
+ crs := s.CRS()
+ for i := uint64(0); i < round; i++ {
+ crs = crypto.Keccak256Hash(crs[:])
+ }
+ return crs
+ }
+ if round > g.CRSRound() {
+ return common.Hash{}
+ }
+ var s *GovernanceState
+ var err error
+ if round == g.CRSRound() {
+ s, err = g.Intf.GetHeadGovState()
+ if err != nil {
+ return common.Hash{}
+ }
+ } else {
+ s, err = g.GetStateAtRound(round)
+ if err != nil {
+ return common.Hash{}
+ }
+ }
+ return s.CRS()
+}