[rpc][quorum] Expose SuperCommittee network wide RPC (#2273)

pull/2284/head
Edgar Aroutiounian 5 years ago committed by GitHub
parent f117201ce4
commit e9b45171ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      consensus/consensus_service.go
  2. 16
      consensus/quorum/one-node-one-vote.go
  3. 24
      consensus/quorum/one-node-staked-vote.go
  4. 4
      consensus/quorum/one-node-staked-vote_test.go
  5. 25
      consensus/quorum/quorum.go
  6. 41
      hmy/api_backend.go
  7. 4
      internal/chain/engine.go
  8. 2
      internal/hmyapi/apiv1/backend.go
  9. 9
      internal/hmyapi/apiv1/blockchain.go
  10. 2
      internal/hmyapi/apiv2/backend.go
  11. 9
      internal/hmyapi/apiv2/blockchain.go
  12. 2
      internal/hmyapi/backend.go
  13. 2
      node/node_cross_link.go
  14. 2
      shard/committee/assignment.go
  15. 13
      shard/shard_state.go
  16. 4
      shard/shard_state_test.go

@ -474,7 +474,7 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
curHeader := consensus.ChainReader.CurrentHeader()
curEpoch := curHeader.Epoch()
nextEpoch := new(big.Int).Add(curHeader.Epoch(), common.Big1)
prevSubCommitteeDump := consensus.Decider.JSON()
prevSubCommitteeDump := consensus.Decider.String()
isFirstTimeStaking := consensus.ChainReader.Config().IsStaking(nextEpoch) &&
len(curHeader.ShardState()) > 0 &&
@ -552,7 +552,7 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
// Update voters in the committee
if _, err := consensus.Decider.SetVoters(
committeeToSet.Slots, true,
committeeToSet.Slots,
); err != nil {
utils.Logger().Error().
Err(err).
@ -566,7 +566,7 @@ func (consensus *Consensus) UpdateConsensusInformation() Mode {
Uint64("curEpoch", curHeader.Epoch().Uint64()).
Uint32("shard-id", consensus.ShardID).
RawJSON("prev-subcommittee", []byte(prevSubCommitteeDump)).
RawJSON("current-subcommittee", []byte(consensus.Decider.JSON())).
RawJSON("current-subcommittee", []byte(consensus.Decider.String())).
Msg("[UpdateConsensusInformation] changing committee")
// take care of possible leader change during the curEpoch

@ -59,9 +59,7 @@ func (v *uniformVoteWeight) IsRewardThresholdAchieved() bool {
return v.SignersCount(Commit) >= (v.ParticipantsCount() * 9 / 10)
}
func (v *uniformVoteWeight) SetVoters(
shard.SlotList, bool,
) (*TallyResult, error) {
func (v *uniformVoteWeight) SetVoters(shard.SlotList) (*TallyResult, error) {
// NO-OP do not add anything here
return nil, nil
}
@ -96,19 +94,23 @@ func (v *uniformVoteWeight) Award(
return payout
}
func (v *uniformVoteWeight) JSON() string {
func (v *uniformVoteWeight) String() string {
s, _ := json.Marshal(v)
return string(s)
}
func (v *uniformVoteWeight) MarshalJSON() ([]byte, error) {
s, _ := v.ShardIDProvider()()
type t struct {
Policy string `json"policy"`
Policy string `json:"policy"`
ShardID uint32 `json:"shard-id"`
Count int `json:"count"`
Participants []string `json:"committee-members"`
}
members := v.DumpParticipants()
b1, _ := json.Marshal(t{v.Policy().String(), s, len(members), members})
return string(b1)
return json.Marshal(t{v.Policy().String(), s, len(members), members})
}
func (v *uniformVoteWeight) AmIMemberOfCommitee() bool {

@ -169,10 +169,7 @@ var (
)
)
func (v *stakedVoteWeight) SetVoters(
staked shard.SlotList, debug bool,
) (*TallyResult, error) {
s, _ := v.ShardIDProvider()()
func (v *stakedVoteWeight) SetVoters(staked shard.SlotList) (*TallyResult, error) {
v.ResetPrepareAndCommitVotes()
v.ResetViewChangeVotes()
@ -180,15 +177,6 @@ func (v *stakedVoteWeight) SetVoters(
if err != nil {
return nil, err
}
if debug {
utils.Logger().Info().
Str("our-percentage", roster.OurVotingPowerTotalPercentage.String()).
Str("their-percentage", roster.TheirVotingPowerTotalPercentage.String()).
Uint32("on-shard", s).
Str("Raw-Staked", roster.RawStakedTotal.String()).
Msg("Total staked")
}
// Hold onto this calculation
v.roster = *roster
return &TallyResult{
@ -205,7 +193,12 @@ func (v *stakedVoteWeight) ToggleActive(k *bls.PublicKey) bool {
return v.roster.Voters[w].IsActive
}
func (v *stakedVoteWeight) JSON() string {
func (v *stakedVoteWeight) String() string {
s, _ := json.Marshal(v)
return string(s)
}
func (v *stakedVoteWeight) MarshalJSON() ([]byte, error) {
s, _ := v.ShardIDProvider()()
voterCount := len(v.roster.Voters)
type u struct {
@ -242,7 +235,7 @@ func (v *stakedVoteWeight) JSON() string {
i++
}
b1, _ := json.Marshal(t{
return json.Marshal(t{
v.Policy().String(),
s,
voterCount,
@ -251,7 +244,6 @@ func (v *stakedVoteWeight) JSON() string {
v.roster.TheirVotingPowerTotalPercentage.String(),
v.roster.RawStakedTotal.String(),
})
return string(b1)
}
func (v *stakedVoteWeight) AmIMemberOfCommitee() bool {

@ -66,7 +66,7 @@ func setupBaseCase() (Decider, *TallyResult, shard.SlotList, map[string]secretKe
decider := NewDecider(SuperMajorityStake)
decider.SetShardIDProvider(func() (uint32, error) { return 0, nil })
decider.UpdateParticipants(pubKeys)
tally, err := decider.SetVoters(slotList, false)
tally, err := decider.SetVoters(slotList)
if err != nil {
panic("Unable to SetVoters for Base Case")
}
@ -92,7 +92,7 @@ func setupEdgeCase() (Decider, *TallyResult, shard.SlotList, secretKeyMap) {
decider := NewDecider(SuperMajorityStake)
decider.SetShardIDProvider(func() (uint32, error) { return 0, nil })
decider.UpdateParticipants(pubKeys)
tally, err := decider.SetVoters(slotList, false)
tally, err := decider.SetVoters(slotList)
if err != nil {
panic("Unable to SetVoters for Edge Case")
}

@ -103,18 +103,13 @@ type DependencyInjectionReader interface {
MyPublicKey() func() (*bls.PublicKey, error)
}
//WithJSONDump representation dump
type WithJSONDump interface {
JSON() string
}
// Decider ..
type Decider interface {
fmt.Stringer
SignatureReader
DependencyInjectionWriter
WithJSONDump
ToggleActive(*bls.PublicKey) bool
SetVoters(shard.SlotList, bool) (*TallyResult, error)
SetVoters(shard.SlotList) (*TallyResult, error)
Policy() Policy
IsQuorumAchieved(Phase) bool
IsQuorumAchievedByMask(mask *bls_cosi.Mask, debug bool) bool
@ -125,6 +120,22 @@ type Decider interface {
ResetViewChangeVotes()
}
// Registry ..
type Registry struct {
Deciders map[uint32]Decider
}
// NewRegistry ..
func NewRegistry() Registry {
return Registry{map[uint32]Decider{}}
}
// Transition ..
type Transition struct {
Previous Registry `json:"previous"`
Current Registry `json:"current"`
}
// These maps represent the signatories (validators), keys are BLS public keys
// and values are BLS private key signed signatures
type cIdentities struct {

@ -16,6 +16,7 @@ import (
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/api/proto"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -453,3 +454,43 @@ func (b *APIBackend) GetPendingCXReceipts() []*types.CXReceiptsProof {
func (b *APIBackend) GetCurrentUtilityMetrics() (*network.UtilityMetric, error) {
return network.NewUtilityMetricSnapshot(b.hmy.BlockChain())
}
// GetSuperCommittees ..
func (b *APIBackend) GetSuperCommittees() (*quorum.Transition, error) {
nowE := b.hmy.BlockChain().CurrentHeader().Epoch()
var (
nowCommittee, prevCommittee *shard.State
err error
)
nowCommittee, err = b.hmy.BlockChain().ReadShardState(nowE)
if err != nil {
return nil, err
}
prevCommittee, err = b.hmy.BlockChain().ReadShardState(
new(big.Int).Sub(nowE, common.Big1),
)
if err != nil {
return nil, err
}
then, now := quorum.NewRegistry(), quorum.NewRegistry()
for _, comm := range prevCommittee.Shards {
decider := quorum.NewDecider(quorum.SuperMajorityStake)
decider.SetShardIDProvider(func() (uint32, error) {
return comm.ShardID, nil
})
decider.SetVoters(comm.Slots)
then.Deciders[comm.ShardID] = decider
}
for _, comm := range nowCommittee.Shards {
decider := quorum.NewDecider(quorum.SuperMajorityStake)
decider.SetShardIDProvider(func() (uint32, error) {
return comm.ShardID, nil
})
decider.SetVoters(comm.Slots)
now.Deciders[comm.ShardID] = decider
}
return &quorum.Transition{then, now}, nil
}

@ -216,7 +216,7 @@ func (e *engineImpl) VerifySeal(chain engine.ChainReader, header *block.Header)
d.SetMyPublicKeyProvider(func() (*bls.PublicKey, error) {
return nil, nil
})
d.SetVoters(slotList.FindCommitteeByID(parentHeader.ShardID()).Slots, true)
d.SetVoters(slotList.FindCommitteeByID(parentHeader.ShardID()).Slots)
if !d.IsQuorumAchievedByMask(mask, true) {
return ctxerror.New(
"[VerifySeal] Not enough voting power in LastCommitSignature from Block Header",
@ -382,7 +382,7 @@ func (e *engineImpl) VerifyHeaderWithSignature(chain engine.ChainReader, header
d.SetMyPublicKeyProvider(func() (*bls.PublicKey, error) {
return nil, nil
})
d.SetVoters(slotList.FindCommitteeByID(header.ShardID()).Slots, true)
d.SetVoters(slotList.FindCommitteeByID(header.ShardID()).Slots)
if !d.IsQuorumAchievedByMask(mask, true) {
return ctxerror.New(
"[VerifySeal] Not enough voting power in commitSignature from Block Header",

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -83,4 +84,5 @@ type Backend interface {
GetMedianRawStakeSnapshot() *big.Int
GetPendingCXReceipts() []*types.CXReceiptsProof
GetCurrentUtilityMetrics() (*network.UtilityMetric, error)
GetSuperCommittees() (*quorum.Transition, error)
}

@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
@ -740,3 +741,11 @@ func (s *PublicBlockChainAPI) GetCurrentUtilityMetrics() (*network.UtilityMetric
}
return nil, errNotBeaconChainShard
}
// GetSuperCommittees ..
func (s *PublicBlockChainAPI) GetSuperCommittees() (*quorum.Transition, error) {
if s.b.GetShardID() == shard.BeaconChainShardID {
return s.b.GetSuperCommittees()
}
return nil, errNotBeaconChainShard
}

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -83,4 +84,5 @@ type Backend interface {
GetMedianRawStakeSnapshot() *big.Int
GetPendingCXReceipts() []*types.CXReceiptsProof
GetCurrentUtilityMetrics() (*network.UtilityMetric, error)
GetSuperCommittees() (*quorum.Transition, error)
}

@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/common/denominations"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/types"
"github.com/harmony-one/harmony/core/vm"
@ -705,3 +706,11 @@ func (s *PublicBlockChainAPI) GetCurrentUtilityMetrics() (*network.UtilityMetric
}
return nil, errNotBeaconChainShard
}
// GetSuperCommittees ..
func (s *PublicBlockChainAPI) GetSuperCommittees() (*quorum.Transition, error) {
if s.b.GetShardID() == shard.BeaconChainShardID {
return s.b.GetSuperCommittees()
}
return nil, errNotBeaconChainShard
}

@ -10,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
"github.com/harmony-one/harmony/accounts"
"github.com/harmony-one/harmony/block"
"github.com/harmony-one/harmony/consensus/quorum"
"github.com/harmony-one/harmony/core"
"github.com/harmony-one/harmony/core/state"
"github.com/harmony-one/harmony/core/types"
@ -85,6 +86,7 @@ type Backend interface {
GetMedianRawStakeSnapshot() *big.Int
GetPendingCXReceipts() []*types.CXReceiptsProof
GetCurrentUtilityMetrics() (*network.UtilityMetric, error)
GetSuperCommittees() (*quorum.Transition, error)
}
// GetAPIs returns all the APIs.

@ -164,7 +164,7 @@ func (node *Node) VerifyCrossLink(cl types.CrossLink) error {
decider.SetMyPublicKeyProvider(func() (*bls.PublicKey, error) {
return nil, nil
})
if _, err := decider.SetVoters(committee.Slots, false); err != nil {
if _, err := decider.SetVoters(committee.Slots); err != nil {
return ctxerror.New("[VerifyCrossLink] Cannot SetVoters for committee", "shardID", cl.ShardID())
}
if !decider.IsQuorumAchievedByMask(mask, false) {

@ -214,7 +214,7 @@ func eposStakedCommittee(
if c := len(candidates); c != 0 {
utils.Logger().Info().Int("staked-candidates", c).
Str("total-staked-by-validators", totalStake.String()).
RawJSON("staked-super-committee", []byte(shardState.JSON())).
RawJSON("staked-super-committee", []byte(shardState.String())).
Msg("EPoS based super-committe")
}

@ -160,8 +160,14 @@ func (ss *State) ExternalValidators() []common.Address {
return slice
}
// JSON produces a non-pretty printed JSON string of the SuperCommittee
func (ss *State) JSON() string {
// String ..
func (ss *State) String() string {
s, _ := json.Marshal(ss)
return string(s)
}
// MarshalJSON ..
func (ss *State) MarshalJSON() ([]byte, error) {
type t struct {
Slot
EcdsaAddress string `json:"ecdsa-address"`
@ -184,8 +190,7 @@ func (ss *State) JSON() string {
dump[i].NodeList[j].EcdsaAddress = common2.MustAddressToBech32(n.EcdsaAddress)
}
}
buf, _ := json.Marshal(dump)
return string(buf)
return json.Marshal(dump)
}
// FindCommitteeByID returns the committee configuration for the given shard,

@ -151,11 +151,11 @@ func TestCompatibilityOldShardStateIntoNew(t *testing.T) {
t.Errorf("Could not decode new format")
}
if a.JSON() != json1 {
if a.String() != json1 {
t.Error("old shard state into new shard state as JSON is not equal")
}
if b.JSON() != json2 {
if b.String() != json2 {
t.Error("new shard state into new shard state as JSON is not equal")
}

Loading…
Cancel
Save