@@ -118,7 +118,7 @@ func (p *BaseProposalSelector) selectInternal(
118118
119119 return nil , errors .WithMessagef (err , "get suffrage for height, %d" , point .Height ())
120120 case len (i ) < 2 :
121- return p .proposalFromNode (wctx , point , i [0 ], previousBlock )
121+ return p .proposalFromLocalNode (wctx , point , i [0 ], previousBlock )
122122 default :
123123 nodes = i
124124 }
@@ -161,11 +161,11 @@ func (p *BaseProposalSelector) selectFromProposer(
161161 nodes []base.Node ,
162162 previousBlock util.Hash ,
163163) (base.ProposalSignFact , base.Address , error ) {
164- e := util .StringError ("select proposal from proposer" )
164+ e := util .StringError ("proposal from selected proposer" )
165165
166166 proposer , err := p .args .ProposerSelectFunc (ctx , point , nodes , previousBlock )
167167 if err != nil {
168- return nil , nil , e .WithMessage (err , "select proposer" )
168+ return nil , nil , e .WithMessage (err , "proposer select " )
169169 }
170170
171171 pr , err := p .proposalFromNode (ctx , point , proposer , previousBlock )
@@ -176,6 +176,41 @@ func (p *BaseProposalSelector) selectFromProposer(
176176 return pr , proposer .Address (), err
177177}
178178
179+ func (p * BaseProposalSelector ) proposalFromLocalNode (
180+ ctx context.Context ,
181+ point base.Point ,
182+ proposer base.Node ,
183+ previousBlock util.Hash ,
184+ ) (base.ProposalSignFact , error ) {
185+ ticker := time .NewTicker (time .Millisecond * 33 )
186+ defer ticker .Stop ()
187+
188+ var reset sync.Once
189+
190+ for {
191+ select {
192+ case <- ctx .Done ():
193+ return nil , errors .WithStack (ctx .Err ())
194+ case <- ticker .C :
195+ reset .Do (func () {
196+ ticker .Reset (p .args .RequestProposalInterval )
197+ })
198+
199+ switch pr , err := p .findProposal (ctx , point , proposer , previousBlock ); {
200+ case err == nil :
201+ return pr , nil
202+ case errors .Is (err , context .Canceled ), errors .Is (err , context .DeadlineExceeded ):
203+ // NOTE ignore context error from findProposal; if context error
204+ // is from main context, it will be catched from the main select
205+ // ctx.Done().
206+ case errors .Is (err , errFailedToRequestProposalToNode ):
207+ default :
208+ return nil , errors .WithMessage (err , "find proposal" )
209+ }
210+ }
211+ }
212+ }
213+
179214func (p * BaseProposalSelector ) proposalFromNode (
180215 ctx context.Context ,
181216 point base.Point ,
@@ -204,6 +239,7 @@ func (p *BaseProposalSelector) proposalFromNode(
204239 // is from main context, it will be catched from the main select
205240 // ctx.Done().
206241 case errors .Is (err , errFailedToRequestProposalToNode ):
242+ return nil , errors .WithMessage (err , "find proposal" )
207243 default :
208244 return nil , errors .WithMessage (err , "find proposal" )
209245 }
@@ -392,7 +428,7 @@ func ConcurrentRequestProposal(
392428 switch pr , found , err := client .RequestProposal (ctx , ci , point , proposer .Address (), previousBlock ); {
393429 case err != nil :
394430 return nil
395- case ! found :
431+ case ! found || pr == nil :
396432 return nil
397433 case ! isExpectedValidProposal (point , proposer , pr , networkID ):
398434 return nil
0 commit comments