From 6f3f370b317c57125f20237b4e3b7c05f888cc1c Mon Sep 17 00:00:00 2001
From: Wei-Ning Huang <w@dexon.org>
Date: Thu, 14 Mar 2019 13:14:29 +0800
Subject: core: vm: implement transfer node ownership (#255)

---
 core/vm/oracle_contracts.go | 43 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 8 deletions(-)

(limited to 'core/vm/oracle_contracts.go')

diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go
index 4168c7b37..836489420 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -240,7 +240,6 @@ func (s *GovernanceState) read1DByteArray(loc *big.Int) [][]byte {
 		elementLoc := new(big.Int).Add(dataLoc, big.NewInt(i))
 		data = append(data, s.readBytes(elementLoc))
 	}
-
 	return data
 }
 
@@ -517,13 +516,13 @@ func (s *GovernanceState) DeleteNodeOffsets(n *nodeInfo) error {
 	return nil
 }
 
-func (s *GovernanceState) GetNodeOwnerByID(id coreTypes.NodeID) (common.Address, error) {
+func (s *GovernanceState) GetNodeByID(id coreTypes.NodeID) (*nodeInfo, error) {
 	offset := s.NodesOffsetByNodeKeyAddress(idToAddress(id))
 	if offset.Cmp(big.NewInt(0)) < 0 {
-		return common.Address{}, errors.New("node not found")
+		return nil, errors.New("node not found")
 	}
 	node := s.Node(offset)
-	return node.Owner, nil
+	return node, nil
 }
 
 // uint256 public crsRound;
@@ -1270,9 +1269,11 @@ func (g *GovernanceContract) addDKGComplaint(round *big.Int, comp []byte) ([]byt
 		return g.penalize()
 	}
 	if need {
+		node, err := g.state.GetNodeByID(dkgComplaint.PrivateShare.ProposerID)
+		if err != nil {
+			return g.penalize()
+		}
 		fineValue := g.state.FineValue(big.NewInt(ReportTypeInvalidDKG))
-		offset := g.state.NodesOffsetByNodeKeyAddress(idToAddress(dkgComplaint.PrivateShare.ProposerID))
-		node := g.state.Node(offset)
 		if err := g.fine(node.Owner, fineValue, comp, nil); err != nil {
 			return g.penalize()
 		}
@@ -1703,8 +1704,10 @@ func (g *GovernanceContract) report(reportType *big.Int, arg1, arg2 []byte) ([]b
 		return g.penalize()
 	}
 
-	offset := g.state.NodesOffsetByNodeKeyAddress(idToAddress(reportedNodeID))
-	node := g.state.Node(offset)
+	node, err := g.state.GetNodeByID(reportedNodeID)
+	if err != nil {
+		return g.penalize()
+	}
 
 	g.state.emitForkReported(node.Owner, reportType, arg1, arg2)
 
@@ -1931,6 +1934,12 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
 			return nil, errExecutionReverted
 		}
 		return g.transferOwnership(newOwner)
+	case "transferNodeOwnership":
+		var newOwner common.Address
+		if err := method.Inputs.Unpack(&newOwner, arguments); err != nil {
+			return nil, errExecutionReverted
+		}
+		return g.transferNodeOwnership(newOwner)
 	case "unstake":
 		amount := new(big.Int)
 		if err := method.Inputs.Unpack(&amount, arguments); err != nil {
@@ -2219,6 +2228,24 @@ func (g *GovernanceContract) transferOwnership(newOwner common.Address) ([]byte,
 	return nil, nil
 }
 
+func (g *GovernanceContract) transferNodeOwnership(newOwner common.Address) ([]byte, error) {
+	caller := g.contract.Caller()
+
+	offset := g.state.NodesOffsetByAddress(caller)
+	if offset.Cmp(big.NewInt(0)) < 0 {
+		return g.penalize()
+	}
+
+	node := g.state.Node(offset)
+	g.state.PutNodeOffsets(node, big.NewInt(0))
+
+	node.Owner = newOwner
+	g.state.PutNodeOffsets(node, offset)
+	g.state.UpdateNode(offset, node)
+
+	return nil, nil
+}
+
 func PackProposeCRS(round uint64, signedCRS []byte) ([]byte, error) {
 	method := GovernanceABI.Name2Method["proposeCRS"]
 	res, err := method.Inputs.Pack(big.NewInt(int64(round)), signedCRS)
-- 
cgit