From d7127cb517f29e727a48a588484834d7f242aadb Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Thu, 11 Oct 2018 15:01:10 +0800 Subject: core: add stake and public key to genesis account info --- core/gen_genesis.go | 2 + core/gen_genesis_account.go | 14 +++++++ core/genesis.go | 26 +++++++++++- core/vm/governance.go | 99 +++++++++++++++++++++++++-------------------- 4 files changed, 95 insertions(+), 46 deletions(-) diff --git a/core/gen_genesis.go b/core/gen_genesis.go index 022f8257a..63f478cc7 100644 --- a/core/gen_genesis.go +++ b/core/gen_genesis.go @@ -15,6 +15,7 @@ import ( var _ = (*genesisSpecMarshaling)(nil) +// MarshalJSON marshals as JSON. func (g Genesis) MarshalJSON() ([]byte, error) { type Genesis struct { Config *params.ChainConfig `json:"config"` @@ -51,6 +52,7 @@ func (g Genesis) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (g *Genesis) UnmarshalJSON(input []byte) error { type Genesis struct { Config *params.ChainConfig `json:"config"` diff --git a/core/gen_genesis_account.go b/core/gen_genesis_account.go index 45a03c329..1a5653e4b 100644 --- a/core/gen_genesis_account.go +++ b/core/gen_genesis_account.go @@ -14,12 +14,15 @@ import ( var _ = (*genesisAccountMarshaling)(nil) +// MarshalJSON marshals as JSON. func (g GenesisAccount) MarshalJSON() ([]byte, error) { type GenesisAccount struct { Code hexutil.Bytes `json:"code,omitempty"` Storage map[storageJSON]storageJSON `json:"storage,omitempty"` Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` + Staked *math.HexOrDecimal256 `json:"staked"` + PublicKey hexutil.Bytes `json:"publicKey"` PrivateKey hexutil.Bytes `json:"secretKey,omitempty"` } var enc GenesisAccount @@ -32,16 +35,21 @@ func (g GenesisAccount) MarshalJSON() ([]byte, error) { } enc.Balance = (*math.HexOrDecimal256)(g.Balance) enc.Nonce = math.HexOrDecimal64(g.Nonce) + enc.Staked = (*math.HexOrDecimal256)(g.Staked) + enc.PublicKey = g.PublicKey enc.PrivateKey = g.PrivateKey return json.Marshal(&enc) } +// UnmarshalJSON unmarshals from JSON. func (g *GenesisAccount) UnmarshalJSON(input []byte) error { type GenesisAccount struct { Code *hexutil.Bytes `json:"code,omitempty"` Storage map[storageJSON]storageJSON `json:"storage,omitempty"` Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` Nonce *math.HexOrDecimal64 `json:"nonce,omitempty"` + Staked *math.HexOrDecimal256 `json:"staked"` + PublicKey *hexutil.Bytes `json:"publicKey"` PrivateKey *hexutil.Bytes `json:"secretKey,omitempty"` } var dec GenesisAccount @@ -64,6 +72,12 @@ func (g *GenesisAccount) UnmarshalJSON(input []byte) error { if dec.Nonce != nil { g.Nonce = uint64(*dec.Nonce) } + if dec.Staked != nil { + g.Staked = (*big.Int)(dec.Staked) + } + if dec.PublicKey != nil { + g.PublicKey = *dec.PublicKey + } if dec.PrivateKey != nil { g.PrivateKey = *dec.PrivateKey } diff --git a/core/genesis.go b/core/genesis.go index f795ac241..6982312d2 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -31,6 +31,8 @@ import ( "github.com/dexon-foundation/dexon/core/rawdb" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" + "github.com/dexon-foundation/dexon/core/vm" + "github.com/dexon-foundation/dexon/crypto" "github.com/dexon-foundation/dexon/ethdb" "github.com/dexon-foundation/dexon/log" "github.com/dexon-foundation/dexon/params" @@ -83,6 +85,8 @@ type GenesisAccount struct { Storage map[common.Hash]common.Hash `json:"storage,omitempty"` Balance *big.Int `json:"balance" gencodec:"required"` Nonce uint64 `json:"nonce,omitempty"` + Staked *big.Int `json:"staked"` + PublicKey []byte `json:"publicKey"` PrivateKey []byte `json:"secretKey,omitempty"` // for tests } @@ -101,8 +105,10 @@ type genesisSpecMarshaling struct { type genesisAccountMarshaling struct { Code hexutil.Bytes Balance *math.HexOrDecimal256 + Staked *math.HexOrDecimal256 Nonce math.HexOrDecimal64 Storage map[storageJSON]storageJSON + PublicKey hexutil.Bytes PrivateKey hexutil.Bytes } @@ -231,13 +237,29 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { db = ethdb.NewMemDatabase() } statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) + govStateHelper := vm.GovernanceStateHelper{ + Address: vm.GovernanceContractAddress, + StateDB: statedb, + } for addr, account := range g.Alloc { - statedb.AddBalance(addr, account.Balance) + statedb.AddBalance(addr, new(big.Int).Sub(account.Balance, account.Staked)) statedb.SetCode(addr, account.Code) statedb.SetNonce(addr, account.Nonce) for key, value := range account.Storage { statedb.SetState(addr, key, value) } + + // Stake in governance state. + if account.Staked.Cmp(big.NewInt(0)) > 0 { + pk, err := crypto.DecompressPubkey(account.PublicKey) + if err != nil { + panic(err) + } + if crypto.PubkeyToAddress(*pk) != addr { + panic(fmt.Errorf("public key does not belones to %s", addr)) + } + govStateHelper.Stake(addr, account.PublicKey, account.Staked) + } } root := statedb.IntermediateRoot(false) head := &types.Header{ @@ -373,7 +395,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis { common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing - faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, + faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))}, }, } } diff --git a/core/vm/governance.go b/core/vm/governance.go index b78d1bf94..497070222 100644 --- a/core/vm/governance.go +++ b/core/vm/governance.go @@ -787,38 +787,38 @@ const ( ) // State manipulation helper fro the governance contract. -type StateHelper struct { +type GovernanceStateHelper struct { Address common.Address StateDB StateDB } -func (s *StateHelper) getState(loc common.Hash) common.Hash { +func (s *GovernanceStateHelper) getState(loc common.Hash) common.Hash { return s.StateDB.GetState(s.Address, loc) } -func (s *StateHelper) setState(loc common.Hash, val common.Hash) { +func (s *GovernanceStateHelper) setState(loc common.Hash, val common.Hash) { s.StateDB.SetState(s.Address, loc, val) } -func (s *StateHelper) getStateBigInt(loc *big.Int) *big.Int { +func (s *GovernanceStateHelper) getStateBigInt(loc *big.Int) *big.Int { res := s.StateDB.GetState(s.Address, common.BigToHash(loc)) return new(big.Int).SetBytes(res.Bytes()) } -func (s *StateHelper) setStateBigInt(loc *big.Int, val *big.Int) { +func (s *GovernanceStateHelper) setStateBigInt(loc *big.Int, val *big.Int) { s.setState(common.BigToHash(loc), common.BigToHash(val)) } -func (s *StateHelper) getSlotLoc(loc *big.Int) *big.Int { +func (s *GovernanceStateHelper) getSlotLoc(loc *big.Int) *big.Int { return new(big.Int).SetBytes(crypto.Keccak256(common.BigToHash(loc).Bytes())) } -func (s *StateHelper) getMapLoc(pos *big.Int, key []byte) *big.Int { +func (s *GovernanceStateHelper) getMapLoc(pos *big.Int, key []byte) *big.Int { return new(big.Int).SetBytes(crypto.Keccak256( key, common.BigToHash(pos).Bytes())) } -func (s *StateHelper) readBytes(loc *big.Int) []byte { +func (s *GovernanceStateHelper) readBytes(loc *big.Int) []byte { // length of the dynamic array (bytes). rawLength := s.getStateBigInt(loc) lengthByte := new(big.Int).Mod(rawLength, big.NewInt(256)) @@ -851,7 +851,7 @@ func (s *StateHelper) readBytes(loc *big.Int) []byte { return data } -func (s *StateHelper) writeBytes(loc *big.Int, data []byte) { +func (s *GovernanceStateHelper) writeBytes(loc *big.Int, data []byte) { length := int64(len(data)) // short bytes (length <= 31) @@ -892,7 +892,7 @@ func (s *StateHelper) writeBytes(loc *big.Int, data []byte) { } } -func (s *StateHelper) read2DByteArray(pos, index *big.Int) [][]byte { +func (s *GovernanceStateHelper) read2DByteArray(pos, index *big.Int) [][]byte { baseLoc := s.getSlotLoc(pos) loc := new(big.Int).Add(baseLoc, index) @@ -907,7 +907,7 @@ func (s *StateHelper) read2DByteArray(pos, index *big.Int) [][]byte { return data } -func (s *StateHelper) appendTo2DByteArray(pos, index *big.Int, data []byte) { +func (s *GovernanceStateHelper) appendTo2DByteArray(pos, index *big.Int, data []byte) { // Find the loc of the last element. baseLoc := s.getSlotLoc(pos) loc := new(big.Int).Add(baseLoc, index) @@ -936,10 +936,21 @@ type nodeInfo struct { staked *big.Int } -func (s *StateHelper) nodesLength() *big.Int { +// Stake is a helper function for creating genesis state. +func (s *GovernanceStateHelper) Stake(addr common.Address, publicKey []byte, staked *big.Int) { + offset := s.nodesLength() + s.pushNode(&nodeInfo{ + owner: addr, + publicKey: publicKey, + staked: staked, + }) + s.putOffset(addr, offset) +} + +func (s *GovernanceStateHelper) nodesLength() *big.Int { return s.getStateBigInt(big.NewInt(nodesLoc)) } -func (s *StateHelper) node(index *big.Int) *nodeInfo { +func (s *GovernanceStateHelper) node(index *big.Int) *nodeInfo { node := new(nodeInfo) arrayBaseLoc := s.getSlotLoc(big.NewInt(nodesLoc)) @@ -959,14 +970,14 @@ func (s *StateHelper) node(index *big.Int) *nodeInfo { return nil } -func (s *StateHelper) pushNode(n *nodeInfo) { +func (s *GovernanceStateHelper) pushNode(n *nodeInfo) { // increase length by 1 arrayLength := s.nodesLength() s.setStateBigInt(big.NewInt(nodesLoc), new(big.Int).Add(arrayLength, big.NewInt(1))) s.updateNode(arrayLength, n) } -func (s *StateHelper) updateNode(index *big.Int, 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))) @@ -984,29 +995,29 @@ func (s *StateHelper) updateNode(index *big.Int, n *nodeInfo) { } // mapping(address => uint256) public offset; -func (s *StateHelper) offset(addr common.Address) *big.Int { +func (s *GovernanceStateHelper) offset(addr common.Address) *big.Int { loc := s.getMapLoc(big.NewInt(offsetLoc), addr.Bytes()) return new(big.Int).Sub(s.getStateBigInt(loc), big.NewInt(1)) } -func (s *StateHelper) putOffset(addr common.Address, offset *big.Int) { +func (s *GovernanceStateHelper) putOffset(addr common.Address, offset *big.Int) { loc := s.getMapLoc(big.NewInt(offsetLoc), addr.Bytes()) s.setStateBigInt(loc, new(big.Int).Add(offset, big.NewInt(1))) } -func (s *StateHelper) deleteOffset(addr common.Address) { +func (s *GovernanceStateHelper) deleteOffset(addr common.Address) { loc := s.getMapLoc(big.NewInt(offsetLoc), addr.Bytes()) s.setStateBigInt(loc, big.NewInt(0)) } // bytes32[] public crs; -func (s *StateHelper) lenCRS() *big.Int { +func (s *GovernanceStateHelper) lenCRS() *big.Int { return s.getStateBigInt(big.NewInt(crsLoc)) } -func (s *StateHelper) crs(index *big.Int) common.Hash { +func (s *GovernanceStateHelper) crs(index *big.Int) common.Hash { baseLoc := s.getSlotLoc(big.NewInt(crsLoc)) loc := new(big.Int).Add(baseLoc, index) return s.getState(common.BigToHash(loc)) } -func (s *StateHelper) pushCRS(crs common.Hash) { +func (s *GovernanceStateHelper) pushCRS(crs common.Hash) { // increase length by 1. length := s.getStateBigInt(big.NewInt(crsLoc)) s.setStateBigInt(big.NewInt(crsLoc), new(big.Int).Add(length, big.NewInt(1))) @@ -1018,28 +1029,28 @@ func (s *StateHelper) pushCRS(crs common.Hash) { } // bytes[][] public dkgMasterPublicKeys; -func (s *StateHelper) dkgMasterPublicKeys(round *big.Int) [][]byte { +func (s *GovernanceStateHelper) dkgMasterPublicKeys(round *big.Int) [][]byte { return s.read2DByteArray(big.NewInt(dkgMasterPublicKeysLoc), round) } -func (s *StateHelper) pushDKGMasterPublicKey(round *big.Int, pk []byte) { +func (s *GovernanceStateHelper) pushDKGMasterPublicKey(round *big.Int, pk []byte) { s.appendTo2DByteArray(big.NewInt(dkgMasterPublicKeysLoc), round, pk) } // bytes[][] public dkgComplaints; -func (s *StateHelper) dkgComplaints(round *big.Int) [][]byte { +func (s *GovernanceStateHelper) dkgComplaints(round *big.Int) [][]byte { return s.read2DByteArray(big.NewInt(dkgComplaintsLoc), round) } -func (s *StateHelper) pushDKGComplaint(round *big.Int, complaint []byte) { +func (s *GovernanceStateHelper) pushDKGComplaint(round *big.Int, complaint []byte) { s.appendTo2DByteArray(big.NewInt(dkgComplaintsLoc), round, complaint) } // mapping(address => bool)[] public dkgFinalized; -func (s *StateHelper) dkgFinalized(round *big.Int, addr common.Address) bool { +func (s *GovernanceStateHelper) dkgFinalized(round *big.Int, addr common.Address) bool { baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinailizedLoc)), round) mapLoc := s.getMapLoc(baseLoc, addr.Bytes()) return s.getStateBigInt(mapLoc).Cmp(big.NewInt(0)) != 0 } -func (s *StateHelper) putDKGFinalized(round *big.Int, addr common.Address, finalized bool) { +func (s *GovernanceStateHelper) putDKGFinalized(round *big.Int, addr common.Address, finalized bool) { baseLoc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinailizedLoc)), round) mapLoc := s.getMapLoc(baseLoc, addr.Bytes()) res := big.NewInt(0) @@ -1050,73 +1061,73 @@ func (s *StateHelper) putDKGFinalized(round *big.Int, addr common.Address, final } // uint256[] public dkgFinalizedsCount; -func (s *StateHelper) dkgFinalizedsCount(round *big.Int) *big.Int { +func (s *GovernanceStateHelper) dkgFinalizedsCount(round *big.Int) *big.Int { loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedsCountLoc)), round) return s.getStateBigInt(loc) } -func (s *StateHelper) incDKGFinalizedsCount(round *big.Int) { +func (s *GovernanceStateHelper) incDKGFinalizedsCount(round *big.Int) { loc := new(big.Int).Add(s.getSlotLoc(big.NewInt(dkgFinalizedsCountLoc)), round) count := s.getStateBigInt(loc) s.setStateBigInt(loc, new(big.Int).Add(count, big.NewInt(1))) } // address public owner; -func (s *StateHelper) owner() common.Address { +func (s *GovernanceStateHelper) owner() common.Address { val := s.getState(common.BigToHash(big.NewInt(ownerLoc))) return common.BytesToAddress(val.Bytes()) } // uint256 public numChains; -func (s *StateHelper) numChains() *big.Int { +func (s *GovernanceStateHelper) numChains() *big.Int { return s.getStateBigInt(big.NewInt(numChainsLoc)) } // uint256 public lambdaBA; -func (s *StateHelper) lambdaBA() *big.Int { +func (s *GovernanceStateHelper) lambdaBA() *big.Int { return s.getStateBigInt(big.NewInt(lambdaBALoc)) } // uint256 public lambdaDKG; -func (s *StateHelper) lambdaDKG() *big.Int { +func (s *GovernanceStateHelper) lambdaDKG() *big.Int { return s.getStateBigInt(big.NewInt(lambdaDKGLoc)) } // uint256 public k; -func (s *StateHelper) k() *big.Int { +func (s *GovernanceStateHelper) k() *big.Int { return s.getStateBigInt(big.NewInt(kLoc)) } // uint256 public phiRatio; // stored as PhiRatio * 10^6 -func (s *StateHelper) phiRatio() *big.Int { +func (s *GovernanceStateHelper) phiRatio() *big.Int { return s.getStateBigInt(big.NewInt(phiRatioLoc)) } // uint256 public notarySetSize; -func (s *StateHelper) notarySetSize() *big.Int { +func (s *GovernanceStateHelper) notarySetSize() *big.Int { return s.getStateBigInt(big.NewInt(notarySetSizeLoc)) } // uint256 public dkgSetSize; -func (s *StateHelper) dkgSetSize() *big.Int { +func (s *GovernanceStateHelper) dkgSetSize() *big.Int { return s.getStateBigInt(big.NewInt(dkgSetSizeLoc)) } // uint256 public roundInterval -func (s *StateHelper) roundInterval() *big.Int { +func (s *GovernanceStateHelper) roundInterval() *big.Int { return s.getStateBigInt(big.NewInt(roundIntervalLoc)) } // uint256 public minBlockInterval -func (s *StateHelper) minBlockInterval() *big.Int { +func (s *GovernanceStateHelper) minBlockInterval() *big.Int { return s.getStateBigInt(big.NewInt(minBlockIntervalLoc)) } // uint256 public maxBlockInterval -func (s *StateHelper) maxBlockInterval() *big.Int { +func (s *GovernanceStateHelper) maxBlockInterval() *big.Int { return s.getStateBigInt(big.NewInt(maxBlockIntervalLoc)) } -func (s *StateHelper) emitConfigurationChangedEvent() { +func (s *GovernanceStateHelper) emitConfigurationChangedEvent() { s.StateDB.AddLog(&types.Log{ Address: s.Address, Topics: []common.Hash{events["ConfigurationChanged"].Id()}, @@ -1124,7 +1135,7 @@ func (s *StateHelper) emitConfigurationChangedEvent() { }) } -func (s *StateHelper) emitCRSProposed(round *big.Int, crs common.Hash) { +func (s *GovernanceStateHelper) emitCRSProposed(round *big.Int, crs common.Hash) { s.StateDB.AddLog(&types.Log{ Address: s.Address, Topics: []common.Hash{events["CRSProposed"].Id(), common.BigToHash(round)}, @@ -1135,14 +1146,14 @@ func (s *StateHelper) emitCRSProposed(round *big.Int, crs common.Hash) { // GovernanceContract represents the governance contract of DEXCON. type GovernanceContract struct { evm *EVM - state StateHelper + state GovernanceStateHelper contract *Contract } func newGovernanceContract(evm *EVM, contract *Contract) *GovernanceContract { return &GovernanceContract{ evm: evm, - state: StateHelper{contract.Address(), evm.StateDB}, + state: GovernanceStateHelper{contract.Address(), evm.StateDB}, contract: contract, } } -- cgit