mirror of https://github.com/poanetwork/gecko.git
81 lines
1.7 KiB
Go
81 lines
1.7 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package snowman
|
|
|
|
import (
|
|
"github.com/ava-labs/gecko/ids"
|
|
)
|
|
|
|
type voter struct {
|
|
t *Transitive
|
|
vdr ids.ShortID
|
|
requestID uint32
|
|
response ids.ID
|
|
deps ids.Set
|
|
}
|
|
|
|
func (v *voter) Dependencies() ids.Set { return v.deps }
|
|
|
|
func (v *voter) Fulfill(id ids.ID) {
|
|
v.deps.Remove(id)
|
|
v.Update()
|
|
}
|
|
|
|
func (v *voter) Abandon(id ids.ID) { v.Fulfill(id) }
|
|
|
|
func (v *voter) Update() {
|
|
if v.deps.Len() != 0 {
|
|
return
|
|
}
|
|
|
|
results := ids.Bag{}
|
|
finished := false
|
|
if v.response.IsZero() {
|
|
results, finished = v.t.polls.CancelVote(v.requestID, v.vdr)
|
|
} else {
|
|
results, finished = v.t.polls.Vote(v.requestID, v.vdr, v.response)
|
|
}
|
|
|
|
if !finished {
|
|
return
|
|
}
|
|
|
|
// To prevent any potential deadlocks with un-disclosed dependencies, votes
|
|
// must be bubbled to the nearest valid block
|
|
results = v.bubbleVotes(results)
|
|
|
|
v.t.Config.Context.Log.Verbo("Finishing poll [%d] with:\n%s", v.requestID, &results)
|
|
v.t.Consensus.RecordPoll(results)
|
|
|
|
v.t.Config.VM.SetPreference(v.t.Consensus.Preference())
|
|
|
|
if v.t.Consensus.Finalized() {
|
|
v.t.Config.Context.Log.Verbo("Snowman engine can quiesce")
|
|
return
|
|
}
|
|
|
|
v.t.Config.Context.Log.Verbo("Snowman engine can't quiesce")
|
|
v.t.repoll()
|
|
}
|
|
|
|
func (v *voter) bubbleVotes(votes ids.Bag) ids.Bag {
|
|
bubbledVotes := ids.Bag{}
|
|
for _, vote := range votes.List() {
|
|
count := votes.Count(vote)
|
|
blk, err := v.t.Config.VM.GetBlock(vote)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for blk.Status().Fetched() && !v.t.Consensus.Issued(blk) {
|
|
blk = blk.Parent()
|
|
}
|
|
|
|
if !blk.Status().Decided() && v.t.Consensus.Issued(blk) {
|
|
bubbledVotes.AddCount(blk.ID(), count)
|
|
}
|
|
}
|
|
return bubbledVotes
|
|
}
|