From 0c9666161c9630edf8eca571e7c93db7d21dfba3 Mon Sep 17 00:00:00 2001 From: Jimmy Hu Date: Fri, 21 Dec 2018 12:03:28 +0800 Subject: core: vm: Add `MPKReady` to governance (#97) * core/vm: Add DKGMPKReady * param: update GenesisHash * vendor: sync to latest core --- core/governance.go | 8 +++ core/vm/governance.go | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+) (limited to 'core') diff --git a/core/governance.go b/core/governance.go index ea0036a0e..45594fb64 100644 --- a/core/governance.go +++ b/core/governance.go @@ -121,6 +121,14 @@ func (g *Governance) DKGMasterPublicKeys(round uint64) []*dkgTypes.MasterPublicK return headHelper.UniqueDKGMasterPublicKeys(big.NewInt(int64(round))) } +func (g *Governance) IsDKGMPKReady(round uint64) bool { + headHelper := g.GetHeadHelper() + config := g.Configuration(round) + threshold := 2*uint64(config.DKGSetSize)/3 + 1 + count := headHelper.DKGMPKReadysCount(big.NewInt(int64(round))).Uint64() + return count >= threshold +} + func (g *Governance) IsDKGFinal(round uint64) bool { headHelper := g.GetHeadHelper() config := g.Configuration(round) diff --git a/core/vm/governance.go b/core/vm/governance.go index 07f0a5479..597399dd5 100644 --- a/core/vm/governance.go +++ b/core/vm/governance.go @@ -236,6 +236,48 @@ const GovernanceABIJSON = ` "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "dkgMPKReadysCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "dkgMPKReadys", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -749,6 +791,24 @@ const GovernanceABIJSON = ` "stateMutability": "nonpayable", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "name": "Round", + "type": "uint256" + }, + { + "name": "MPKReady", + "type": "bytes" + } + ], + "name": "addDKGMPKReady", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -917,6 +977,15 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (ret []by return nil, errExecutionReverted } return g.addDKGMasterPublicKey(args.Round, args.PublicKey) + case "addDKGMPKReady": + args := struct { + Round *big.Int + MPKReady []byte + }{} + if err := method.Inputs.Unpack(&args, arguments); err != nil { + return nil, errExecutionReverted + } + return g.addDKGMPKReady(args.Round, args.MPKReady) case "addDKGFinalize": args := struct { Round *big.Int @@ -1070,6 +1139,30 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (ret []by return nil, errExecutionReverted } return res, nil + case "dkgReadys": + round, addr := new(big.Int), common.Address{} + args := []interface{}{&round, &addr} + if err := method.Inputs.Unpack(&args, arguments); err != nil { + return nil, errExecutionReverted + } + ready := g.state.DKGMPKReady(round, addr) + res, err := method.Outputs.Pack(ready) + if err != nil { + return nil, errExecutionReverted + } + return res, nil + case "dkgReadysCount": + round := new(big.Int) + if err := method.Inputs.Unpack(&round, arguments); err != nil { + return nil, errExecutionReverted + } + count := g.state.DKGMPKReadysCount(round) + res, err := method.Outputs.Pack(count) + if err != nil { + return nil, errExecutionReverted + } + return res, nil + case "dkgFinalizeds": round, addr := new(big.Int), common.Address{} args := []interface{}{&round, &addr} @@ -1228,6 +1321,8 @@ const ( crsLoc dkgMasterPublicKeysLoc dkgComplaintsLoc + dkgReadyLoc + dkgReadysCountLoc dkgFinalizedLoc dkgFinalizedsCountLoc ownerLoc @@ -1716,6 +1811,33 @@ func (s *GovernanceStateHelper) PushDKGComplaint(round *big.Int, complaint []byt s.appendTo2DByteArray(big.NewInt(dkgComplaintsLoc), round, complaint) } +// mapping(address => bool)[] public dkgReady; +func (s *GovernanceStateHelper) DKGMPKReady(round *big.Int, addr common.Address) bool { + baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadyLoc)), round) + mapLoc := s.getMapLoc(baseLoc, addr.Bytes()) + return s.getStateBigInt(mapLoc).Cmp(big.NewInt(0)) != 0 +} +func (s *GovernanceStateHelper) PutDKGMPKReady(round *big.Int, addr common.Address, ready bool) { + baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadyLoc)), round) + mapLoc := s.getMapLoc(baseLoc, addr.Bytes()) + res := big.NewInt(0) + if ready { + res = big.NewInt(1) + } + s.setStateBigInt(mapLoc, res) +} + +// uint256[] public dkgReadysCount; +func (s *GovernanceStateHelper) DKGMPKReadysCount(round *big.Int) *big.Int { + loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadysCountLoc)), round) + return s.getStateBigInt(loc) +} +func (s *GovernanceStateHelper) IncDKGMPKReadysCount(round *big.Int) { + loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgReadysCountLoc)), round) + count := s.getStateBigInt(loc) + s.setStateBigInt(loc, new(big.Int).Add(count, big.NewInt(1))) +} + // mapping(address => bool)[] public dkgFinalized; func (s *GovernanceStateHelper) DKGFinalized(round *big.Int, addr common.Address) bool { baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedLoc)), round) @@ -2087,6 +2209,21 @@ func (g *GovernanceContract) addDKGMasterPublicKey(round *big.Int, mpk []byte) ( return nil, errExecutionReverted } + // MPKReady caller is not allowed to propose mpk. + if g.state.DKGMPKReady(round, caller) { + return g.penalize() + } + + // Calculate 2f + threshold := new(big.Int).Mul( + big.NewInt(2), + new(big.Int).Div(g.state.DKGSetSize(), big.NewInt(3))) + + // If 2f + 1 of DKG set is mpk ready, one can not propose mpk anymore. + if g.state.DKGMPKReadysCount(round).Cmp(threshold) > 0 { + return nil, errExecutionReverted + } + var dkgMasterPK dkgTypes.MasterPublicKey if err := rlp.DecodeBytes(mpk, &dkgMasterPK); err != nil { return g.penalize() @@ -2107,6 +2244,35 @@ func (g *GovernanceContract) addDKGMasterPublicKey(round *big.Int, mpk []byte) ( return g.useGas(100000) } +func (g *GovernanceContract) addDKGMPKReady(round *big.Int, ready []byte) ([]byte, error) { + if round.Cmp(g.state.Round()) != 0 { + return g.penalize() + } + + caller := g.contract.Caller() + + var dkgReady dkgTypes.MPKReady + if err := rlp.DecodeBytes(ready, &dkgReady); err != nil { + return g.penalize() + } + + // DKGFInalize must belongs to someone in DKG set. + if !g.inDKGSet(round, dkgReady.ProposerID) { + return g.penalize() + } + + verified, _ := core.VerifyDKGMPKReadySignature(&dkgReady) + if !verified { + return g.penalize() + } + + if !g.state.DKGMPKReady(round, caller) { + g.state.PutDKGMPKReady(round, caller, true) + g.state.IncDKGMPKReadysCount(round) + } + + return g.useGas(100000) +} func (g *GovernanceContract) addDKGFinalize(round *big.Int, finalize []byte) ([]byte, error) { if round.Cmp(g.state.Round()) != 0 { return g.penalize() -- cgit v1.2.3