func (ks *Keyserver) PushRatification(ctx context.Context, r *proto.SignedEpochHead) (*proto.Nothing, error) {
	verifierCertID, err := authenticateVerifier(ctx)
	if err != nil {
		log.Printf("PushRatification: %s", err)
		return nil, fmt.Errorf("PushRatification: %s", err)
	}
	for signerID := range r.Signatures {
		if signerID != verifierCertID {
			return nil, fmt.Errorf("PushRatification: not authorized: authenticated as %x but tried to write %x's signature", verifierCertID, signerID)
		}
	}
	uid := genUID()
	ch := ks.wr.Wait(uid)
	ks.log.Propose(ctx, replication.LogEntry{Data: proto.MustMarshal(&proto.KeyserverStep{
		UID:  uid,
		Type: &proto.KeyserverStep_VerifierSigned{VerifierSigned: r},
	})})
	select {
	case <-ctx.Done():
		ks.wr.Notify(uid, nil)
		return nil, ctx.Err()
	case <-ch:
		return nil, nil
	}
}
PushRatification implements the interfaceE2EKSVerification interface from proto/verifier.proto
package keyserver
import (
	"encoding/binary"
	"fmt"
	"log"
	"math"
	"strconv"
	"strings"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/peer"
	"github.com/yahoo/coname/keyserver/kv"
	"github.com/yahoo/coname/keyserver/replication"
	"github.com/yahoo/coname/proto"
	"golang.org/x/net/context"
)
func (ks *Keyserver) VerifierStream(rq *proto.VerifierStreamRequest, stream proto.E2EKSVerification_VerifierStreamServer) error {
	var step proto.VerifierStep  
	for start, limit := rq.Start, saturatingAdd(rq.Start, rq.PageSize); start < limit; {
		iter := ks.db.NewIterator(&kv.Range{Start: tableVerifierLog(start), Limit: tableVerifierLog(limit)})
		for ; iter.Next() && start < limit; start++ {
			select {
			case <-stream.Context().Done():
				iter.Release()
				return stream.Context().Err()
			default:
			}
			dbIdx := binary.BigEndian.Uint64(iter.Key()[1:])
			if dbIdx != start {
				log.Printf("ERROR: non-consecutive entries in verifier log (wanted %d, got %d)", start, dbIdx)
				iter.Release()
				return fmt.Errorf("internal error")
			}
			if err := step.Unmarshal(iter.Value()); err != nil {
				log.Printf("ERROR: invalid protobuf entry in verifier log (index %d)", start)
				iter.Release()
				return fmt.Errorf("internal error")
			}
			if err := stream.Send(&step); err != nil {
				iter.Release()
				return err
			}
			step.Reset()
		}
		iter.Release()
		if err := iter.Error(); err != nil {
			log.Printf("ERROR: range [tableVerifierLog(%d), tableVerifierLog(%d)) ended at %d (not included) with error %s", rq.Start, limit, start, err)
			return fmt.Errorf("internal error")
		}
	sbLoop:
		for ch := ks.sb.Receive(start, limit); ch != nil && start < limit; start++ {
			select {
			case <-stream.Context().Done():
				return stream.Context().Err()
			case sbStep, ok := <-ch:  
				if !ok {
					break sbLoop
				}
				if err := stream.Send(sbStep.(*proto.VerifierStep)); err != nil {
					return err
				}
			}
		}
	}
	return nil
}
const verifierCommonNamePrefix = "verifier" + " "
func authenticateVerifier(ctx context.Context) (uint64, error) {
	pr, ok := peer.FromContext(ctx)
	if !ok {
		return 0, fmt.Errorf("failed to authenticate verifier: peer.FromContext returned false")
	}
	certChains := pr.AuthInfo.(credentials.TLSInfo).State.VerifiedChains
	if len(certChains) != 1 {
		return 0, fmt.Errorf("failed to authenticate verifier: expected exactly one valid certificate chain")
	}
	chain := certChains[0]
	leaf := chain[0]
	verifierIDString := leaf.Subject.CommonName
	if !strings.HasPrefix(verifierIDString, verifierCommonNamePrefix) {
		return 0, fmt.Errorf("failed to authenticate verifier: invalid common name: missing prefix %q (got %q)", verifierCommonNamePrefix, verifierIDString)
	}
	verifierID, err := strconv.ParseUint(verifierIDString[len(verifierCommonNamePrefix):], 16, 64)
	if err != nil {
		return 0, fmt.Errorf("failed to authenticate verifier: invalid common name: id not an integer: %s", err)
	}
	return verifierID, nil
}