@@ -45,7 +45,8 @@ import (
45
45
const (
46
46
// txChanSize is the size of channel listening to NewTxsEvent.
47
47
// The number is referenced from the size of tx pool.
48
- txChanSize = 4096
48
+ txChanSize = 256
49
+ voteChanSize = 4096
49
50
)
50
51
51
52
var (
@@ -79,12 +80,25 @@ type txPool interface {
79
80
SubscribeReannoTxsEvent (chan <- core.ReannoTxsEvent ) event.Subscription
80
81
}
81
82
83
+ // votePool defines the methods needed from a votes pool implementation to
84
+ // support all the operations needed by the Ethereum chain protocols.
85
+ type votePool interface {
86
+ PutVote (vote * types.VoteEnvelope ) error
87
+ Get (hash common.Hash ) * types.VoteEnvelope
88
+ GetVotes () types.VoteEnvelopes
89
+
90
+ // SubscribeNewVotesEvent should return an event subscription of
91
+ // NewVotesEvent and send events to the given channel.
92
+ SubscribeNewVotesEvent (chan <- core.NewVotesEvent ) event.Subscription
93
+ }
94
+
82
95
// handlerConfig is the collection of initialization parameters to create a full
83
96
// node network handler.
84
97
type handlerConfig struct {
85
98
Database ethdb.Database // Database for direct sync insertions
86
99
Chain * core.BlockChain // Blockchain to serve data from
87
100
TxPool txPool // Transaction pool to propagate from
101
+ VotePool votePool // Votes pool to propagate from
88
102
Network uint64 // Network identifier to adfvertise
89
103
Sync downloader.SyncMode // Whether to fast or full sync
90
104
DiffSync bool // Whether to diff sync
@@ -112,6 +126,7 @@ type handler struct {
112
126
113
127
database ethdb.Database
114
128
txpool txPool
129
+ votepool votePool
115
130
chain * core.BlockChain
116
131
maxPeers int
117
132
@@ -127,6 +142,8 @@ type handler struct {
127
142
reannoTxsCh chan core.ReannoTxsEvent
128
143
reannoTxsSub event.Subscription
129
144
minedBlockSub * event.TypeMuxSubscription
145
+ votesCh chan core.NewVotesEvent
146
+ votesSub event.Subscription
130
147
131
148
whitelist map [uint64 ]common.Hash
132
149
@@ -152,6 +169,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
152
169
eventMux : config .EventMux ,
153
170
database : config .Database ,
154
171
txpool : config .TxPool ,
172
+ votepool : config .VotePool ,
155
173
chain : config .Chain ,
156
174
peers : newPeerSet (),
157
175
whitelist : config .Whitelist ,
@@ -332,9 +350,10 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
332
350
}
333
351
h .chainSync .handlePeerEvent (peer )
334
352
335
- // Propagate existing transactions. new transactions appearing
353
+ // Propagate existing transactions and votes . new transactions and votes appearing
336
354
// after this will be sent via broadcasts.
337
355
h .syncTransactions (peer )
356
+ h .syncVotes (peer )
338
357
339
358
// If we have a trusted CHT, reject all peers below that (avoid fast sync eclipse)
340
359
if h .checkpointHash != (common.Hash {}) {
@@ -438,6 +457,12 @@ func (h *handler) Start(maxPeers int) {
438
457
h .txsSub = h .txpool .SubscribeNewTxsEvent (h .txsCh )
439
458
go h .txBroadcastLoop ()
440
459
460
+ // broadcast votes
461
+ h .wg .Add (1 )
462
+ h .votesCh = make (chan core.NewVotesEvent , voteChanSize )
463
+ h .votesSub = h .votepool .SubscribeNewVotesEvent (h .votesCh )
464
+ go h .voteBroadcastLoop ()
465
+
441
466
// announce local pending transactions again
442
467
h .wg .Add (1 )
443
468
h .reannoTxsCh = make (chan core.ReannoTxsEvent , txChanSize )
@@ -510,7 +535,7 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) {
510
535
log .Trace ("Propagated block" , "hash" , hash , "recipients" , len (transfer ), "duration" , common .PrettyDuration (time .Since (block .ReceivedAt )))
511
536
return
512
537
}
513
- // Otherwise if the block is indeed in out own chain, announce it
538
+ // Otherwise if the block is indeed in our own chain, announce it
514
539
if h .chain .HasBlock (hash , block .NumberU64 ()) {
515
540
for _ , peer := range peers {
516
541
peer .AsyncSendNewBlockHash (block )
@@ -580,6 +605,33 @@ func (h *handler) ReannounceTransactions(txs types.Transactions) {
580
605
"announce packs" , peersCount , "announced hashes" , peersCount * uint (len (hashes )))
581
606
}
582
607
608
+ // BroadcastVotes will propagate a batch of votes to all peers
609
+ // which are not known to already have the given vote.
610
+ func (h * handler ) BroadcastVotes (votes types.VoteEnvelopes ) {
611
+ var (
612
+ directCount int // Count of announcements made
613
+ directPeers int
614
+
615
+ voteset = make (map [* ethPeer ][]* types.VoteEnvelope ) // Set peer->hash to transfer directly
616
+ )
617
+
618
+ // Broadcast votes to a batch of peers not knowing about it
619
+ for _ , vote := range votes {
620
+ peers := h .peers .peersWithoutVote (vote .Hash ())
621
+ for _ , peer := range peers {
622
+ voteset [peer ] = append (voteset [peer ], vote )
623
+ }
624
+ }
625
+
626
+ for peer , _votes := range voteset {
627
+ directPeers ++
628
+ directCount += len (_votes )
629
+ peer .AsyncSendVotes (_votes )
630
+ }
631
+ log .Debug ("Vote broadcast" , "votes" , len (votes ),
632
+ "vote packs" , directPeers , "broadcast votes" , directCount )
633
+ }
634
+
583
635
// minedBroadcastLoop sends mined blocks to connected peers.
584
636
func (h * handler ) minedBroadcastLoop () {
585
637
defer h .wg .Done ()
@@ -617,3 +669,16 @@ func (h *handler) txReannounceLoop() {
617
669
}
618
670
}
619
671
}
672
+
673
+ // voteBroadcastLoop announces new transactions to connected peers.
674
+ func (h * handler ) voteBroadcastLoop () {
675
+ defer h .wg .Done ()
676
+ for {
677
+ select {
678
+ case event := <- h .votesCh :
679
+ h .BroadcastVotes (event .Votes )
680
+ case <- h .votesSub .Err ():
681
+ return
682
+ }
683
+ }
684
+ }
0 commit comments