Verifies a zero-knowledge proof. 
    @x: Blinded message, G1Element, x = HG1(m)*r
    @tTilde: hashed tweak, G2Element, t~ = HG2(t)
    @y: server response (intermediate result), GtElement
    @pi:  pi = (p, c, u), zero-knowledge proof from server, 
      p = g^kw, GtElement; c,u integer values
    @errorOnFail: Rasise an exception if the proof does not hold.

def verifyGt(x, tTilde, y, pi, errorOnFail=True):
    """
    Verifies a zero-knowledge proof. 
    @x: Blinded message, G1Element, x = HG1(m)*r
    @tTilde: hashed tweak, G2Element, t~ = HG2(t)
    @y: server response (intermediate result), GtElement
    @pi:  pi = (p, c, u), zero-knowledge proof from server, 
      p = g^kw, GtElement; c,u integer values
    @errorOnFail: Rasise an exception if the proof does not hold.
    """
    # Unpack the proof
    p,c,u = pi

    # Verify types
    assertType(x, G1Element)
    assertType(tTilde, G2Element)
    assertType(y, GtElement)
    assertType(p, GtElement)

    # TODO: This can be pre-computed while waiting for a server response.
    g = generatorGt()
    beta = pair(x,tTilde)

    # Recompute c'
    t1 = g**u * p**c 
    t2 = beta**u * y**c

    cPrime = hashZ(g,p,beta,y,t1,t2)

    # Check computed @c' against server's value @c
    if cPrime == c:
        return True

    if errorOnFail:
        raise Exception("zero-knowledge proof failed verification.")
    else:
        return False