dleqProve method

VRFProof dleqProve(
  1. VRFInOut out, {
  2. bool kusamaVRF = true,
  3. GenerateRandom? nonceGenerator,
  4. MerlinTranscript? verifyScript,
})

Generates a Discrete Logarithm Equality Proof (DLEQ) for a Verifiable Random Function (VRF) output.

This method generates a DLEQ proof for a given VRF output, ensuring the equality of discrete logarithms of specific points in the VRF computation.

Parameters:

  • out: A VRFInOut containing the VRF output to prove.
  • kusamaVRF (optional): A boolean indicating whether to include the public key in the DLEQ proof. Default is true for Kusama VRF compatibility.
  • nonceGenerator (optional): A function that generates a nonce. Default is a function that generates a random 64-byte nonce.

Returns: A VRFProof representing the DLEQ proof.

Example Usage:

VRFInOut vrfOutput = ...;
SchnorrkelSecretKey secretKey = ...;
var dleqProof = secretKey.dleqProve(vrfOutput);

The dleqProve method generates a DLEQ proof for a VRF output, ensuring the equality of discrete logarithms between specific points in the VRF computation. It returns a VRFProof instance.

Implementation

VRFProof dleqProve(VRFInOut out,
    {bool kusamaVRF = true,
    GenerateRandom? nonceGenerator,
    MerlinTranscript? verifyScript}) {
  const int nonceLength = SchnorrkelKeyCost.nonceLength * 2;
  final script = verifyScript ?? MerlinTranscript("VRF");
  script.additionalData("proto-name".codeUnits, "DLEQProof".codeUnits);
  script.additionalData("vrf:h".codeUnits, out.input);
  if (!kusamaVRF) {
    script.additionalData("vrf:pk".codeUnits, publicKey().toBytes());
  }
  final nonce = nonceGenerator?.call(nonceLength) ??
      QuickCrypto.generateRandom(nonceLength);
  if (nonce.length != nonceLength) {
    throw const CryptoException("invalid nonce length.");
  }
  final nScalar = Ed25519Utils.scalarReduceConst(nonce);
  final mult =
      RistrettoPoint.fromEdwardBytes(Ed25519Utils.scalarMultBase(nScalar));
  script.additionalData("vrf:R=g^r".codeUnits, mult.toBytes());
  RistrettoPoint inputPoint = RistrettoPoint.fromBytes(out.input);
  inputPoint = RistrettoPoint.fromEdwardBytes(
      Ed25519Utils.pointScalarMult(inputPoint.toEdwardBytes(), nScalar));
  script.additionalData("vrf:h^r".codeUnits, inputPoint.toBytes());
  if (kusamaVRF) {
    script.additionalData("vrf:pk".codeUnits, publicKey().toBytes());
  }
  script.additionalData("vrf:h^sk".codeUnits, out.output);
  final c = script.toBytesWithReduceScalar(
      "prove".codeUnits, SchnorrkelKeyCost.vrfProofLength);
  final multiply = Ed25519Utils.mulSub(c, key(), nScalar);
  return VRFProof._(c, multiply);
}