github.com/MetalBlockchain/metalgo@v1.11.9/snow/engine/snowman/voter.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package snowman 5 6 import ( 7 "context" 8 9 "go.uber.org/zap" 10 11 "github.com/MetalBlockchain/metalgo/ids" 12 "github.com/MetalBlockchain/metalgo/snow/engine/snowman/job" 13 "github.com/MetalBlockchain/metalgo/utils/bag" 14 ) 15 16 var _ job.Job[ids.ID] = (*voter)(nil) 17 18 // Voter records chits received from [nodeID] once its dependencies are met. 19 type voter struct { 20 t *Transitive 21 nodeID ids.NodeID 22 requestID uint32 23 responseOptions []ids.ID 24 } 25 26 // The resolution results from the dependencies of the voter aren't explicitly 27 // used. The responseOptions are used to determine which block to apply the vote 28 // to. The dependencies are only used to optimistically delay the application of 29 // the vote until the blocks have been issued. 30 func (v *voter) Execute(ctx context.Context, _ []ids.ID, _ []ids.ID) error { 31 var ( 32 vote ids.ID 33 shouldVote bool 34 voteIndex int 35 ) 36 for i, voteOption := range v.responseOptions { 37 // To prevent any potential deadlocks with undisclosed dependencies, 38 // votes must be bubbled to the nearest valid block 39 vote, shouldVote = v.t.getProcessingAncestor(ctx, voteOption) 40 if shouldVote { 41 voteIndex = i 42 break 43 } 44 } 45 46 var results []bag.Bag[ids.ID] 47 if shouldVote { 48 v.t.selectedVoteIndex.Observe(float64(voteIndex)) 49 results = v.t.polls.Vote(v.requestID, v.nodeID, vote) 50 } else { 51 results = v.t.polls.Drop(v.requestID, v.nodeID) 52 } 53 54 if len(results) == 0 { 55 return nil 56 } 57 58 for _, result := range results { 59 result := result 60 v.t.Ctx.Log.Debug("finishing poll", 61 zap.Stringer("result", &result), 62 ) 63 if err := v.t.Consensus.RecordPoll(ctx, result); err != nil { 64 return err 65 } 66 } 67 68 if err := v.t.VM.SetPreference(ctx, v.t.Consensus.Preference()); err != nil { 69 return err 70 } 71 72 if v.t.Consensus.NumProcessing() == 0 { 73 v.t.Ctx.Log.Debug("Snowman engine can quiesce") 74 return nil 75 } 76 77 v.t.Ctx.Log.Debug("Snowman engine can't quiesce") 78 v.t.repoll(ctx) 79 return nil 80 }