aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2019-03-14 13:14:29 +0800
committerJimmy Hu <jimmy.hu@dexon.org>2019-03-14 13:14:29 +0800
commitb8ce12b428d44e28f94a44948efdabb9352563d8 (patch)
tree040568183bd59b92a0ebf81f871385dee6dea148
parent206035f286f375c198451b778ff8884a2357c5b1 (diff)
downloaddexon-b8ce12b428d44e28f94a44948efdabb9352563d8.tar.gz
dexon-b8ce12b428d44e28f94a44948efdabb9352563d8.tar.zst
dexon-b8ce12b428d44e28f94a44948efdabb9352563d8.zip
core: vm: implement transfer node ownership (#255)
-rw-r--r--core/vm/oracle_contract_abi.go16
-rw-r--r--core/vm/oracle_contracts.go43
-rw-r--r--core/vm/oracle_contracts_test.go33
-rw-r--r--dex/app.go3
4 files changed, 85 insertions, 10 deletions
diff --git a/core/vm/oracle_contract_abi.go b/core/vm/oracle_contract_abi.go
index 23fb99ae5..e06adf633 100644
--- a/core/vm/oracle_contract_abi.go
+++ b/core/vm/oracle_contract_abi.go
@@ -741,7 +741,7 @@ const GovernanceABIJSON = `
"constant": false,
"inputs": [
{
- "name": "newOwner",
+ "name": "NewOwner",
"type": "address"
}
],
@@ -806,6 +806,20 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NewOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferNodeOwnership",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "nodesLength",
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)
diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go
index 0b8b7b4f7..436923aa3 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/oracle_contracts_test.go
@@ -239,6 +239,39 @@ func (g *OracleContractsTestSuite) TestTransferOwnership() {
g.Require().Equal(addr, g.s.Owner())
}
+func (g *OracleContractsTestSuite) TestTransferNodeOwnership() {
+ privKey, addr := g.newPrefundAccount()
+ pk := crypto.FromECDSAPub(&privKey.PublicKey)
+ nodeKeyAddr := crypto.PubkeyToAddress(privKey.PublicKey)
+
+ amount := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e6))
+ input, err := GovernanceABI.ABI.Pack("register", pk, "Test1", "test1@dexon.org", "Taipei", "https://dexon.org")
+ g.Require().NoError(err)
+ _, err = g.call(GovernanceContractAddress, addr, input, amount)
+ g.Require().NoError(err)
+
+ offset := g.s.NodesOffsetByAddress(addr)
+
+ _, newAddr := g.newPrefundAccount()
+ newNodeKeyAddr := crypto.PubkeyToAddress(privKey.PublicKey)
+
+ input, err = GovernanceABI.ABI.Pack("transferNodeOwnership", newAddr)
+ g.Require().NoError(err)
+
+ // Call with non-owner.
+ _, noneOwner := g.newPrefundAccount()
+ _, err = g.call(GovernanceContractAddress, noneOwner, input, big.NewInt(0))
+ g.Require().Error(err)
+
+ // Call with owner.
+ _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0))
+ g.Require().NoError(err)
+ g.Require().Equal(uint64(0), g.s.NodesOffsetByAddress(addr).Uint64())
+ g.Require().Equal(uint64(0), g.s.NodesOffsetByNodeKeyAddress(nodeKeyAddr).Uint64())
+ g.Require().Equal(offset.Uint64(), g.s.NodesOffsetByAddress(newAddr).Uint64())
+ g.Require().Equal(offset.Uint64(), g.s.NodesOffsetByNodeKeyAddress(newNodeKeyAddr).Uint64())
+}
+
func (g *OracleContractsTestSuite) TestStakingMechanism() {
privKey, addr := g.newPrefundAccount()
pk := crypto.FromECDSAPub(&privKey.PublicKey)
diff --git a/dex/app.go b/dex/app.go
index 90ffd3d3c..8caa84837 100644
--- a/dex/app.go
+++ b/dex/app.go
@@ -430,10 +430,11 @@ func (d *DexconApp) BlockDelivered(
var owner common.Address
if !block.IsEmpty() {
gs := d.gov.GetStateForConfigAtRound(block.Position.Round)
- owner, err = gs.GetNodeOwnerByID(block.ProposerID)
+ node, err := gs.GetNodeByID(block.ProposerID)
if err != nil {
panic(err)
}
+ owner = node.Owner
}
newBlock := types.NewBlock(&types.Header{