Make ShardState comparable (recursively)

Rename existing CompareNodeID as CompareNodeIDByBLSKey to better reflect
what it does and to make room for the full node ID compare function.
pull/874/head
Eugene Kim 6 years ago
parent 828f2d0f41
commit efc57c47ed
  1. 2
      core/resharding.go
  2. 80
      core/types/shard_state.go

@ -131,7 +131,7 @@ func (ss *ShardingState) Reshard(newNodeList []types.NodeID, percent float64) {
func Shuffle(list []types.NodeID) {
// Sort to make sure everyone will generate the same with the same rand seed.
sort.Slice(list, func(i, j int) bool {
return types.CompareNodeID(list[i], list[j]) == -1
return types.CompareNodeIDByBLSKey(list[i], list[j]) == -1
})
rand.Shuffle(len(list), func(i, j int) {
list[i], list[j] = list[j], list[i]

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/hex"
"sort"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls"
@ -21,6 +22,26 @@ type EpochShardState struct {
// ShardState is the collection of all committees
type ShardState []Committee
// CompareShardState compares two ShardState instances.
func CompareShardState(s1, s2 ShardState) int {
commonLen := len(s1)
if commonLen > len(s2) {
commonLen = len(s2)
}
for idx := 0; idx < commonLen; idx++ {
if c := CompareCommittee(&s1[idx], &s2[idx]); c != 0 {
return c
}
}
switch {
case len(s1) < len(s2):
return -1
case len(s1) > len(s2):
return +1
}
return 0
}
// BlsPublicKey defines the bls public key
type BlsPublicKey [96]byte
@ -46,15 +67,51 @@ func (pk *BlsPublicKey) ToLibBLSPublicKey(key *bls.PublicKey) error {
return key.Deserialize(pk[:])
}
// CompareBlsPublicKey compares two BlsPublicKey, lexicographically.
func CompareBlsPublicKey(k1, k2 BlsPublicKey) int {
return bytes.Compare(k1[:], k2[:])
}
// NodeID represents node id (BLS address).
type NodeID struct {
EcdsaAddress string
BlsPublicKey BlsPublicKey
}
// CompareNodeID compares two node IDs.
func CompareNodeID(id1, id2 *NodeID) int {
if c := strings.Compare(id1.EcdsaAddress, id2.EcdsaAddress); c != 0 {
return c
}
if c := CompareBlsPublicKey(id1.BlsPublicKey, id2.BlsPublicKey); c != 0 {
return c
}
return 0
}
// NodeIDList is a list of NodeIDList.
type NodeIDList []NodeID
// CompareNodeIDList compares two node ID lists.
func CompareNodeIDList(l1, l2 NodeIDList) int {
commonLen := len(l1)
if commonLen > len(l2) {
commonLen = len(l2)
}
for idx := 0; idx < commonLen; idx++ {
if c := CompareNodeID(&l1[idx], &l2[idx]); c != 0 {
return c
}
}
switch {
case len(l1) < len(l2):
return -1
case len(l1) > len(l2):
return +1
}
return 0
}
// Committee contains the active nodes in one shard
type Committee struct {
ShardID uint32
@ -62,6 +119,23 @@ type Committee struct {
NodeList NodeIDList
}
// CompareCommittee compares two committees and their leader/node list.
func CompareCommittee(c1, c2 *Committee) int {
switch {
case c1.ShardID < c2.ShardID:
return -1
case c1.ShardID > c2.ShardID:
return +1
}
if c := CompareNodeID(&c1.Leader, &c2.Leader); c != 0 {
return c
}
if c := CompareNodeIDList(c1.NodeList, c2.NodeList); c != 0 {
return c
}
return 0
}
// GetHashFromNodeList will sort the list, then use Keccak256 to hash the list
// notice that the input nodeList will be modified (sorted)
func GetHashFromNodeList(nodeList []NodeID) []byte {
@ -71,7 +145,7 @@ func GetHashFromNodeList(nodeList []NodeID) []byte {
}
sort.Slice(nodeList, func(i, j int) bool {
return CompareNodeID(nodeList[i], nodeList[j]) == -1
return CompareNodeIDByBLSKey(nodeList[i], nodeList[j]) == -1
})
d := sha3.NewLegacyKeccak256()
for i := range nodeList {
@ -94,8 +168,8 @@ func (ss ShardState) Hash() (h common.Hash) {
return h
}
// CompareNodeID compares two nodes by their ID; used to sort node list
func CompareNodeID(n1 NodeID, n2 NodeID) int {
// CompareNodeIDByBLSKey compares two nodes by their ID; used to sort node list
func CompareNodeIDByBLSKey(n1 NodeID, n2 NodeID) int {
return bytes.Compare(n1.BlsPublicKey[:], n2.BlsPublicKey[:])
}

Loading…
Cancel
Save