From 32dcd528f9152d6fe3e32f76adb1ea3c595910de Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Tue, 6 Nov 2018 22:12:40 +0800 Subject: core: vm: governance: add node info --- core/blockchain.go | 4 ++ core/gen_genesis_account.go | 6 +++ core/genesis.go | 15 +++++- core/genesis_alloc.go | 2 +- core/mkalloc.go | 14 ++++++ core/vm/governance.go | 118 +++++++++++++++++++++++++++++++++++++++++--- test/genesis.json | 32 ++++++++++-- 7 files changed, 177 insertions(+), 14 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 04b154ade..c44d2633a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -231,6 +231,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par } } } + + // Set genesis round height mapping. + bc.roundHeightMap.Store(0, 0) + // Take ownership of this particular state go bc.update() return bc, nil diff --git a/core/gen_genesis_account.go b/core/gen_genesis_account.go index 1a5653e4b..15393d978 100644 --- a/core/gen_genesis_account.go +++ b/core/gen_genesis_account.go @@ -23,6 +23,7 @@ func (g GenesisAccount) MarshalJSON() ([]byte, error) { Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` Staked *math.HexOrDecimal256 `json:"staked"` PublicKey hexutil.Bytes `json:"publicKey"` + NodeInfo NodeInfo `json:"info"` PrivateKey hexutil.Bytes `json:"secretKey,omitempty"` } var enc GenesisAccount @@ -37,6 +38,7 @@ func (g GenesisAccount) MarshalJSON() ([]byte, error) { enc.Nonce = math.HexOrDecimal64(g.Nonce) enc.Staked = (*math.HexOrDecimal256)(g.Staked) enc.PublicKey = g.PublicKey + enc.NodeInfo = g.NodeInfo enc.PrivateKey = g.PrivateKey return json.Marshal(&enc) } @@ -50,6 +52,7 @@ func (g *GenesisAccount) UnmarshalJSON(input []byte) error { Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"` Staked *math.HexOrDecimal256 `json:"staked"` PublicKey *hexutil.Bytes `json:"publicKey"` + NodeInfo *NodeInfo `json:"info"` PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"` } var dec GenesisAccount @@ -78,6 +81,9 @@ func (g *GenesisAccount) UnmarshalJSON(input []byte) error { if dec.PublicKey != nil { g.PublicKey = *dec.PublicKey } + if dec.NodeInfo != nil { + g.NodeInfo = *dec.NodeInfo + } if dec.PrivateKey != nil { g.PrivateKey = *dec.PrivateKey } diff --git a/core/genesis.go b/core/genesis.go index 8b957edd2..38b8c360b 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -80,6 +80,14 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error { return nil } +// NodeInfo represents the info of a node. +type NodeInfo struct { + Name string `json:"name"` + Email string `json:"email"` + Location string `json:"location"` + Url string `json:"url"` +} + // GenesisAccount is an account in the state of the genesis block. type GenesisAccount struct { Code []byte `json:"code,omitempty"` @@ -88,6 +96,7 @@ type GenesisAccount struct { Nonce uint64 `json:"nonce,omitempty"` Staked *big.Int `json:"staked"` PublicKey []byte `json:"publicKey"` + NodeInfo NodeInfo `json:"info"` PrivateKey []byte `json:"secretKey,omitempty"` // for tests } @@ -285,7 +294,9 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { account.Staked = big.NewInt(0) } if account.Staked.Cmp(big.NewInt(0)) > 0 { - govStateHelper.Stake(addr, account.PublicKey, account.Staked) + govStateHelper.Stake(addr, account.PublicKey, account.Staked, + account.NodeInfo.Name, account.NodeInfo.Email, + account.NodeInfo.Location, account.NodeInfo.Url) } } // Genesis CRS. @@ -420,6 +431,7 @@ func decodePrealloc(data string) GenesisAlloc { Staked *big.Int Code []byte PublicKey []byte + NodeInfo NodeInfo } var p []struct { @@ -436,6 +448,7 @@ func decodePrealloc(data string) GenesisAlloc { Staked: account.Account.Staked, Code: account.Account.Code, PublicKey: account.Account.PublicKey, + NodeInfo: account.Account.NodeInfo, } } return ga diff --git a/core/genesis_alloc.go b/core/genesis_alloc.go index 60f6e717b..ffe360457 100644 --- a/core/genesis_alloc.go +++ b/core/genesis_alloc.go @@ -21,6 +21,6 @@ package core // Use mkalloc.go to create/update them. // nolint: misspell -const mainnetAllocData = "\xf9\x02\x0e\xe4\x94\x12E\xa8g/\xa8\x81\u03c5\x8e\xf0\x1d4\xc4+U\u0672c\xff\u038a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\x80\x80\x80\xf8o\x946\x1eIX\xbd\x8bM\x03\\h\xc4s\x19>w\xfd\xabj\xea\x9d\xf8X\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04\f/\a\xcf\"\x96n\xba\xa1\x9d\xd8}\xe1\x1d\x04\xf9\xa6\x06\xe8>u\xa5)Utv\nZM\xd8(\a\xe7\xd9\xf2\x8f\x86\xcd8\x98q\u0753\x1aG|\xacd\xe23\xa6\xf0\x98\u0572W\x87\x1d\x81c\xdc\x1b\xdd\xcf\xf8o\x94\xb6\xa2\xe2p\xb5O\x19\xb4\x00-e5\xa7\x1c\xfd\xd1\xca\x1f_\xc1\xf8X\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04c\xf7\x8d9\x8fk\x04)R\x06*&\xf3U\x1aN)J\x11\bK\x10\x06\xc8\xd67d7\xb7$\x88\xd8\xf3\xafk\x84\x991\xc06$\xad-X\x19\x00\xe9\xad_<\xfe\xee\xd0@\u01d9\xe50\x8c\xd8\x01(S\xfb\xf8o\x94\xb6\xbb\xbe9\x0311\xe4(\u0563TXV\xa5\x96\xca\xcbx\x10\xf8X\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04\xa1\x11\x8c\x8f\x1c.)=\xe5(\xe5\xb4Z\xc5\xe6Qg\xafL\xb4\xd1\b\x87\x92J\x9f\x83\x92\x87\xd0`\xda&AN\x97\x1c\xabu\x01>V\r\xfe\u01c9{\x19\x83\xea\xa61\xae/\x16\xea@bRS\x10\xed\xd8\xea\xf8o\x94\xbcq\xc0\xf2\xae\xcaF\xfa\x00\x01\xe7e\x96P)\xb1j\x06\x04\x9e\xf8X\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04\xa1*\x01_'\u064eS\x05I\x8d#\xae\xac\xde(\x1eH\xaa\xd9\x18\xae\x87\xd7\xf6\x17\x84\xabC\x82\x89S\u06d9\xbf\x1fDBb\x94\xcb\xc2\x1e2\xcf:\x99\x12/,\xe8\xa3[\xa7\x18\xa7\xc8\x14\xee\u01fa\xe9\xa3\xea\u453f\x8cH\xa6\xba\xccF\x90\u007f\x9b\x89s-%\xe4z-|\xf7\u038a\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\x80\x80\x80" +const mainnetAllocData = "\xf9\x03+\xe9\x94\x12E\xa8g/\xa8\x81\u03c5\x8e\xf0\x1d4\xc4+U\u0672c\xff\u04ca\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\x80\x80\x80\u0100\x80\x80\x80\xf8\xa9\x946\x1eIX\xbd\x8bM\x03\\h\xc4s\x19>w\xfd\xabj\xea\x9d\xf8\x92\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04\f/\a\xcf\"\x96n\xba\xa1\x9d\xd8}\xe1\x1d\x04\xf9\xa6\x06\xe8>u\xa5)Utv\nZM\xd8(\a\xe7\xd9\xf2\x8f\x86\xcd8\x98q\u0753\x1aG|\xacd\xe23\xa6\xf0\x98\u0572W\x87\x1d\x81c\xdc\x1b\xdd\xcf\xf88\x86DEXON1\x8fnode1@dexon.org\x8eTaipei, Taiwan\x91https://dexon.org\xf8\xa9\x94\xb6\xa2\xe2p\xb5O\x19\xb4\x00-e5\xa7\x1c\xfd\xd1\xca\x1f_\xc1\xf8\x92\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04c\xf7\x8d9\x8fk\x04)R\x06*&\xf3U\x1aN)J\x11\bK\x10\x06\xc8\xd67d7\xb7$\x88\xd8\xf3\xafk\x84\x991\xc06$\xad-X\x19\x00\xe9\xad_<\xfe\xee\xd0@\u01d9\xe50\x8c\xd8\x01(S\xfb\xf88\x86DEXON3\x8fnode3@dexon.org\x8eTaipei, Taiwan\x91https://dexon.org\xf8\xa9\x94\xb6\xbb\xbe9\x0311\xe4(\u0563TXV\xa5\x96\xca\xcbx\x10\xf8\x92\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04\xa1\x11\x8c\x8f\x1c.)=\xe5(\xe5\xb4Z\xc5\xe6Qg\xafL\xb4\xd1\b\x87\x92J\x9f\x83\x92\x87\xd0`\xda&AN\x97\x1c\xabu\x01>V\r\xfe\u01c9{\x19\x83\xea\xa61\xae/\x16\xea@bRS\x10\xed\xd8\xea\xf88\x86DEXON4\x8fnode4@dexon.org\x8eTaipei, Taiwan\x91https://dexon.org\xf8\xa9\x94\xbcq\xc0\xf2\xae\xcaF\xfa\x00\x01\xe7e\x96P)\xb1j\x06\x04\x9e\xf8\x92\x8965\u026d\xc5\u07a0\x00\x00\x89\x1b\x1a\xe4\xd6\xe2\xefP\x00\x00\x80\xb8A\x04\xa1*\x01_'\u064eS\x05I\x8d#\xae\xac\xde(\x1eH\xaa\xd9\x18\xae\x87\xd7\xf6\x17\x84\xabC\x82\x89S\u06d9\xbf\x1fDBb\x94\xcb\xc2\x1e2\xcf:\x99\x12/,\xe8\xa3[\xa7\x18\xa7\xc8\x14\xee\u01fa\xe9\xa3\xea\xf88\x86DEXON2\x8fnode2@dexon.org\x8eTaipei, Taiwan\x91https://dexon.org\u953f\x8cH\xa6 \xba\xccF\x90\u007f\x9b\x89s-%\xe4z-|\xf7\u04ca\x15-\x02\xc7\xe1J\xf6\x80\x00\x00\x80\x80\x80\u0100\x80\x80\x80\xea\x94\xe0\xf8Y4\x03S\x85F\x93\xf57\xea3q\x06\xa3>\x9f\xea\xb0\u050bR\xb7\xd2\xdc\xc8\f\xd2\xe4\x00\x00\x00\x80\x80\x80\u0100\x80\x80\x80" const testnetAllocData = mainnetAllocData diff --git a/core/mkalloc.go b/core/mkalloc.go index cc246b5a8..a871685f6 100644 --- a/core/mkalloc.go +++ b/core/mkalloc.go @@ -38,11 +38,19 @@ import ( "github.com/dexon-foundation/dexon/rlp" ) +type nodeInfo struct { + Name string + Email string + Location string + Url string +} + type accountData struct { Balance *big.Int Staked *big.Int Code []byte PublicKey []byte + NodeInfo nodeInfo } type allocItem struct { @@ -67,6 +75,12 @@ func makelist(g *core.Genesis) allocList { Balance: account.Balance, Staked: account.Staked, PublicKey: account.PublicKey, + NodeInfo: nodeInfo{ + Name: account.NodeInfo.Name, + Email: account.NodeInfo.Email, + Location: account.NodeInfo.Location, + Url: account.NodeInfo.Url, + }, }}) } sort.Sort(a) diff --git a/core/vm/governance.go b/core/vm/governance.go index 46effcc29..3361be671 100644 --- a/core/vm/governance.go +++ b/core/vm/governance.go @@ -127,6 +127,22 @@ const abiJSON = ` { "name": "staked", "type": "uint256" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "location", + "type": "string" + }, + { + "name": "url", + "type": "string" } ], "payable": false, @@ -568,6 +584,22 @@ const abiJSON = ` { "name": "PublicKey", "type": "bytes" + }, + { + "name": "Name", + "type": "string" + }, + { + "name": "Email", + "type": "string" + }, + { + "name": "Location", + "type": "string" + }, + { + "name": "Url", + "type": "string" } ], "name": "stake", @@ -692,11 +724,17 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) ( } return g.proposeCRS(args.Round, args.SignedCRS) case "stake": - var publicKey []byte - if err := method.Inputs.Unpack(&publicKey, arguments); err != nil { + args := struct { + PublicKey []byte + Name string + Email string + Location string + Url string + }{} + if err := method.Inputs.Unpack(&args, arguments); err != nil { return nil, errExecutionReverted } - return g.stake(publicKey) + return g.stake(args.PublicKey, args.Name, args.Email, args.Location, args.Url) case "snapshotRound": args := struct { Round *big.Int @@ -844,7 +882,9 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) ( return nil, errExecutionReverted } info := g.state.Node(index) - res, err := method.Outputs.Pack(info.Owner, info.PublicKey, info.Staked) + res, err := method.Outputs.Pack( + info.Owner, info.PublicKey, info.Staked, + info.Name, info.Email, info.Location, info.Url) if err != nil { return nil, errExecutionReverted } @@ -1080,6 +1120,10 @@ func (s *GovernanceStateHelper) PushRoundHeight(height *big.Int) { // address owner; // bytes publicKey; // uint256 staked; +// string name; +// string email; +// string location; +// string url; // } // // Node[] nodes; @@ -1088,8 +1132,14 @@ type nodeInfo struct { Owner common.Address PublicKey []byte Staked *big.Int + Name string + Email string + Location string + Url string } +const nodesInfoSize = 7 + func (s *GovernanceStateHelper) NodesLength() *big.Int { return s.getStateBigInt(big.NewInt(nodesLoc)) } @@ -1097,7 +1147,8 @@ func (s *GovernanceStateHelper) Node(index *big.Int) *nodeInfo { node := new(nodeInfo) arrayBaseLoc := s.getSlotLoc(big.NewInt(nodesLoc)) - elementBaseLoc := new(big.Int).Add(arrayBaseLoc, new(big.Int).Mul(index, big.NewInt(3))) + elementBaseLoc := new(big.Int).Add(arrayBaseLoc, + new(big.Int).Mul(index, big.NewInt(nodesInfoSize))) // owner. loc := elementBaseLoc @@ -1111,6 +1162,22 @@ func (s *GovernanceStateHelper) Node(index *big.Int) *nodeInfo { loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2)) node.Staked = s.getStateBigInt(loc) + // name. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(3)) + node.Name = string(s.readBytes(loc)) + + // email. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(4)) + node.Email = string(s.readBytes(loc)) + + // location. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(5)) + node.Location = string(s.readBytes(loc)) + + // url. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6)) + node.Url = string(s.readBytes(loc)) + return node } func (s *GovernanceStateHelper) PushNode(n *nodeInfo) { @@ -1122,7 +1189,8 @@ func (s *GovernanceStateHelper) PushNode(n *nodeInfo) { } func (s *GovernanceStateHelper) UpdateNode(index *big.Int, n *nodeInfo) { arrayBaseLoc := s.getSlotLoc(big.NewInt(nodesLoc)) - elementBaseLoc := new(big.Int).Add(arrayBaseLoc, new(big.Int).Mul(index, big.NewInt(3))) + elementBaseLoc := new(big.Int).Add(arrayBaseLoc, + new(big.Int).Mul(index, big.NewInt(nodesInfoSize))) // owner. loc := elementBaseLoc @@ -1135,6 +1203,22 @@ func (s *GovernanceStateHelper) UpdateNode(index *big.Int, n *nodeInfo) { // staked. loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2)) s.setStateBigInt(loc, n.Staked) + + // name. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(3)) + s.writeBytes(loc, []byte(n.Name)) + + // email. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(4)) + s.writeBytes(loc, []byte(n.Email)) + + // location. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(5)) + s.writeBytes(loc, []byte(n.Location)) + + // url. + loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6)) + s.writeBytes(loc, []byte(n.Url)) } func (s *GovernanceStateHelper) Nodes() []*nodeInfo { var nodes []*nodeInfo @@ -1298,12 +1382,18 @@ func (s *GovernanceStateHelper) MinBlockInterval() *big.Int { } // Stake is a helper function for creating genesis state. -func (s *GovernanceStateHelper) Stake(addr common.Address, publicKey []byte, staked *big.Int) { +func (s *GovernanceStateHelper) Stake( + addr common.Address, publicKey []byte, staked *big.Int, + name, email, location, url string) { offset := s.NodesLength() s.PushNode(&nodeInfo{ Owner: addr, PublicKey: publicKey, Staked: staked, + Name: name, + Email: email, + Location: location, + Url: url, }) s.PutOffset(addr, offset) } @@ -1530,7 +1620,15 @@ func (g *GovernanceContract) updateConfiguration(config *params.DexconConfig) ([ return nil, nil } -func (g *GovernanceContract) stake(publicKey []byte) ([]byte, error) { +func (g *GovernanceContract) stake( + 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 { + g.penalize() + return nil, errExecutionReverted + } + caller := g.contract.Caller() offset := g.state.Offset(caller) @@ -1545,6 +1643,10 @@ func (g *GovernanceContract) stake(publicKey []byte) ([]byte, error) { Owner: caller, PublicKey: publicKey, Staked: g.contract.Value(), + Name: name, + Email: email, + Location: location, + Url: url, }) g.state.PutOffset(caller, offset) diff --git a/test/genesis.json b/test/genesis.json index 15c69179e..32a3bcfa0 100644 --- a/test/genesis.json +++ b/test/genesis.json @@ -46,22 +46,46 @@ "0x361e4958bd8b4d035C68C473193E77FdAb6aEa9D": { "balance": "1000000000000000000000", "staked": "500000000000000000000", - "publicKey": "0x040c2f07cf22966ebaa19dd87de11d04f9a606e83e75a5295574760a5a4dd82807e7d9f28f86cd389871dd931a477cac64e233a6f098d5b257871d8163dc1bddcf" + "publicKey": "0x040c2f07cf22966ebaa19dd87de11d04f9a606e83e75a5295574760a5a4dd82807e7d9f28f86cd389871dd931a477cac64e233a6f098d5b257871d8163dc1bddcf", + "info": { + "name": "DEXON1", + "email": "node1@dexon.org", + "location": "Taipei, Taiwan", + "url": "https://dexon.org" + } }, "0xbC71C0F2aeCa46fa0001e765965029b16a06049E": { "balance": "1000000000000000000000", "staked": "500000000000000000000", - "publicKey": "0x04a12a015f27d98e5305498d23aeacde281e48aad918ae87d7f61784ab43828953db99bf1f44426294cbc21e32cf3a99122f2ce8a35ba718a7c814eec7bae9a3ea" + "publicKey": "0x04a12a015f27d98e5305498d23aeacde281e48aad918ae87d7f61784ab43828953db99bf1f44426294cbc21e32cf3a99122f2ce8a35ba718a7c814eec7bae9a3ea", + "info": { + "name": "DEXON2", + "email": "node2@dexon.org", + "location": "Taipei, Taiwan", + "url": "https://dexon.org" + } }, "0xB6a2e270b54F19B4002d6535a71CFDd1CA1f5fC1": { "balance": "1000000000000000000000", "staked": "500000000000000000000", - "publicKey": "0x0463f78d398f6b042952062a26f3551a4e294a11084b1006c8d6376437b72488d8f3af6b849931c03624ad2d581900e9ad5f3cfeeed040c799e5308cd8012853fb" + "publicKey": "0x0463f78d398f6b042952062a26f3551a4e294a11084b1006c8d6376437b72488d8f3af6b849931c03624ad2d581900e9ad5f3cfeeed040c799e5308cd8012853fb", + "info": { + "name": "DEXON3", + "email": "node3@dexon.org", + "location": "Taipei, Taiwan", + "url": "https://dexon.org" + } }, "0xb6bBBE39033131e428d5a3545856a596cacB7810": { "balance": "1000000000000000000000", "staked": "500000000000000000000", - "publicKey": "0x04a1118c8f1c2e293de528e5b45ac5e65167af4cb4d10887924a9f839287d060da26414e971cab75013e560dfec7897b1983eaa631ae2f16ea4062525310edd8ea" + "publicKey": "0x04a1118c8f1c2e293de528e5b45ac5e65167af4cb4d10887924a9f839287d060da26414e971cab75013e560dfec7897b1983eaa631ae2f16ea4062525310edd8ea", + "info": { + "name": "DEXON4", + "email": "node4@dexon.org", + "location": "Taipei, Taiwan", + "url": "https://dexon.org" + } } } } -- cgit v1.2.3