This PR adds an extra mechanism to sync.HeadSync that tries to retrieve the latest finality update from every server each time it sends an optimistic update in a new epoch (unless we already have a validated finality update attested in the same epoch).
Note that this is not necessary and does not happen if the new finality update is delivered before the optimistic update. The spec only mandates light_client_finality_update events when a new epoch is finalized. If the chain does not finalize for a while then we might need an explicit request that returns a finality proof that proves the same finality epoch from the latest attested epoch.
t.Errorf("Missing validated head in test case #%d index #%d (expected {slot %d blockRoot %x}, got none)",tci,i,expHead.Header.Slot,expHead.Header.Hash())
t.Errorf("Missing validated head in test case #%d index #%d (expected {slot %d blockRoot %x}, got none)",tci,i,expHead.Attested.Header.Slot,expHead.Attested.Header.Hash())
continue
}
ifht.validated[i]!=expHead{
vhead:=ht.validated[i].Header
t.Errorf("Wrong validated head in test case #%d index #%d (expected {slot %d blockRoot %x}, got {slot %d blockRoot %x})",tci,i,expHead.Header.Slot,expHead.Header.Hash(),vhead.Slot,vhead.Hash())
if!reflect.DeepEqual(ht.validated[i],expHead){
vhead:=ht.validated[i].Attested.Header
t.Errorf("Wrong validated head in test case #%d index #%d (expected {slot %d blockRoot %x}, got {slot %d blockRoot %x})",tci,i,expHead.Attested.Header.Slot,expHead.Attested.Header.Hash(),vhead.Slot,vhead.Hash())
}
}
fori:=len(expHeads);i<len(ht.validated);i++{
vhead:=ht.validated[i].Header
vhead:=ht.validated[i].Attested.Header
t.Errorf("Unexpected validated head in test case #%d index #%d (expected none, got {slot %d blockRoot %x})",tci,i,vhead.Slot,vhead.Hash())