aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-04-15 18:19:46 +0800
committerGitHub <noreply@github.com>2019-04-15 18:19:46 +0800
commit4a8d6480f7ab074bc032d68df6ee8df5876ef3cc (patch)
tree54fdb27d6254ecc56f27b7819e9e554c2b1e9f63 /core
parentd77c1aa22cb6f2b76af3edf4995159b843838441 (diff)
downloaddexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.tar
dexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.tar.gz
dexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.tar.bz2
dexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.tar.lz
dexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.tar.xz
dexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.tar.zst
dexon-4a8d6480f7ab074bc032d68df6ee8df5876ef3cc.zip
core: implement DKG success (#362)
* vendor: sync to latest core * core: implmenet dkg success * cmd: govtool: add DKGSuccess
Diffstat (limited to 'core')
-rw-r--r--core/governance.go9
-rw-r--r--core/vm/oracle_contract_abi.go47
-rw-r--r--core/vm/oracle_contracts.go175
-rw-r--r--core/vm/oracle_contracts_test.go16
4 files changed, 215 insertions, 32 deletions
diff --git a/core/governance.go b/core/governance.go
index 39b2704e6..277b3bb89 100644
--- a/core/governance.go
+++ b/core/governance.go
@@ -310,6 +310,15 @@ func (g *Governance) IsDKGFinal(round uint64) bool {
return count >= threshold
}
+func (g *Governance) IsDKGSuccess(round uint64) bool {
+ s := g.GetStateForDKGAtRound(round)
+ if s == nil {
+ return false
+ }
+ return s.DKGSuccessesCount().Uint64() >=
+ uint64(coreUtils.GetDKGValidThreshold(g.Configuration(round)))
+}
+
func (g *Governance) MinGasPrice(round uint64) *big.Int {
return g.GetStateForConfigAtRound(round).MinGasPrice()
}
diff --git a/core/vm/oracle_contract_abi.go b/core/vm/oracle_contract_abi.go
index bd99c0cc7..dc44552a2 100644
--- a/core/vm/oracle_contract_abi.go
+++ b/core/vm/oracle_contract_abi.go
@@ -24,6 +24,25 @@ const GovernanceABIJSON = `
[
{
"constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "dkgSuccesses",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
"inputs": [],
"name": "notarySetSize",
"outputs": [
@@ -191,6 +210,20 @@ const GovernanceABIJSON = `
},
{
"constant": true,
+ "inputs": [],
+ "name": "dkgSuccessesCount",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
"inputs": [
{
"name": "",
@@ -1030,6 +1063,20 @@ const GovernanceABIJSON = `
"constant": false,
"inputs": [
{
+ "name": "Success",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGSuccess",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
"name": "PublicKey",
"type": "bytes"
},
diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go
index 4878fd325..b36a05d15 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -78,6 +78,8 @@ const (
dkgReadysCountLoc
dkgFinalizedLoc
dkgFinalizedsCountLoc
+ dkgSuccessLoc
+ dkgSuccessesCountLoc
ownerLoc
minStakeLoc
lockupPeriodLoc
@@ -766,6 +768,37 @@ func (s *GovernanceState) ResetDKGFinalizedsCount() {
s.setStateBigInt(big.NewInt(dkgFinalizedsCountLoc), big.NewInt(0))
}
+// mapping(address => bool) public dkgSuccesses;
+func (s *GovernanceState) DKGSuccess(addr common.Address) bool {
+ mapLoc := s.getMapLoc(big.NewInt(dkgSuccessLoc), addr.Bytes())
+ return s.getStateBigInt(mapLoc).Cmp(big.NewInt(0)) != 0
+}
+func (s *GovernanceState) PutDKGSuccess(addr common.Address, success bool) {
+ mapLoc := s.getMapLoc(big.NewInt(dkgSuccessLoc), addr.Bytes())
+ res := big.NewInt(0)
+ if success {
+ res = big.NewInt(1)
+ }
+ s.setStateBigInt(mapLoc, res)
+}
+func (s *GovernanceState) ClearDKGSuccesses(dkgSet map[coreTypes.NodeID]struct{}) {
+ for id := range dkgSet {
+ s.PutDKGSuccess(IdToAddress(id), false)
+ }
+}
+
+// uint256 public dkgSuccessesCount;
+func (s *GovernanceState) DKGSuccessesCount() *big.Int {
+ return s.getStateBigInt(big.NewInt(dkgSuccessesCountLoc))
+}
+func (s *GovernanceState) IncDKGSuccessesCount() {
+ s.setStateBigInt(big.NewInt(dkgSuccessesCountLoc),
+ new(big.Int).Add(s.getStateBigInt(big.NewInt(dkgSuccessesCountLoc)), big.NewInt(1)))
+}
+func (s *GovernanceState) ResetDKGSuccessesCount() {
+ s.setStateBigInt(big.NewInt(dkgSuccessesCountLoc), big.NewInt(0))
+}
+
// address public owner;
func (s *GovernanceState) Owner() common.Address {
val := s.getState(common.BigToHash(big.NewInt(ownerLoc)))
@@ -1357,6 +1390,8 @@ func (g *GovernanceContract) clearDKG() {
g.state.ResetDKGMPKReadysCount()
g.state.ClearDKGFinalizeds(dkgSet)
g.state.ResetDKGFinalizedsCount()
+ g.state.ClearDKGSuccesses(dkgSet)
+ g.state.ResetDKGSuccessesCount()
}
func (g *GovernanceContract) fineFailStopDKG(threshold int) {
@@ -1628,6 +1663,40 @@ func (g *GovernanceContract) addDKGFinalize(finalize []byte) ([]byte, error) {
return g.useGas(GovernanceActionGasCost)
}
+func (g *GovernanceContract) addDKGSuccess(success []byte) ([]byte, error) {
+ caller := g.contract.Caller()
+
+ var dkgSuccess dkgTypes.Success
+ if err := rlp.DecodeBytes(success, &dkgSuccess); err != nil {
+ return nil, errExecutionReverted
+ }
+ round := big.NewInt(int64(dkgSuccess.Round))
+ if round.Uint64() != g.evm.Round.Uint64()+1 {
+ return nil, errExecutionReverted
+ }
+
+ if dkgSuccess.Reset != g.state.DKGResetCount(round).Uint64() {
+ return nil, errExecutionReverted
+ }
+
+ // DKGFInalize must belongs to someone in DKG set.
+ if !g.inNotarySet(round, dkgSuccess.ProposerID) {
+ return nil, errExecutionReverted
+ }
+
+ verified, _ := coreUtils.VerifyDKGSuccessSignature(&dkgSuccess)
+ if !verified {
+ return nil, errExecutionReverted
+ }
+
+ if !g.state.DKGSuccess(caller) {
+ g.state.PutDKGSuccess(caller, true)
+ g.state.IncDKGSuccessesCount()
+ }
+
+ return g.useGas(GovernanceActionGasCost)
+}
+
func (g *GovernanceContract) updateConfiguration(cfg *rawConfigStruct) ([]byte, error) {
// Only owner can update configuration.
if g.contract.Caller() != g.state.Owner() {
@@ -1974,9 +2043,9 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
}
// Extend the the current round.
- // target = (80 + 100 * DKGResetCount)%
+ // target = (85 + 100 * DKGResetCount)%
target := new(big.Int).Add(
- big.NewInt(80),
+ big.NewInt(85),
new(big.Int).Mul(big.NewInt(100), resetCount))
roundHeight := g.state.RoundHeight(round)
@@ -1991,37 +2060,42 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
targetBlockNum.Quo(targetBlockNum, big.NewInt(100))
targetBlockNum.Add(targetBlockNum, roundHeight)
- // Check if current block over 80% of current round.
+ // Check if current block over 85%of current round.
blockHeight := g.evm.Context.BlockNumber
if blockHeight.Cmp(targetBlockNum) < 0 {
return nil, errExecutionReverted
}
- // Check if next DKG did not success.
- // Calculate 2f + 1
- threshold := 2*g.configNotarySetSize(g.evm.Round).Uint64()/3 + 1
tsigThreshold := coreUtils.GetDKGThreshold(&coreTypes.Config{
- NotarySetSize: uint32(g.configNotarySetSize(g.evm.Round).Uint64())})
-
- // 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)
- if gpk, ok := gpk.(*dkgTypes.GroupPublicKey); ok {
- nextRound := new(big.Int).Add(g.evm.Round, big.NewInt(1))
- if len(gpk.QualifyNodeIDs) < coreUtils.GetDKGValidThreshold(&coreTypes.Config{
- NotarySetSize: uint32(g.configNotarySetSize(nextRound).Uint64())}) {
- err = dkgTypes.ErrNotReachThreshold
+ NotarySetSize: uint32(g.configNotarySetSize(nextRound).Uint64())})
+ // Check if next DKG has not enough of success.
+ if g.state.DKGSuccessesCount().Uint64() >=
+ uint64(coreUtils.GetDKGValidThreshold(&coreTypes.Config{
+ NotarySetSize: uint32(g.configNotarySetSize(nextRound).Uint64()),
+ })) {
+ // Check if next DKG did not success.
+ // Calculate 2f + 1
+ threshold := 2*g.configNotarySetSize(nextRound).Uint64()/3 + 1
+
+ // 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)
+ if gpk, ok := gpk.(*dkgTypes.GroupPublicKey); ok {
+ if len(gpk.QualifyNodeIDs) < coreUtils.GetDKGValidThreshold(&coreTypes.Config{
+ NotarySetSize: uint32(g.configNotarySetSize(nextRound).Uint64())}) {
+ err = dkgTypes.ErrNotReachThreshold
+ }
}
- }
- // DKG success.
- if err == nil {
- return nil, errExecutionReverted
- }
- switch err {
- case dkgTypes.ErrNotReachThreshold, dkgTypes.ErrInvalidThreshold:
- default:
- return nil, errExecutionReverted
+ // DKG success.
+ if err == nil {
+ return nil, errExecutionReverted
+ }
+ switch err {
+ case dkgTypes.ErrNotReachThreshold, dkgTypes.ErrInvalidThreshold:
+ default:
+ return nil, errExecutionReverted
+ }
}
}
@@ -2046,7 +2120,9 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
prevCRS = crypto.Keccak256Hash(prevCRS[:])
}
- dkgGPK, err := g.coreDKGUtils.NewGroupPublicKey(state, round, tsigThreshold)
+ dkgGPK, err := g.coreDKGUtils.NewGroupPublicKey(state, round,
+ coreUtils.GetDKGThreshold(&coreTypes.Config{
+ NotarySetSize: uint32(g.configNotarySetSize(round).Uint64())}))
if err != nil {
return nil, errExecutionReverted
}
@@ -2058,19 +2134,17 @@ func (g *GovernanceContract) resetDKG(newSignedCRS []byte) ([]byte, error) {
return nil, errExecutionReverted
}
- newRound := new(big.Int).Add(g.evm.Round, big.NewInt(1))
-
// Clear DKG states for next round.
g.clearDKG()
- g.state.SetDKGRound(newRound)
+ g.state.SetDKGRound(nextRound)
// Save new CRS into state and increase round.
newCRS := crypto.Keccak256(newSignedCRS)
crs := common.BytesToHash(newCRS)
g.state.SetCRS(crs)
- g.state.SetCRSRound(newRound)
- g.state.emitCRSProposed(newRound, crs)
+ g.state.SetCRSRound(nextRound)
+ g.state.emitCRSProposed(nextRound, crs)
// Increase reset count.
g.state.IncDKGResetCount(nextRound)
@@ -2124,6 +2198,12 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return g.addDKGFinalize(Finalize)
+ case "addDKGSuccess":
+ var Success []byte
+ if err := method.Inputs.Unpack(&Success, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGSuccess(Success)
case "nodesLength":
res, err := method.Outputs.Pack(g.state.LenNodes())
if err != nil {
@@ -2266,6 +2346,24 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return res, nil
+ case "dkgSuccesses":
+ addr := common.Address{}
+ if err := method.Inputs.Unpack(&addr, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ finalized := g.state.DKGSuccess(addr)
+ res, err := method.Outputs.Pack(finalized)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
+ case "dkgSuccessesCount":
+ count := g.state.DKGSuccessesCount()
+ res, err := method.Outputs.Pack(count)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "dkgMasterPublicKeys":
offset := new(big.Int)
if err := method.Inputs.Unpack(&offset, arguments); err != nil {
@@ -2632,6 +2730,21 @@ func PackAddDKGFinalize(final *dkgTypes.Finalize) ([]byte, error) {
return data, nil
}
+func PackAddDKGSuccess(final *dkgTypes.Success) ([]byte, error) {
+ method := GovernanceABI.Name2Method["addDKGSuccess"]
+ encoded, err := rlp.EncodeToBytes(final)
+ if err != nil {
+ return nil, err
+ }
+
+ res, err := method.Inputs.Pack(encoded)
+ if err != nil {
+ return nil, err
+ }
+ data := append(method.Id(), res...)
+ return data, nil
+}
+
func PackReportForkVote(vote1, vote2 *coreTypes.Vote) ([]byte, error) {
method := GovernanceABI.Name2Method["report"]
diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go
index 269421717..4fb05a34e 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/oracle_contracts_test.go
@@ -985,6 +985,8 @@ func (g *OracleContractsTestSuite) TestResetDKG() {
g.s.ResetDKGMPKReadysCount()
g.s.ClearDKGFinalizeds(dkgSet)
g.s.ResetDKGFinalizedsCount()
+ g.s.ClearDKGSuccesses(dkgSet)
+ g.s.ResetDKGSuccessesCount()
g.s.SetDKGRound(big.NewInt(int64(round)))
}
@@ -1034,6 +1036,9 @@ func (g *OracleContractsTestSuite) TestResetDKG() {
// Prepare Finalized.
g.s.PutDKGFinalized(addr, true)
g.s.IncDKGFinalizedsCount()
+ // Prepare Success.
+ g.s.PutDKGSuccess(addr, true)
+ g.s.IncDKGSuccessesCount()
}
i += 1
}
@@ -1050,6 +1055,10 @@ func (g *OracleContractsTestSuite) TestResetDKG() {
for _, addr := range addrs[round] {
g.Require().True(g.s.DKGFinalized(addr))
}
+ g.Require().Equal(int64(dkgSetSize), g.s.DKGSuccessesCount().Int64())
+ for _, addr := range addrs[round] {
+ g.Require().True(g.s.DKGSuccess(addr))
+ }
}
}
@@ -1089,7 +1098,7 @@ func (g *OracleContractsTestSuite) TestResetDKG() {
g.s.IncDKGFinalizedsCount()
g.context.BlockNumber = big.NewInt(
- roundHeight*int64(round) + roundHeight*int64(r) + roundHeight*80/100)
+ roundHeight*int64(round) + roundHeight*int64(r) + roundHeight*85/100)
_, addr := newPrefundAccount(g.stateDB)
newCRS := randomBytes(common.HashLength, common.HashLength)
input, err := GovernanceABI.ABI.Pack("resetDKG", newCRS)
@@ -1115,6 +1124,11 @@ func (g *OracleContractsTestSuite) TestResetDKG() {
for _, addr := range addrs[round+1] {
g.Require().False(g.s.DKGFinalized(addr))
}
+ // Test if Success is purged.
+ g.Require().Equal(int64(0), g.s.DKGSuccessesCount().Int64())
+ for _, addr := range addrs[round+1] {
+ g.Require().False(g.s.DKGSuccess(addr))
+ }
g.Require().Equal(int64(r+1), g.s.DKGResetCount(roundPlusOne).Int64())