aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei-Ning Huang <w@cobinhood.com>2018-10-03 23:18:55 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:49 +0800
commitcbd9e4cd4cabb10b80f549311d2cd3c3af63a557 (patch)
treeb07a75fcc0bf5940610fa9546804be2c721dfdb5
parent333af73098bcf40bc1f509ef2327ef6abd1042a1 (diff)
downloaddexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.tar
dexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.tar.gz
dexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.tar.bz2
dexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.tar.lz
dexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.tar.xz
dexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.tar.zst
dexon-cbd9e4cd4cabb10b80f549311d2cd3c3af63a557.zip
core: vm: implement governance contract methods
-rw-r--r--core/vm/governance.go269
1 files changed, 218 insertions, 51 deletions
diff --git a/core/vm/governance.go b/core/vm/governance.go
index c3b316a64..bf3e33c39 100644
--- a/core/vm/governance.go
+++ b/core/vm/governance.go
@@ -6,6 +6,13 @@ import (
"github.com/dexon-foundation/dexon/accounts/abi"
"github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/crypto"
+ "github.com/dexon-foundation/dexon/rlp"
+
+ coreCommon "github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core"
+ coreCrypto "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/types"
)
var GovernanceContractAddress = common.BytesToAddress([]byte{0XED}) // Reverse of DEX0
@@ -347,11 +354,32 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (
case "unstake":
return g.unstake()
case "proposeCRS":
- return g.proposeCRS()
+ args := struct {
+ Round *big.Int
+ SignedCRS []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, argument); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.proposeCRS(args.Round, args.SignedCRS)
case "addDKGMasterPublicKey":
- return g.addDKGMasterPublicKey()
+ args := struct {
+ Round *big.Int
+ DKGMasterPublicKey []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, argument); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGMasterPublicKey(args.Round, args.DKGMasterPublicKey)
case "addDKGComplaint":
- return g.addDKGComplaint()
+ args := struct {
+ Round *big.Int
+ DKGComplaint []byte
+ }{}
+ if err := method.Inputs.Unpack(&args, argument); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.addDKGComplaint(args.Round, args.DKGComplaint)
}
return nil, nil
}
@@ -361,43 +389,13 @@ type StateHelper struct {
StateDB StateDB
}
-// 0: address public governanceMultisig;
-func (s *StateHelper) governanceMultisig() common.Address {
- return common.Address{}
-}
-
-// 1: int256 public numChains;
-func (s *StateHelper) numChains() *big.Int {
- return nil
-}
-
-// 2: int256 public lambdaBA;
-func (s *StateHelper) lambdaBA() *big.Int {
- return nil
-}
-
-// 3: int256 public lambdaDKG;
-func (s *StateHelper) lambdaDKG() *big.Int {
- return nil
-}
-
-// 4: int256 public k;
-func (s *StateHelper) k() *big.Int {
- return nil
-}
-
-// 5: int256 public phiRatio; // stored as PhiRatio * 10^6
-func (s *StateHelper) phiRatio() *big.Int {
- return nil
-}
-
// struct Node {
// address owner;
// bytes publicKey;
// uint256 staked;
// }
//
-// 6: Node[] nodes;
+// 0: Node[] nodes;
type nodeInfo struct {
owner common.Address
@@ -408,13 +406,15 @@ type nodeInfo struct {
func (s *StateHelper) nodesLength() *big.Int {
return nil
}
-func (s *StateHelper) node(offset *big.Int) *nodeInfo {
+func (s *StateHelper) node(index *big.Int) *nodeInfo {
return nil
}
func (s *StateHelper) pushNode(n *nodeInfo) {
}
+func (s *StateHelper) updateNode(index *big.Int, n *nodeInfo) {
+}
-// 7: mapping(address => uint256) public offset;
+// 1: mapping(address => uint256) public offset;
func (s *StateHelper) offset(addr common.Address) *big.Int {
return nil
}
@@ -423,7 +423,29 @@ func (s *StateHelper) putOffset(addr common.Address, offset *big.Int) {
func (s *StateHelper) deleteOffset(addr common.Address) {
}
-// 8: uint256 public round;
+// 2: mapping(uint256 => bytes32) public crs;
+func (s *StateHelper) crs(round *big.Int) common.Hash {
+ return common.Hash{}
+}
+func (s *StateHelper) putCRS(round *big.Int, crs []byte) common.Hash {
+ return common.Hash{}
+}
+
+// 3: mapping(uint256 => bytes[]) public DKGMasterPublicKeys;
+func (s *StateHelper) dkgMasterPublicKeys(round *big.Int) [][]byte {
+ return nil
+}
+func (s *StateHelper) pushDKGMasterPublicKey(round *big.Int, pk []byte) {
+}
+
+// 4: mapping(uint256 => bytes[]) public DKGComplaints;
+func (s *StateHelper) dkgComplaints(round *big.Int) [][]byte {
+ return nil
+}
+func (s *StateHelper) addDKGComplaint(round *big.Int, complaint []byte) {
+}
+
+// 5: uint256 public round;
func (s *StateHelper) round() *big.Int {
return nil
}
@@ -431,26 +453,59 @@ func (s *StateHelper) incRound() *big.Int {
return nil
}
-// 9: mapping(uint256 => bytes32) public crs;
-func (s *StateHelper) crs(round *big.Int) common.Hash {
- return common.Hash{}
+// 6: address public governanceMultisig;
+func (s *StateHelper) governanceMultisig() common.Address {
+ return common.Address{}
}
-func (s *StateHelper) pushCRS(round *big.Int, crs []byte) common.Hash {
- return common.Hash{}
+
+// 7: uint256 public numChains;
+func (s *StateHelper) numChains() *big.Int {
+ return nil
}
-// 10: mapping(uint256 => bytes[]) public DKGMasterPublicKeys;
-func (s *StateHelper) dkgMasterPublicKey(round *big.Int) [][]byte {
+// 8: uint256 public lambdaBA;
+func (s *StateHelper) lambdaBA() *big.Int {
return nil
}
-func (s *StateHelper) addDKGMasterPublicKey(round *big.Int, pk []byte) {
+
+// 9: uint256 public lambdaDKG;
+func (s *StateHelper) lambdaDKG() *big.Int {
+ return nil
}
-// 11: mapping(uint256 => bytes[]) public DKGComplaints;
-func (s *StateHelper) dkgComplaint(round *big.Int) [][]byte {
+// 10: uint256 public k;
+func (s *StateHelper) k() *big.Int {
return nil
}
-func (s *StateHelper) addDKGComplaint(round *big.Int, complaint []byte) {
+
+// 11: uint256 public phiRatio; // stored as PhiRatio * 10^6
+func (s *StateHelper) phiRatio() *big.Int {
+ return nil
+}
+
+// 12: uint256 public numNotarySet;
+func (s *StateHelper) numNotarySet() *big.Int {
+ return nil
+}
+
+// 13: uint256 public numDKGSet;
+func (s *StateHelper) numDKGSet() *big.Int {
+ return nil
+}
+
+// 14: uint256 public roundInterval
+func (s *StateHelper) roundInterval() *big.Int {
+ return nil
+}
+
+// 15: uint256 public minBlockInterval
+func (s *StateHelper) minBlockInterval() *big.Int {
+ return nil
+}
+
+// 16: uint256 public maxBlockInterval
+func (s *StateHelper) maxBlockInterval() *big.Int {
+ return nil
}
type GovernanceContract struct {
@@ -472,21 +527,133 @@ func (G *GovernanceContract) updateConfiguration() ([]byte, error) {
}
func (g *GovernanceContract) stake(publicKey []byte) ([]byte, error) {
+ caller := g.contract.Caller()
+ offset := g.state.offset(caller)
+
+ // Can not stake if already staked.
+ if offset != nil {
+ return nil, errExecutionReverted
+ }
+
+ // TODO(w): check of pk belongs to the address.
+ offset = g.state.nodesLength()
+ g.state.pushNode(&nodeInfo{
+ owner: caller,
+ publicKey: publicKey,
+ staked: g.contract.Value(),
+ })
+ g.state.putOffset(caller, offset)
return nil, nil
}
func (g *GovernanceContract) unstake() ([]byte, error) {
+ caller := g.contract.Caller()
+ offset := g.state.offset(caller)
+ if offset == nil {
+ return nil, errExecutionReverted
+ }
+
+ node := g.state.node(offset)
+ length := g.state.nodesLength()
+ lastIndex := new(big.Int).Sub(length, big.NewInt(1))
+
+ // Delete the node.
+ if offset != lastIndex {
+ lastNode := g.state.node(lastIndex)
+ g.state.updateNode(offset, lastNode)
+ g.state.putOffset(lastNode.owner, offset)
+ g.state.deleteOffset(caller)
+ }
+
+ // Return the staked fund.
+ g.evm.Transfer(g.evm.StateDB, GovernanceContractAddress, caller, node.staked)
return nil, nil
}
-func (g *GovernanceContract) proposeCRS() ([]byte, error) {
+func (g *GovernanceContract) proposeCRS(round *big.Int, signedCRS []byte) ([]byte, error) {
+ crs := g.state.crs(round)
+
+ // Revert if CRS for that round already exists.
+ if crs != (common.Hash{}) {
+ return nil, errExecutionReverted
+ }
+
+ prevRound := g.state.round()
+ prevCRS := g.state.crs(prevRound)
+
+ // round should be the next round number, abort otherwise.
+ if new(big.Int).Add(prevRound, big.NewInt(1)).Cmp(round) != 0 {
+ return nil, errExecutionReverted
+ }
+
+ // Prepare DKGMasterPublicKeys.
+ // TODO(w): make sure DKGMasterPKs are unique.
+ var dkgMasterPKs []*types.DKGMasterPublicKey
+ for _, pk := range g.state.dkgMasterPublicKeys(round) {
+ x := new(types.DKGMasterPublicKey)
+ if err := rlp.DecodeBytes(pk, x); err != nil {
+ panic(err)
+ }
+ dkgMasterPKs = append(dkgMasterPKs, x)
+ }
+
+ // Prepare DKGComplaints.
+ var dkgComplaints []*types.DKGComplaint
+ for _, comp := range g.state.dkgComplaints(round) {
+ x := new(types.DKGComplaint)
+ if err := rlp.DecodeBytes(comp, x); err != nil {
+ panic(err)
+ }
+ dkgComplaints = append(dkgComplaints, x)
+ }
+
+ threshold := int(g.state.numDKGSet().Uint64() / 3)
+
+ dkgGPK, err := core.NewDKGGroupPublicKey(
+ round.Uint64(), dkgMasterPKs, dkgComplaints, threshold)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ signature := coreCrypto.Signature{
+ Type: "bls",
+ Signature: signedCRS,
+ }
+ if !dkgGPK.VerifySignature(coreCommon.Hash(prevCRS), signature) {
+ return nil, errExecutionReverted
+ }
+
+ // Save new CRS into state and increase round.
+ newCRS := crypto.Keccak256(signedCRS)
+ g.state.incRound()
+ g.state.putCRS(round, newCRS)
+
return nil, nil
}
-func (g *GovernanceContract) addDKGMasterPublicKey() ([]byte, error) {
+func (g *GovernanceContract) addDKGMasterPublicKey(round *big.Int, pk []byte) ([]byte, error) {
+ var dkgMasterPK types.DKGMasterPublicKey
+ if err := rlp.DecodeBytes(pk, &dkgMasterPK); err != nil {
+ return nil, errExecutionReverted
+ }
+ verified, _ := core.VerifyDKGMasterPublicKeySignature(&dkgMasterPK)
+ if !verified {
+ return nil, errExecutionReverted
+ }
+
+ g.state.pushDKGMasterPublicKey(round, pk)
return nil, nil
}
-func (g *GovernanceContract) addDKGComplaint() ([]byte, error) {
+func (g *GovernanceContract) addDKGComplaint(round *big.Int, comp []byte) ([]byte, error) {
+ var dkgComplaint types.DKGComplaint
+ if err := rlp.DecodeBytes(comp, &dkgComplaint); err != nil {
+ return nil, errExecutionReverted
+ }
+ verified, _ := core.VerifyDKGComplaintSignature(&dkgComplaint)
+ if !verified {
+ return nil, errExecutionReverted
+ }
+
+ g.state.addDKGComplaint(round, comp)
return nil, nil
}