diff options
author | Wei-Ning Huang <w@dexon.org> | 2019-03-14 13:14:29 +0800 |
---|---|---|
committer | Jimmy Hu <jimmy.hu@dexon.org> | 2019-03-14 13:14:29 +0800 |
commit | b8ce12b428d44e28f94a44948efdabb9352563d8 (patch) | |
tree | 040568183bd59b92a0ebf81f871385dee6dea148 | |
parent | 206035f286f375c198451b778ff8884a2357c5b1 (diff) | |
download | dexon-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.go | 16 | ||||
-rw-r--r-- | core/vm/oracle_contracts.go | 43 | ||||
-rw-r--r-- | core/vm/oracle_contracts_test.go | 33 | ||||
-rw-r--r-- | dex/app.go | 3 |
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{ |