Skip to content

Commit 1d8dfe6

Browse files
authored
Broadcast vote power. (#4748)
* Broadcast vote power. * Moved `GetLastSigningPower` from private api to public. * Fix for view change sign power. * Rebased and fixed conflicts. * Fix for broadcasting consensus vote power.
1 parent 991d1a0 commit 1d8dfe6

16 files changed

+408
-197
lines changed

api/proto/message/harmonymessage.pb.go

Lines changed: 269 additions & 141 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/proto/message/harmonymessage.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum MessageType {
2929
DRAND_INIT = 10 [deprecated=true];
3030
DRAND_COMMIT = 11 [deprecated=true];
3131
LOTTERY_REQUEST = 12 [deprecated=true]; // it should be either ENTER or GETPLAYERS but it will be removed later.
32+
LAST_SIGN_POWER = 13;
3233
}
3334

3435
// This is universal message for all communication protocols.
@@ -47,6 +48,7 @@ message Message {
4748
ViewChangeRequest viewchange = 7;
4849
// Refactor this later after demo.
4950
LotteryRequest lottery_request = 8 [deprecated=true];
51+
LastSignPowerBroadcast last_sign_power = 9;
5052
}
5153
}
5254

@@ -116,3 +118,11 @@ message ViewChangeRequest {
116118
bytes m3_bitmap= 12;
117119
bytes prepared_block = 13;
118120
}
121+
122+
message LastSignPowerBroadcast {
123+
int64 prepare = 1;
124+
int64 commit = 2;
125+
int64 change = 3;
126+
bytes sender_pubkey = 4;
127+
uint32 shard_id = 5;
128+
}

consensus/consensus.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ type Consensus struct {
138138
// Both flags only for initialization state.
139139
start bool
140140
isInitialLeader bool
141+
142+
// value receives from
143+
lastKnownSignPower int64
144+
lastKnowViewChange int64
141145
}
142146

143147
// Blockchain returns the blockchain.
@@ -395,6 +399,18 @@ func (consensus *Consensus) InitConsensusWithValidators() (err error) {
395399
return nil
396400
}
397401

402+
func (consensus *Consensus) SetLastKnownSignPower(signPower, viewChange int64) {
403+
atomic.StoreInt64(&consensus.lastKnownSignPower, signPower)
404+
atomic.StoreInt64(&consensus.lastKnowViewChange, viewChange)
405+
}
406+
407+
func (consensus *Consensus) GetLastKnownSignPower() int64 {
408+
if consensus.IsViewChangingMode() {
409+
return atomic.LoadInt64(&consensus.lastKnowViewChange)
410+
}
411+
return atomic.LoadInt64(&consensus.lastKnownSignPower)
412+
}
413+
398414
type downloadAsync struct {
399415
}
400416

