fix bitArray nil bugs
This commit is contained in:
parent
ba17961269
commit
6020223e85
|
@ -21,14 +21,19 @@ func NewBitArray(bits uint) *BitArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) Size() uint {
|
func (bA *BitArray) Size() uint {
|
||||||
|
if bA == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
return bA.Bits
|
return bA.Bits
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: behavior is undefined if i >= bA.Bits
|
// NOTE: behavior is undefined if i >= bA.Bits
|
||||||
func (bA *BitArray) GetIndex(i uint) bool {
|
func (bA *BitArray) GetIndex(i uint) bool {
|
||||||
|
if bA == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
return bA.getIndex(i)
|
return bA.getIndex(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +46,11 @@ func (bA *BitArray) getIndex(i uint) bool {
|
||||||
|
|
||||||
// NOTE: behavior is undefined if i >= bA.Bits
|
// NOTE: behavior is undefined if i >= bA.Bits
|
||||||
func (bA *BitArray) SetIndex(i uint, v bool) bool {
|
func (bA *BitArray) SetIndex(i uint, v bool) bool {
|
||||||
|
if bA == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
return bA.setIndex(i, v)
|
return bA.setIndex(i, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +67,9 @@ func (bA *BitArray) setIndex(i uint, v bool) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) Copy() *BitArray {
|
func (bA *BitArray) Copy() *BitArray {
|
||||||
|
if bA == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
return bA.copy()
|
return bA.copy()
|
||||||
|
@ -85,9 +95,11 @@ func (bA *BitArray) copyBits(bits uint) *BitArray {
|
||||||
|
|
||||||
// Returns a BitArray of larger bits size.
|
// Returns a BitArray of larger bits size.
|
||||||
func (bA *BitArray) Or(o *BitArray) *BitArray {
|
func (bA *BitArray) Or(o *BitArray) *BitArray {
|
||||||
|
if bA == nil {
|
||||||
|
o.Copy()
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
c := bA.copyBits(MaxUint(bA.Bits, o.Bits))
|
c := bA.copyBits(MaxUint(bA.Bits, o.Bits))
|
||||||
for i := 0; i < len(c.Elems); i++ {
|
for i := 0; i < len(c.Elems); i++ {
|
||||||
c.Elems[i] |= o.Elems[i]
|
c.Elems[i] |= o.Elems[i]
|
||||||
|
@ -97,9 +109,11 @@ func (bA *BitArray) Or(o *BitArray) *BitArray {
|
||||||
|
|
||||||
// Returns a BitArray of smaller bit size.
|
// Returns a BitArray of smaller bit size.
|
||||||
func (bA *BitArray) And(o *BitArray) *BitArray {
|
func (bA *BitArray) And(o *BitArray) *BitArray {
|
||||||
|
if bA == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
return bA.and(o)
|
return bA.and(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +126,11 @@ func (bA *BitArray) and(o *BitArray) *BitArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) Not() *BitArray {
|
func (bA *BitArray) Not() *BitArray {
|
||||||
|
if bA == nil {
|
||||||
|
return nil // Degenerate
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
c := bA.copy()
|
c := bA.copy()
|
||||||
for i := 0; i < len(c.Elems); i++ {
|
for i := 0; i < len(c.Elems); i++ {
|
||||||
c.Elems[i] = ^c.Elems[i]
|
c.Elems[i] = ^c.Elems[i]
|
||||||
|
@ -123,9 +139,11 @@ func (bA *BitArray) Not() *BitArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) Sub(o *BitArray) *BitArray {
|
func (bA *BitArray) Sub(o *BitArray) *BitArray {
|
||||||
|
if bA == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
if bA.Bits > o.Bits {
|
if bA.Bits > o.Bits {
|
||||||
c := bA.copy()
|
c := bA.copy()
|
||||||
for i := 0; i < len(o.Elems)-1; i++ {
|
for i := 0; i < len(o.Elems)-1; i++ {
|
||||||
|
@ -139,11 +157,14 @@ func (bA *BitArray) Sub(o *BitArray) *BitArray {
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
} else {
|
} else {
|
||||||
return bA.and(o.Not())
|
return bA.and(o.Not()) // Note degenerate case where o == nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) IsFull() bool {
|
func (bA *BitArray) IsFull() bool {
|
||||||
|
if bA == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
|
@ -165,6 +186,9 @@ func (bA *BitArray) IsFull() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) PickRandom() (uint, bool) {
|
func (bA *BitArray) PickRandom() (uint, bool) {
|
||||||
|
if bA == nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
|
@ -210,14 +234,16 @@ func (bA *BitArray) String() string {
|
||||||
}
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
|
|
||||||
return bA.stringIndented("")
|
return bA.stringIndented("")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) StringIndented(indent string) string {
|
func (bA *BitArray) StringIndented(indent string) string {
|
||||||
|
if bA == nil {
|
||||||
|
return "nil-BitArray"
|
||||||
|
}
|
||||||
bA.mtx.Lock()
|
bA.mtx.Lock()
|
||||||
defer bA.mtx.Unlock()
|
defer bA.mtx.Unlock()
|
||||||
return bA.StringIndented(indent)
|
return bA.stringIndented(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bA *BitArray) stringIndented(indent string) string {
|
func (bA *BitArray) stringIndented(indent string) string {
|
||||||
|
|
|
@ -433,7 +433,6 @@ OUTER_LOOP:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rs := conR.conS.GetRoundState()
|
rs := conR.conS.GetRoundState()
|
||||||
ps.EnsureVoteBitArrays(rs.Height, rs.Validators.Size())
|
|
||||||
prs := ps.GetRoundState()
|
prs := ps.GetRoundState()
|
||||||
|
|
||||||
switch sleeping {
|
switch sleeping {
|
||||||
|
@ -443,7 +442,14 @@ OUTER_LOOP:
|
||||||
sleeping = 0
|
sleeping = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
trySendVote := func(voteSet *VoteSet, peerVoteSet *BitArray) (sent bool) {
|
// Returns true when useful work was done.
|
||||||
|
trySendVote := func(height uint, voteSet *VoteSet, peerVoteSet *BitArray) (sent bool) {
|
||||||
|
if voteSet == nil {
|
||||||
|
return false
|
||||||
|
} else if peerVoteSet == nil {
|
||||||
|
ps.EnsureVoteBitArrays(height, voteSet.Size())
|
||||||
|
return true
|
||||||
|
}
|
||||||
// TODO: give priority to our vote.
|
// TODO: give priority to our vote.
|
||||||
if index, ok := voteSet.BitArray().Sub(peerVoteSet.Copy()).PickRandom(); ok {
|
if index, ok := voteSet.BitArray().Sub(peerVoteSet.Copy()).PickRandom(); ok {
|
||||||
vote := voteSet.GetByIndex(index)
|
vote := voteSet.GetByIndex(index)
|
||||||
|
@ -456,7 +462,14 @@ OUTER_LOOP:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true when useful work was done.
|
||||||
trySendCommitFromValidation := func(blockMeta *types.BlockMeta, validation *types.Validation, peerVoteSet *BitArray) (sent bool) {
|
trySendCommitFromValidation := func(blockMeta *types.BlockMeta, validation *types.Validation, peerVoteSet *BitArray) (sent bool) {
|
||||||
|
if validation == nil {
|
||||||
|
return false
|
||||||
|
} else if peerVoteSet == nil {
|
||||||
|
ps.EnsureVoteBitArrays(blockMeta.Header.Height, uint(len(validation.Commits)))
|
||||||
|
return true
|
||||||
|
}
|
||||||
if index, ok := validation.BitArray().Sub(prs.Commits.Copy()).PickRandom(); ok {
|
if index, ok := validation.BitArray().Sub(prs.Commits.Copy()).PickRandom(); ok {
|
||||||
commit := validation.Commits[index]
|
commit := validation.Commits[index]
|
||||||
log.Debug("Picked commit to send", "index", index, "commit", commit)
|
log.Debug("Picked commit to send", "index", index, "commit", commit)
|
||||||
|
@ -482,31 +495,27 @@ OUTER_LOOP:
|
||||||
|
|
||||||
// If there are lastcommits to send...
|
// If there are lastcommits to send...
|
||||||
if prs.Round == 0 && prs.Step == RoundStepNewHeight {
|
if prs.Round == 0 && prs.Step == RoundStepNewHeight {
|
||||||
if prs.LastCommits != nil && rs.LastCommits != nil {
|
if trySendVote(rs.Height-1, rs.LastCommits, prs.LastCommits) {
|
||||||
if prs.LastCommits.Size() == rs.LastCommits.Size() {
|
continue OUTER_LOOP
|
||||||
if trySendVote(rs.LastCommits, prs.LastCommits) {
|
|
||||||
continue OUTER_LOOP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are prevotes to send...
|
// If there are prevotes to send...
|
||||||
if rs.Round == prs.Round && prs.Step <= RoundStepPrevote {
|
if rs.Round == prs.Round && prs.Step <= RoundStepPrevote {
|
||||||
if trySendVote(rs.Prevotes, prs.Prevotes) {
|
if trySendVote(rs.Height, rs.Prevotes, prs.Prevotes) {
|
||||||
continue OUTER_LOOP
|
continue OUTER_LOOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are precommits to send...
|
// If there are precommits to send...
|
||||||
if rs.Round == prs.Round && prs.Step <= RoundStepPrecommit {
|
if rs.Round == prs.Round && prs.Step <= RoundStepPrecommit {
|
||||||
if trySendVote(rs.Precommits, prs.Precommits) {
|
if trySendVote(rs.Height, rs.Precommits, prs.Precommits) {
|
||||||
continue OUTER_LOOP
|
continue OUTER_LOOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are any commits to send...
|
// If there are any commits to send...
|
||||||
if trySendVote(rs.Commits, prs.Commits) {
|
if trySendVote(rs.Height, rs.Commits, prs.Commits) {
|
||||||
continue OUTER_LOOP
|
continue OUTER_LOOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,7 +526,7 @@ OUTER_LOOP:
|
||||||
// If peer is lagging by height 1, match our LastCommits or SeenValidation to peer's Commits.
|
// If peer is lagging by height 1, match our LastCommits or SeenValidation to peer's Commits.
|
||||||
if rs.Height == prs.Height+1 && rs.LastCommits.Size() > 0 {
|
if rs.Height == prs.Height+1 && rs.LastCommits.Size() > 0 {
|
||||||
// If there are lastcommits to send...
|
// If there are lastcommits to send...
|
||||||
if trySendVote(rs.LastCommits, prs.Commits) {
|
if trySendVote(prs.Height, rs.LastCommits, prs.Commits) {
|
||||||
continue OUTER_LOOP
|
continue OUTER_LOOP
|
||||||
} else {
|
} else {
|
||||||
ps.SetHasAllCatchupCommits(prs.Height)
|
ps.SetHasAllCatchupCommits(prs.Height)
|
||||||
|
@ -665,18 +674,20 @@ func (ps *PeerState) EnsureVoteBitArrays(height uint, numValidators uint) {
|
||||||
ps.mtx.Lock()
|
ps.mtx.Lock()
|
||||||
defer ps.mtx.Unlock()
|
defer ps.mtx.Unlock()
|
||||||
|
|
||||||
if ps.Height != height {
|
if ps.Height == height {
|
||||||
return
|
if ps.Prevotes == nil {
|
||||||
}
|
ps.Prevotes = NewBitArray(numValidators)
|
||||||
|
}
|
||||||
if ps.Prevotes == nil {
|
if ps.Precommits == nil {
|
||||||
ps.Prevotes = NewBitArray(numValidators)
|
ps.Precommits = NewBitArray(numValidators)
|
||||||
}
|
}
|
||||||
if ps.Precommits == nil {
|
if ps.Commits == nil {
|
||||||
ps.Precommits = NewBitArray(numValidators)
|
ps.Commits = NewBitArray(numValidators)
|
||||||
}
|
}
|
||||||
if ps.Commits == nil {
|
} else if ps.Height == height+1 {
|
||||||
ps.Commits = NewBitArray(numValidators)
|
if ps.LastCommits == nil {
|
||||||
|
ps.LastCommits = NewBitArray(numValidators)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue