|
|
|
@ -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,10 +86,13 @@ 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++ { |
|
|
|
|
// 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] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Reshard will first add new nodes into shards, then use cuckoo rule to reshard to get new shard state
|
|
|
|
|
func (ss *ShardingState) Reshard(newNodeList []types.NodeID, percent float64) { |
|
|
|
@ -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)) |
|
|
|
|