consensus/consensus_service.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/ethereum/go-ethereum/common"
99
bls_core "github.com/harmony-one/bls/ffi/go/bls"
10+
"github.com/harmony-one/harmony/api/proto"
1011
msg_pb "github.com/harmony-one/harmony/api/proto/message"
1112
consensus_engine "github.com/harmony-one/harmony/consensus/engine"
1213
"github.com/harmony-one/harmony/consensus/quorum"
@@ -17,8 +18,10 @@ import (
1718
bls_cosi "github.com/harmony-one/harmony/crypto/bls"
1819
"github.com/harmony-one/harmony/crypto/hash"
1920
"github.com/harmony-one/harmony/internal/chain"
21+
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
2022
"github.com/harmony-one/harmony/internal/utils"
2123
"github.com/harmony-one/harmony/multibls"
24+
"github.com/harmony-one/harmony/p2p"
2225
"github.com/harmony-one/harmony/shard"
2326
"github.com/harmony-one/harmony/shard/committee"
2427
"github.com/harmony-one/harmony/webhooks"
@@ -153,6 +156,53 @@ func (consensus *Consensus) updateBitmaps() {
153156

154157
}
155158

159+
func (consensus *Consensus) sendLastSignPower() {
160+
if consensus.isLeader() {
161+
k, err := consensus.getLeaderPrivateKey(consensus.getLeaderPubKey().Object)
162+
if err != nil {
163+
consensus.getLogger().Err(err).Msg("Leader not found in the committee")
164+
return
165+
}
166+
comm := getOrZero(consensus.decider.CurrentTotalPower(quorum.Commit))
167+
prep := getOrZero(consensus.decider.CurrentTotalPower(quorum.Prepare))
168+
view := consensus.decider.ComputeTotalPowerByMask(consensus.vc.GetViewIDBitmap(consensus.current.viewChangingID)).Int64()
169+
for view > 100 {
170+
view /= 10
171+
}
172+
msg := &msg_pb.Message{
173+
ServiceType: msg_pb.ServiceType_CONSENSUS,
174+
Type: msg_pb.MessageType_LAST_SIGN_POWER,
175+
Request: &msg_pb.Message_LastSignPower{
176+
LastSignPower: &msg_pb.LastSignPowerBroadcast{
177+
Prepare: prep,
178+
Commit: comm,
179+
Change: view,
180+
SenderPubkey: k.Pub.Bytes[:],
181+
ShardId: consensus.ShardID,
182+
},
183+
},
184+
}
185+
marshaledMessage, err := consensus.signAndMarshalConsensusMessage(msg, k.Pri)
186+
if err != nil {
187+
consensus.getLogger().Err(err).
188+
Msg("[constructNewViewMessage] failed to sign and marshal the new view message")
189+
return
190+
}
191+
if comm == 0 && prep == 0 && view == 0 {
192+
return
193+
}
194+
msgToSend := proto.ConstructConsensusMessage(marshaledMessage)
195+
if err := consensus.msgSender.SendWithoutRetry(
196+
[]nodeconfig.GroupID{
197+
nodeconfig.NewGroupIDByShardID(nodeconfig.ShardID(consensus.ShardID))},
198+
p2p.ConstructMessage(msgToSend),
199+
); err != nil {
200+
consensus.getLogger().Err(err).
201+
Msg("[LastSignPower] could not send out the ViewChange message")
202+
}
203+
}
204+
}
205+
156206
// ResetState resets the state of the consensus
157207
func (consensus *Consensus) resetState() {
158208
consensus.switchPhase("ResetState", FBFTAnnounce)

consensus/consensus_v2.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
vrf_bls "github.com/harmony-one/harmony/crypto/vrf/bls"
2121
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
2222
"github.com/harmony-one/harmony/internal/utils"
23+
"github.com/harmony-one/harmony/numeric"
2324
"github.com/harmony-one/harmony/p2p"
2425
"github.com/harmony-one/harmony/shard"
2526
"github.com/harmony-one/vdf/src/vdf_go"
@@ -89,6 +90,8 @@ func (consensus *Consensus) HandleMessageUpdate(ctx context.Context, peer libp2p
8990
case t == msg_pb.MessageType_NEWVIEW:
9091
members := consensus.decider.Participants()
9192
fbftMsg, err = ParseNewViewMessage(msg, members)
93+
case t == msg_pb.MessageType_LAST_SIGN_POWER:
94+
return nil
9295
default:
9396
fbftMsg, err = consensus.parseFBFTMessage(msg)
9497
}
@@ -820,6 +823,7 @@ func (consensus *Consensus) setupForNewConsensus(blk *types.Block, committedMsg
820823
}
821824
consensus.fBFTLog.PruneCacheBeforeBlock(blk.NumberU64())
822825
consensus.resetState()
826+
consensus.sendLastSignPower()
823827
}
824828

825829
func (consensus *Consensus) postCatchup(initBN uint64) {
@@ -968,3 +972,10 @@ func (consensus *Consensus) DeleteMessagesLessThan(number uint64) {
968972
defer consensus.mutex.Unlock()
969973
consensus.fBFTLog.deleteMessagesLessThan(number)
970974
}
975+
976+
func getOrZero(n *numeric.Dec, err error) int64 {
977+
if n == nil {
978+
return 0
979+
}
980+
return (*n).Mul(numeric.NewDec(100)).TruncateInt64()
981+
}

consensus/fbft_log.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type FBFTMessage struct {
3636
M3AggSig *bls_core.Sign
3737
M3Bitmap *bls_cosi.Mask
3838
Verified bool
39+
LastVotePower int64
3940
}
4041

4142
func (m *FBFTMessage) Hash() []byte {

consensus/quorum/one-node-one-vote.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ func (v *uniformVoteWeight) IsQuorumAchievedByMask(mask *bls_cosi.Mask) bool {
7171
return true
7272
}
7373

74+
func (v *uniformVoteWeight) ComputeTotalPowerByMask(mask *bls_cosi.Mask) numeric.Dec {
75+
if mask == nil {
76+
return numeric.ZeroDec()
77+
}
78+
currentTotalPower := utils.CountOneBits(mask.Bitmap)
79+
return numeric.NewDec(currentTotalPower)
80+
}
81+
7482
// QuorumThreshold ..
7583
func (v *uniformVoteWeight) QuorumThreshold() numeric.Dec {
7684
return numeric.NewDec(v.TwoThirdsSignersCount())

consensus/quorum/one-node-staked-vote.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ func (v *stakedVoteWeight) IsQuorumAchievedByMask(mask *bls_cosi.Mask) bool {
163163
return (*currentTotalPower).GT(threshold)
164164
}
165165

166+
func (v *stakedVoteWeight) ComputeTotalPowerByMask(mask *bls_cosi.Mask) numeric.Dec {
167+
if mask == nil {
168+
return numeric.ZeroDec()
169+
}
170+
currentTotalPower := v.computeTotalPowerByMask(mask)
171+
return *currentTotalPower
172+
}
173+
166174
// ComputeTotalPowerByMask computes the total power indicated by bitmap mask
167175
func (v *stakedVoteWeight) computeTotalPowerByMask(mask *bls_cosi.Mask) *numeric.Dec {
168176
currentTotal := numeric.ZeroDec()

consensus/quorum/quorum.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ type Decider interface {
118118
) (*votepower.Ballot, error)
119119
IsQuorumAchieved(Phase) bool
120120
IsQuorumAchievedByMask(mask *bls_cosi.Mask) bool
121+
ComputeTotalPowerByMask(mask *bls_cosi.Mask) numeric.Dec
121122
QuorumThreshold() numeric.Dec
122123
IsAllSigsCollected() bool
123124
ResetPrepareAndCommitVotes()

consensus/quorum/thread_safe_decider.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,9 @@ func (a threadSafeDeciderImpl) IsQuorumAchieved(p Phase) bool {
169169
defer a.mu.Unlock()
170170
return a.decider.IsQuorumAchieved(p)
171171
}
172+
173+
func (a threadSafeDeciderImpl) ComputeTotalPowerByMask(mask *bls.Mask) numeric.Dec {
174+
a.mu.Lock()
175+
defer a.mu.Unlock()
176+
return a.decider.ComputeTotalPowerByMask(mask)
177+
}

consensus/view_change.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ func (consensus *Consensus) onViewChange(recvMsg *FBFTMessage) {
424424
Msg("[onViewChange] process View Change message error")
425425
return
426426
}
427+
consensus.sendLastSignPower()
427428

428429
// received enough view change messages, change state to normal consensus
429430
if consensus.decider.IsQuorumAchievedByMask(consensus.vc.GetViewIDBitmap(recvMsg.ViewID)) && consensus.isViewChangingMode() {

hmy/hmy.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ type NodeAPI interface {
120120
GetConfig() commonRPC.Config
121121
ShutDown()
122122
GetLastSigningPower() (float64, error)
123-
GetLastSigningPower2() (float64, error)
124123
}
125124

126125
// New creates a new Harmony object (including the

node/harmony/api.go

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package node
22

33
import (
4-
"github.com/harmony-one/harmony/consensus/quorum"
5-
"github.com/harmony-one/harmony/consensus/votepower"
64
"github.com/harmony-one/harmony/core/types"
7-
"github.com/harmony-one/harmony/crypto/bls"
85
"github.com/harmony-one/harmony/eth/rpc"
96
"github.com/harmony-one/harmony/hmy"
107
"github.com/harmony-one/harmony/internal/tikv"
@@ -171,37 +168,7 @@ func (node *Node) GetConfig() rpc_common.Config {
171168

172169
// GetLastSigningPower get last signed power
173170
func (node *Node) GetLastSigningPower() (float64, error) {
174-
power, err := node.Consensus.Decider().CurrentTotalPower(quorum.Commit)
175-
if err != nil {
176-
return 0, err
177-
}
178-
179-
round := float64(power.MulInt64(10000).RoundInt64()) / 10000
180-
return round, nil
181-
}
182-
183-
func (node *Node) GetLastSigningPower2() (float64, error) {
184-
bc := node.Consensus.Blockchain()
185-
cur := bc.CurrentBlock()
186-
ss, err := bc.ReadShardState(cur.Epoch())
187-
if err != nil {
188-
return 0, err
189-
}
190-
roster, err := votepower.Compute(&ss.Shards[bc.ShardID()], cur.Epoch())
191-
if err != nil {
192-
return 0, err
193-
}
194-
blsPubKeys, err := ss.Shards[bc.ShardID()].BLSPublicKeys()
195-
if err != nil {
196-
return 0, err
197-
}
198-
199-
mask := bls.NewMask(blsPubKeys)
200-
err = mask.SetMask(cur.Header().LastCommitBitmap())
201-
if err != nil {
202-
return 0, err
203-
}
204-
power := roster.VotePowerByMask(mask)
205-
round := float64(power.MulInt64(10000).RoundInt64()) / 10000
171+
p := node.Consensus.GetLastKnownSignPower()
172+
round := float64(p) / 100
206173
return round, nil
207174
}

node/harmony/node.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,16 @@ func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer.
528528
}
529529
}
530530

531-
maybeCon, maybeVC := m.GetConsensus(), m.GetViewchange()
532-
senderKey := []byte{}
533-
senderBitmap := []byte{}
531+
var (
532+
maybeCon = m.GetConsensus()
533+
maybeVC = m.GetViewchange()
534+
maybeSP = m.GetLastSignPower()
535+
senderKey []byte
536+
senderBitmap []byte
537+
)
534538

535-
if maybeCon != nil {
539+
switch {
540+
case maybeCon != nil:
536541
if maybeCon.ShardId != consensus.ShardID {
537542
nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid_shard"}).Inc()
538543
return nil, nil, true, errors.WithStack(errWrongShardID)
@@ -546,7 +551,7 @@ func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer.
546551
if maybeCon.ViewId+5 < consensus.GetCurBlockViewID() {
547552
return nil, nil, true, errors.WithStack(errViewIDTooOld)
548553
}
549-
} else if maybeVC != nil {
554+
case maybeVC != nil:
550555
if maybeVC.ShardId != consensus.ShardID {
551556
nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid_shard"}).Inc()
552557
return nil, nil, true, errors.WithStack(errWrongShardID)
@@ -556,7 +561,14 @@ func validateShardBoundMessage(consensus *consensus.Consensus, peer libp2p_peer.
556561
if maybeVC.ViewId+5 < consensus.GetViewChangingID() {
557562
return nil, nil, true, errors.WithStack(errViewIDTooOld)
558563
}
559-
} else {
564+
case maybeSP != nil:
565+
if maybeSP.ShardId != consensus.ShardID {
566+
nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid_shard"}).Inc()
567+
return nil, nil, true, errors.WithStack(errWrongShardID)
568+
}
569+
senderKey = maybeSP.SenderPubkey
570+
consensus.SetLastKnownSignPower(maybeSP.Commit, maybeSP.Change)
571+
default:
560572
nodeConsensusMessageCounterVec.With(prometheus.Labels{"type": "invalid"}).Inc()
561573
return nil, nil, true, errors.WithStack(errNoSenderPubKey)
562574
}

rpc/harmony/private_debug.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,3 @@ func (s *PrivateDebugService) GetConfig(
5858
) (StructuredResponse, error) {
5959
return NewStructuredResponse(s.hmy.NodeAPI.GetConfig())
6060
}
61-
62-
// GetLastSigningPower get last signed power
63-
func (s *PrivateDebugService) GetLastSigningPower(
64-
ctx context.Context,
65-
) (float64, error) {
66-
return s.hmy.NodeAPI.GetLastSigningPower()
67-
}
68-
69-
// GetLastSigningPower2 get last signed power
70-
func (s *PrivateDebugService) GetLastSigningPower2(
71-
ctx context.Context,
72-
) (float64, error) {
73-
return s.hmy.NodeAPI.GetLastSigningPower2()
74-
}

rpc/harmony/public_debug.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,10 @@ func (s *PublicDebugService) SetLogVerbosity(ctx context.Context, level int) (ma
3636
utils.SetLogVerbosity(verbosity)
3737
return map[string]interface{}{"verbosity": verbosity.String()}, nil
3838
}
39+
40+
// GetLastSigningPower get last signed power
41+
func (s *PublicDebugService) GetLastSigningPower(
42+
ctx context.Context,
43+
) (float64, error) {
44+
return s.hmy.NodeAPI.GetLastSigningPower()
45+
}

0 commit comments

Comments
 (0)