Example #1
1
// Waits until a sufficient quorum is assembled
func (ks *Keyserver) blockingLookup(ctx context.Context, req *proto.LookupRequest, epoch uint64) (*proto.LookupProof, error) {
	newSignatures := make(chan interface{}, newSignatureBufferSize)
	ks.signatureBroadcast.Subscribe(epoch, newSignatures)
	defer ks.signatureBroadcast.Unsubscribe(epoch, newSignatures)
	verifiersLeft := coname.ListQuorum(req.QuorumRequirement, nil)
	ratifications, haveVerifiers, err := ks.findRatificationsForEpoch(epoch, verifiersLeft)
	if err != nil {
		return nil, err
	}
	for v := range haveVerifiers {
		delete(verifiersLeft, v)
	}
	for !coname.CheckQuorum(req.QuorumRequirement, haveVerifiers) {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("timed out while waiting for ratification")
		case v := <-newSignatures:
			newSig := v.(*proto.SignedEpochHead)
			for id := range newSig.Signatures {
				if _, ok := verifiersLeft[id]; ok {
					ratifications = append(ratifications, newSig)
					delete(verifiersLeft, id)
					haveVerifiers[id] = struct{}{}
				}
			}
		}
	}
	return ks.assembleLookupProof(req, epoch, ratifications)
}
Example #2
0
func (ks *Keyserver) findLatestEpochSignedByQuorum(quorum *proto.QuorumExpr) (uint64, []*proto.SignedEpochHead, error) {
	verifiers := coname.ListQuorum(quorum, nil)
	// find latest epoch, iterate backwards until quorum requirement is met
	// 0 is bad for iterating uint64 in the negative direction and there is no epoch 0
	oldestEpoch, newestEpoch := uint64(1), ks.lastSignedEpoch()
	if newestEpoch == 0 {
		log.Printf("ERROR: no epochs created yet, so lookup failed")
		return 0, nil, fmt.Errorf("internal error")
	}
	if newestEpoch-oldestEpoch > ks.laggingVerifierScan { // careful with overflows!
		oldestEpoch = newestEpoch - ks.laggingVerifierScan
	}
	// TODO: (for lookup throughput and latency) optimize this for the case
	// where verifiers sign everything consecutively
	for epoch := newestEpoch; epoch >= oldestEpoch; epoch-- {
		ratifications, haveVerifiers, err := ks.findRatificationsForEpoch(epoch, verifiers)
		if err != nil {
			return 0, nil, err
		}
		if coname.CheckQuorum(quorum, haveVerifiers) {
			return epoch, ratifications, nil
		}
	}
	// TODO: (why? ~andreser) return whatever ratification we could find
	return 0, nil, fmt.Errorf("could not find sufficient verification in the last %d epochs (and not bothering to look further into the past)", ks.laggingVerifierScan)
}
Example #3
0
// Lookup implements proto.E2EKSLookupServer
func (ks *Keyserver) Lookup(ctx context.Context, req *proto.LookupRequest) (*proto.LookupProof, error) {
	ctx, _ = context.WithTimeout(ctx, ks.clientTimeout)
	var lookupEpoch uint64
	var ratifications []*proto.SignedEpochHead
	if req.Epoch == 0 {
		// use the latest epoch possible
		var err error
		lookupEpoch, ratifications, err = ks.findLatestEpochSignedByQuorum(req.QuorumRequirement)
		if err != nil {
			return nil, err
		}
	} else {
		lookupEpoch = req.Epoch
		var err error
		var haveVerifiers map[uint64]struct{}
		ratifications, haveVerifiers, err = ks.findRatificationsForEpoch(lookupEpoch, coname.ListQuorum(req.QuorumRequirement, nil))
		if err != nil {
			return nil, err
		}
		if !coname.CheckQuorum(req.QuorumRequirement, haveVerifiers) {
			// TODO: return whatever ratification we could find
			return nil, fmt.Errorf("could not find sufficient verification")
		}
	}
	return ks.assembleLookupProof(req, lookupEpoch, ratifications)
}