-
Notifications
You must be signed in to change notification settings - Fork 368
Expand file tree
/
Copy pathcatchup.go
More file actions
112 lines (92 loc) · 2.99 KB
/
Copy pathcatchup.go
File metadata and controls
112 lines (92 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package propagation
import (
"math/rand"
proptypes "github.com/tendermint/tendermint/consensus/propagation/types"
"github.com/tendermint/tendermint/libs/bits"
"github.com/tendermint/tendermint/p2p"
protoprop "github.com/tendermint/tendermint/proto/tendermint/propagation"
"github.com/tendermint/tendermint/types"
)
// retryWants ensure that all data for all unpruned compact blocks is requested.
//
// todo: add a request limit for each part to avoid downloading the block too
// many times. atm, this code will request the same part from every peer.
func (blockProp *Reactor) retryWants(currentHeight int64, currentRound int32) {
data := blockProp.dumpAll()
peers := blockProp.getPeers()
for _, prop := range data {
height, round := prop.compactBlock.Proposal.Height, prop.compactBlock.Proposal.Round
if height == currentHeight && round == currentRound {
continue
}
if prop.block.IsComplete() {
continue
}
// only re-request original parts that are missing, not parity parts.
missing := prop.block.MissingOriginal()
if missing.IsEmpty() {
blockProp.Logger.Error("no missing parts yet block is incomplete", "height", height, "round", round)
continue
}
// make requests from different peers
peers = shuffle(peers)
for _, peer := range peers {
mc := missing.Copy()
reqs, has := peer.GetRequests(height, round)
if has {
mc = mc.Sub(reqs)
}
if mc.IsEmpty() {
continue
}
e := p2p.Envelope{
ChannelID: WantChannel,
Message: &protoprop.WantParts{
Parts: *mc.ToProto(),
Height: height,
Round: round,
Prove: true,
},
}
if !p2p.TrySendEnvelopeShim(peer.peer, e, blockProp.Logger) { //nolint:staticcheck
blockProp.Logger.Error("failed to send want part", "peer", peer, "height", height, "round", round)
continue
}
// keep track of which requests we've made this attempt.
missing.Sub(mc)
peer.AddRequests(height, round, missing)
}
}
}
func (blockProp *Reactor) AddCommitment(height int64, round int32, psh *types.PartSetHeader) {
blockProp.Logger.Info("adding commitment", "height", height, "round", round, "psh", psh)
blockProp.pmtx.Lock()
defer blockProp.pmtx.Unlock()
blockProp.Logger.Info("added commitment", "height", height, "round", round)
if blockProp.proposals[height] == nil {
blockProp.proposals[height] = make(map[int32]*proposalData)
}
combinedSet := proptypes.NewCombinedPartSetFromOriginal(types.NewPartSetFromHeader(*psh), true)
if blockProp.proposals[height][round] != nil {
return
}
blockProp.proposals[height][round] = &proposalData{
compactBlock: &proptypes.CompactBlock{
Proposal: types.Proposal{
Height: height,
Round: round,
},
},
catchup: true,
block: combinedSet,
maxRequests: bits.NewBitArray(int(psh.Total * 2)), // this assumes that the parity parts are the same size
}
}
func shuffle[T any](slice []T) []T {
n := len(slice)
for i := n - 1; i > 0; i-- {
j := rand.Intn(i + 1)
slice[i], slice[j] = slice[j], slice[i]
}
return slice
}