Merge pull request #560 from harmony-one/rj_branch

Setup genesis shard state, and fix other issues
pull/563/head
Rongjian Lan 6 years ago committed by GitHub
commit 197e4c9552
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      core/blockchain.go
  2. 58
      core/gen_genesis.go
  3. 46
      core/genesis.go
  4. 32
      core/resharding.go
  5. 3
      node/node.go
  6. 7
      node/node_genesis.go
  7. 4
      node/node_handler.go
  8. 4
      node/node_newblock.go
  9. 1
      test/configs/beaconchain.txt

@ -1732,8 +1732,8 @@ func (bc *BlockChain) ValidateNewShardState(block *types.Block, stakeInfo *map[c
return nil
}
// InsertNewShardState insert new shard state into epoch block
func (bc *BlockChain) InsertNewShardState(block *types.Block, stakeInfo *map[common.Address]*structs.StakeInfo) {
// StoreNewShardState insert new shard state into epoch block
func (bc *BlockChain) StoreNewShardState(block *types.Block, stakeInfo *map[common.Address]*structs.StakeInfo) {
// write state into db.
shardState := bc.GetNewShardState(block, stakeInfo)
if shardState == nil {
@ -1742,8 +1742,8 @@ func (bc *BlockChain) InsertNewShardState(block *types.Block, stakeInfo *map[com
hash := block.Hash()
number := block.NumberU64()
rawdb.WriteShardState(bc.db, hash, number, shardState)
utils.GetLogInstance().Debug("[resharding] save new shard state success", "shardStateHash", shardState.Hash())
utils.GetLogInstance().Debug("[Resharding] Saved new shard state success", "shardStateHash", shardState.Hash())
for _, c := range shardState {
utils.GetLogInstance().Debug("[resharding] new shard information", "shardID", c.ShardID, "NodeList", c.NodeList)
utils.GetLogInstance().Debug("[Resharding] Shard Info", "shardID", c.ShardID, "NodeList", c.NodeList)
}
}

@ -18,19 +18,20 @@ var _ = (*genesisSpecMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (g Genesis) MarshalJSON() ([]byte, error) {
type Genesis struct {
Config *params.ChainConfig `json:"config"`
Nonce math.HexOrDecimal64 `json:"nonce"`
ShardID uint32 `json:"shardID"`
Timestamp math.HexOrDecimal64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"`
Number math.HexOrDecimal64 `json:"number"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
Config *params.ChainConfig `json:"config"`
Nonce math.HexOrDecimal64 `json:"nonce"`
ShardID uint32 `json:"shardID"`
Timestamp math.HexOrDecimal64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"`
ShardStateHash common.Hash `json:"shardStateHash"`
Number math.HexOrDecimal64 `json:"number"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
}
var enc Genesis
enc.Config = g.Config
@ -48,6 +49,7 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
enc.Alloc[common.UnprefixedAddress(k)] = v
}
}
enc.ShardStateHash = g.ShardStateHash
enc.Number = math.HexOrDecimal64(g.Number)
enc.GasUsed = math.HexOrDecimal64(g.GasUsed)
enc.ParentHash = g.ParentHash
@ -57,19 +59,20 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (g *Genesis) UnmarshalJSON(input []byte) error {
type Genesis struct {
Config *params.ChainConfig `json:"config"`
Nonce *math.HexOrDecimal64 `json:"nonce"`
ShardID *uint32 `json:"shardID"`
Timestamp *math.HexOrDecimal64 `json:"timestamp"`
ExtraData *hexutil.Bytes `json:"extraData"`
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash *common.Hash `json:"mixHash"`
Coinbase *common.Address `json:"coinbase"`
Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"`
Number *math.HexOrDecimal64 `json:"number"`
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
ParentHash *common.Hash `json:"parentHash"`
Config *params.ChainConfig `json:"config"`
Nonce *math.HexOrDecimal64 `json:"nonce"`
ShardID *uint32 `json:"shardID"`
Timestamp *math.HexOrDecimal64 `json:"timestamp"`
ExtraData *hexutil.Bytes `json:"extraData"`
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
Mixhash *common.Hash `json:"mixHash"`
Coinbase *common.Address `json:"coinbase"`
Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc" gencodec:"required"`
ShardStateHash *common.Hash `json:"shardStateHash"`
Number *math.HexOrDecimal64 `json:"number"`
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
ParentHash *common.Hash `json:"parentHash"`
}
var dec Genesis
if err := json.Unmarshal(input, &dec); err != nil {
@ -111,6 +114,9 @@ func (g *Genesis) UnmarshalJSON(input []byte) error {
for k, v := range dec.Alloc {
g.Alloc[common.Address(k)] = v
}
if dec.ShardStateHash != nil {
g.ShardStateHash = *dec.ShardStateHash
}
if dec.Number != nil {
g.Number = uint64(*dec.Number)
}

@ -45,16 +45,17 @@ var errGenesisNoConfig = errors.New("genesis has no chain configuration")
// Genesis specifies the header fields, state of a genesis block. It also defines hard
// fork switch-over blocks through the chain configuration.
type Genesis struct {
Config *params.ChainConfig `json:"config"`
Nonce uint64 `json:"nonce"`
ShardID uint32 `json:"shardID"`
Timestamp uint64 `json:"timestamp"`
ExtraData []byte `json:"extraData"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc GenesisAlloc `json:"alloc" gencodec:"required"`
Config *params.ChainConfig `json:"config"`
Nonce uint64 `json:"nonce"`
ShardID uint32 `json:"shardID"`
Timestamp uint64 `json:"timestamp"`
ExtraData []byte `json:"extraData"`
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
Difficulty *big.Int `json:"difficulty" gencodec:"required"`
Mixhash common.Hash `json:"mixHash"`
Coinbase common.Address `json:"coinbase"`
Alloc GenesisAlloc `json:"alloc" gencodec:"required"`
ShardStateHash common.Hash `json:"shardStateHash"`
// These fields are used for consensus tests. Please don't use them
// in actual genesis blocks.
@ -237,18 +238,19 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
}
root := statedb.IntermediateRoot(false)
head := &types.Header{
Number: new(big.Int).SetUint64(g.Number),
Nonce: types.EncodeNonce(g.Nonce),
ShardID: types.EncodeShardID(g.ShardID),
Time: new(big.Int).SetUint64(g.Timestamp),
ParentHash: g.ParentHash,
Extra: g.ExtraData,
GasLimit: g.GasLimit,
GasUsed: g.GasUsed,
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
Root: root,
Number: new(big.Int).SetUint64(g.Number),
Nonce: types.EncodeNonce(g.Nonce),
ShardID: types.EncodeShardID(g.ShardID),
Time: new(big.Int).SetUint64(g.Timestamp),
ParentHash: g.ParentHash,
Extra: g.ExtraData,
GasLimit: g.GasLimit,
GasUsed: g.GasUsed,
Difficulty: g.Difficulty,
MixDigest: g.Mixhash,
Coinbase: g.Coinbase,
Root: root,
ShardStateHash: g.ShardStateHash,
}
if g.GasLimit == 0 {
head.GasLimit = 10000000000 // TODO(RJ): figure out better solution. // params.GenesisGasLimit

@ -19,9 +19,12 @@ import (
const (
// InitialSeed is the initial random seed, a magic number to answer everything, remove later
InitialSeed uint32 = 42
// FirstEpoch is the number of the first epoch.
// TODO(minhdoan): we should design the first epoch as 0. Please figure out how to change other logic to make it 0
FirstEpoch = 1
// GenesisEpoch is the number of the first genesis epoch.
GenesisEpoch = 0
// GenesisShardNum is the number of shard at genesis
GenesisShardNum = 3
// GenesisShardSize is the size of each shard at genesis
GenesisShardSize = 10
)
// ShardingState is data structure hold the sharding state
@ -83,8 +86,11 @@ func (ss *ShardingState) cuckooResharding(percent float64) {
// assignLeaders will first add new nodes into shards, then use cuckoo rule to reshard to get new shard state
func (ss *ShardingState) assignLeaders() {
for i := 0; i < ss.numShards; i++ {
Shuffle(ss.shardState[i].NodeList)
ss.shardState[i].Leader = ss.shardState[i].NodeList[0]
// At genesis epoch, the shards are empty.
if len(ss.shardState[i].NodeList) > 0 {
Shuffle(ss.shardState[i].NodeList)
ss.shardState[i].Leader = ss.shardState[i].NodeList[0]
}
}
}
@ -134,12 +140,13 @@ func GetShardingStateFromBlockChain(bc *BlockChain, epoch uint64) *ShardingState
// CalculateNewShardState get sharding state from previous epoch and calculate sharding state for new epoch
// TODO: currently, we just mock everything
func CalculateNewShardState(bc *BlockChain, epoch uint64, stakeInfo *map[common.Address]*structs.StakeInfo) types.ShardState {
if epoch == FirstEpoch {
return getInitShardState(3, 10)
if epoch == GenesisEpoch {
return GetInitShardState()
}
ss := GetShardingStateFromBlockChain(bc, epoch-1)
newNodeList := ss.UpdateShardingState(stakeInfo)
percent := ss.calculateKickoutRate(newNodeList)
utils.GetLogInstance().Info("Kickout Percentage", "percentage", percent)
ss.Reshard(newNodeList, percent)
return ss.shardState
}
@ -190,15 +197,16 @@ func (ss *ShardingState) calculateKickoutRate(newNodeList []types.NodeID) float6
return math.Max(0.1, math.Min(rate, 1.0))
}
// getInitShardState returns the initial shard state at genesis.
func getInitShardState(numberOfShards, numNodesPerShard int) types.ShardState {
// GetInitShardState returns the initial shard state at genesis.
// TODO: make the deploy.sh config file in sync with genesis constants.
func GetInitShardState() types.ShardState {
shardState := types.ShardState{}
for i := 0; i < numberOfShards; i++ {
for i := 0; i < GenesisShardNum; i++ {
com := types.Committee{ShardID: uint32(i)}
if i == 0 {
for j := 0; j < numNodesPerShard; j++ {
for j := 0; j < GenesisShardSize; j++ {
priKey := bls.SecretKey{}
priKey.SetHexString(contract.InitialBeaconChainAccounts[i].Private)
priKey.SetHexString(contract.InitialBeaconChainAccounts[j].Private)
addrBytes := priKey.GetPublicKey().GetAddress()
address := hex.EncodeToString(addrBytes[:])
com.NodeList = append(com.NodeList, types.NodeID(address))

@ -240,6 +240,9 @@ func New(host p2p.Host, consensusObj *consensus.Consensus, db ethdb.Database) *N
os.Exit(1)
}
node.blockchain = chain
// Store the genesis shard state into db.
node.blockchain.StoreNewShardState(node.blockchain.CurrentBlock(), nil)
node.BlockChannel = make(chan *types.Block)
node.ConfirmedBlockChannel = make(chan *types.Block)
node.BeaconBlockChannel = make(chan *types.Block)

@ -43,9 +43,10 @@ func (node *Node) GenesisBlockSetup(db ethdb.Database) (*core.BlockChain, error)
chainConfig := params.TestChainConfig
chainConfig.ChainID = big.NewInt(int64(node.Consensus.ShardID)) // Use ChainID as piggybacked ShardID
gspec := core.Genesis{
Config: chainConfig,
Alloc: genesisAlloc,
ShardID: uint32(node.Consensus.ShardID),
Config: chainConfig,
Alloc: genesisAlloc,
ShardID: uint32(node.Consensus.ShardID),
ShardStateHash: core.GetInitShardState().Hash(),
}
// Store genesis block into db.

@ -153,7 +153,7 @@ func (node *Node) messageHandler(content []byte, sender string) {
utils.GetLogInstance().Info("NET: received message: Node/Control")
controlType := msgPayload[0]
if proto_node.ControlMessageType(controlType) == proto_node.STOP {
utils.GetLogInstance().Debug("Stopping Node", "node", node, "numBlocks", node.blockchain.CurrentBlock().NumberU64(), "numTxsProcessed", node.countNumTransactionsInBlockchain())
utils.GetLogInstance().Debug("Stopping Node", "numBlocks", node.blockchain.CurrentBlock().NumberU64(), "numTxsProcessed", node.countNumTransactionsInBlockchain())
var avgBlockSizeInBytes common.StorageSize
txCount := 0
@ -297,7 +297,7 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) {
func (node *Node) AddNewBlock(newBlock *types.Block) {
blockNum, err := node.blockchain.InsertChain([]*types.Block{newBlock})
node.blockchain.InsertNewShardState(newBlock, &node.CurrentStakes)
node.blockchain.StoreNewShardState(newBlock, &node.CurrentStakes)
if err != nil {
utils.GetLogInstance().Debug("Error adding new block to blockchain", "blockNum", blockNum, "Error", err)
} else {

@ -60,7 +60,7 @@ func (node *Node) WaitForConsensusReady(readySignal chan struct{}, stopChan chan
} else {
// add new shard state if it's epoch block
// TODO(minhdoan): only happens for beaconchain
node.addNewShardState(block)
node.addNewShardStateHash(block)
newBlock = block
break
}
@ -78,7 +78,7 @@ func (node *Node) WaitForConsensusReady(readySignal chan struct{}, stopChan chan
}()
}
func (node *Node) addNewShardState(block *types.Block) {
func (node *Node) addNewShardStateHash(block *types.Block) {
shardState := node.blockchain.GetNewShardState(block, &node.CurrentStakes)
if shardState != nil {
shardHash := shardState.Hash()

@ -8,3 +8,4 @@
127.0.0.1 9007 validator 0
127.0.0.1 9008 validator 0
127.0.0.1 9009 validator 0
127.0.0.1 19999 client 0

Loading…
Cancel
Save