diff options
author | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-17 15:42:47 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-09-17 16:57:30 +0800 |
commit | 0f7b223fa10ec41f1d2342d3b5de9a9f6a7432ce (patch) | |
tree | 6c72fa1f326801f6acb91d768d660cbb383771c0 | |
parent | 8dddb63449d3d1439357a3bccd5c3cf828136ea5 (diff) | |
download | go-tangerine-0f7b223fa10ec41f1d2342d3b5de9a9f6a7432ce.tar.gz go-tangerine-0f7b223fa10ec41f1d2342d3b5de9a9f6a7432ce.tar.zst go-tangerine-0f7b223fa10ec41f1d2342d3b5de9a9f6a7432ce.zip |
core: vm: add updateNodeInfo governance method
-rw-r--r-- | core/vm/oracle_contract_abi.go | 184 | ||||
-rw-r--r-- | core/vm/oracle_contracts.go | 79 | ||||
-rw-r--r-- | core/vm/oracle_contracts_test.go | 24 |
3 files changed, 201 insertions, 86 deletions
diff --git a/core/vm/oracle_contract_abi.go b/core/vm/oracle_contract_abi.go index 53c3edc1e..535161bd4 100644 --- a/core/vm/oracle_contract_abi.go +++ b/core/vm/oracle_contract_abi.go @@ -947,11 +947,11 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "NewOwner", - "type": "address" + "name": "Complaint", + "type": "bytes" } ], - "name": "transferNodeOwnership", + "name": "addDKGComplaint", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -961,15 +961,11 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "OldOwner", - "type": "address" - }, - { - "name": "NewOwner", - "type": "address" + "name": "PublicKey", + "type": "bytes" } ], - "name": "transferNodeOwnershipByFoundation", + "name": "addDKGMasterPublicKey", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -979,43 +975,39 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "NewPublicKey", + "name": "MPKReady", "type": "bytes" } ], - "name": "replaceNodePublicKey", + "name": "addDKGMPKReady", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, - "inputs": [], - "name": "nodesLength", - "outputs": [ + "constant": false, + "inputs": [ { - "name": "", - "type": "uint256" + "name": "Finalize", + "type": "bytes" } ], + "name": "addDKGFinalize", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { - "name": "Round", - "type": "uint256" - }, - { - "name": "SignedCRS", + "name": "Success", "type": "bytes" } ], - "name": "proposeCRS", + "name": "addDKGSuccess", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1025,39 +1017,43 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "Complaint", - "type": "bytes" + "name": "NodeAddress", + "type": "address" } ], - "name": "addDKGComplaint", + "name": "payFine", "outputs": [], - "payable": false, - "stateMutability": "nonpayable", + "payable": true, + "stateMutability": "payable", "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "nodesLength", + "outputs": [ { - "name": "PublicKey", - "type": "bytes" + "name": "", + "type": "uint256" } ], - "name": "addDKGMasterPublicKey", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { - "name": "MPKReady", + "name": "Round", + "type": "uint256" + }, + { + "name": "SignedCRS", "type": "bytes" } ], - "name": "addDKGMPKReady", + "name": "proposeCRS", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1067,11 +1063,19 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "Finalize", + "name": "Type", + "type": "uint256" + }, + { + "name": "Arg1", + "type": "bytes" + }, + { + "name": "Arg2", "type": "bytes" } ], - "name": "addDKGFinalize", + "name": "report", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1081,11 +1085,11 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "Success", + "name": "NewSignedCRS", "type": "bytes" } ], - "name": "addDKGSuccess", + "name": "resetDKG", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1123,6 +1127,20 @@ const GovernanceABIJSON = ` }, { "constant": false, + "inputs": [ + { + "name": "NewPublicKey", + "type": "bytes" + } + ], + "name": "replaceNodePublicKey", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, "inputs": [], "name": "stake", "outputs": [], @@ -1134,11 +1152,11 @@ const GovernanceABIJSON = ` "constant": false, "inputs": [ { - "name": "Amount", - "type": "uint256" + "name": "NewOwner", + "type": "address" } ], - "name": "unstake", + "name": "transferNodeOwnership", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1146,58 +1164,57 @@ const GovernanceABIJSON = ` }, { "constant": false, - "inputs": [], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "withdrawable", - "outputs": [ + "inputs": [ { - "name": "", - "type": "bool" + "name": "OldOwner", + "type": "address" + }, + { + "name": "NewOwner", + "type": "address" } ], + "name": "transferNodeOwnershipByFoundation", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { - "name": "NodeAddress", - "type": "address" + "name": "Amount", + "type": "uint256" } ], - "name": "payFine", + "name": "unstake", "outputs": [], - "payable": true, - "stateMutability": "payable", + "payable": false, + "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { - "name": "Type", - "type": "uint256" + "name": "Name", + "type": "string" }, { - "name": "Arg1", - "type": "bytes" + "name": "Email", + "type": "string" }, { - "name": "Arg2", - "type": "bytes" + "name": "Location", + "type": "string" + }, + { + "name": "Url", + "type": "string" } ], - "name": "report", + "name": "updateNodeInfo", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -1205,16 +1222,25 @@ const GovernanceABIJSON = ` }, { "constant": false, - "inputs": [ + "inputs": [], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "withdrawable", + "outputs": [ { - "name": "NewSignedCRS", - "type": "bytes" + "name": "", + "type": "bool" } ], - "name": "resetDKG", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" } ] diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go index 05d4bd821..484ed82b8 100644 --- a/core/vm/oracle_contracts.go +++ b/core/vm/oracle_contracts.go @@ -465,19 +465,48 @@ func (s *GovernanceState) UpdateNode(index *big.Int, n *nodeInfo) { // Update set size. s.CalNotarySetSize() } +func (s *GovernanceState) EraseNode(index *big.Int) { + s.UpdateNode(index, &nodeInfo{ + Staked: big.NewInt(0), + Fined: big.NewInt(0), + Unstaked: big.NewInt(0), + UnstakedAt: big.NewInt(0), + }) +} func (s *GovernanceState) PopLastNode() { // Decrease length by 1. arrayLength := s.LenNodes() newArrayLength := new(big.Int).Sub(arrayLength, big.NewInt(1)) s.setStateBigInt(big.NewInt(nodesLoc), newArrayLength) - s.UpdateNode(newArrayLength, &nodeInfo{ - Staked: big.NewInt(0), - Fined: big.NewInt(0), - Unstaked: big.NewInt(0), - UnstakedAt: big.NewInt(0), - }) + s.EraseNode(newArrayLength) } +func (s *GovernanceState) UpdateNodeInfo(index *big.Int, n *nodeInfo) { + arrayBaseLoc := s.getSlotLoc(big.NewInt(nodesLoc)) + elementBaseLoc := new(big.Int).Add(arrayBaseLoc, + new(big.Int).Mul(index, big.NewInt(nodeStructSize))) + + // Name. + loc := new(big.Int).Add(elementBaseLoc, big.NewInt(4)) + s.eraseBytes(loc) + s.writeBytes(loc, []byte(n.Name)) + + // Email. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(5)) + s.eraseBytes(loc) + s.writeBytes(loc, []byte(n.Email)) + + // Location. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6)) + s.eraseBytes(loc) + s.writeBytes(loc, []byte(n.Location)) + + // Url. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(7)) + s.eraseBytes(loc) + s.writeBytes(loc, []byte(n.Url)) +} + func (s *GovernanceState) Nodes() []*nodeInfo { var nodes []*nodeInfo for i := int64(0); i < int64(s.LenNodes().Uint64()); i++ { @@ -1728,7 +1757,7 @@ func (g *GovernanceContract) register( publicKey []byte, name, email, location, url string) ([]byte, error) { // Reject invalid inputs. - if len(name) >= 32 || len(email) >= 32 || len(location) >= 32 || len(url) >= 128 { + if len(name) >= 64 || len(email) >= 128 || len(location) >= 64 || len(url) >= 128 { return nil, errExecutionReverted } @@ -1838,6 +1867,31 @@ func (g *GovernanceContract) unstake(amount *big.Int) ([]byte, error) { return g.useGas(GovernanceActionGasCost) } +func (g *GovernanceContract) updateNodeInfo( + name, email, location, url string) ([]byte, error) { + + caller := g.contract.Caller() + + offset := g.state.NodesOffsetByAddress(caller) + if offset.Cmp(big.NewInt(0)) < 0 { + return nil, errExecutionReverted + } + + // Reject invalid inputs. + if len(name) >= 64 || len(email) >= 128 || len(location) >= 64 || len(url) >= 128 { + return nil, errExecutionReverted + } + + g.state.UpdateNodeInfo(offset, &nodeInfo{ + Name: name, + Email: email, + Location: location, + Url: url, + }) + + return g.useGas(GovernanceActionGasCost) +} + func (g *GovernanceContract) withdraw() ([]byte, error) { if !g.withdrawable() { return nil, errExecutionReverted @@ -2323,6 +2377,17 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re return nil, errExecutionReverted } return g.updateConfiguration(&cfg) + case "updateNodeInfo": + args := struct { + Name string + Email string + Location string + Url string + }{} + if err := method.Inputs.Unpack(&args, arguments); err != nil { + return nil, errExecutionReverted + } + return g.updateNodeInfo(args.Name, args.Email, args.Location, args.Url) case "withdraw": return g.withdraw() case "withdrawable": diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go index 9a2c151bf..7c892ac10 100644 --- a/core/vm/oracle_contracts_test.go +++ b/core/vm/oracle_contracts_test.go @@ -402,6 +402,30 @@ func (g *OracleContractsTestSuite) TestReplaceNodePublicKey() { g.Require().Error(err) } +func (g *OracleContractsTestSuite) TestUpdateNodeInfo() { + privKey, addr := newPrefundAccount(g.stateDB) + pk := crypto.FromECDSAPub(&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) + + input, err = GovernanceABI.ABI.Pack("updateNodeInfo", "New Name", "new@dexon.org", "New Location", "https://new.dexon.org") + g.Require().NoError(err) + + _, err = g.call(GovernanceContractAddress, addr, input, big.NewInt(0)) + g.Require().NoError(err) + + offset := g.s.NodesOffsetByAddress(addr) + node := g.s.Node(offset) + g.Require().Equal("New Name", node.Name) + g.Require().Equal("new@dexon.org", node.Email) + g.Require().Equal("New Location", node.Location) + g.Require().Equal("https://new.dexon.org", node.Url) +} + func (g *OracleContractsTestSuite) TestStakingMechanism() { privKey, addr := newPrefundAccount(g.stateDB) pk := crypto.FromECDSAPub(&privKey.PublicKey) |