Verifiable Random Function #


Filecoin uses the notion of a Verifiable Random Function (VRF). A VRF uses a private key to produce a digest of an arbitrary message such that the output is unique per signer and per message. Any third party in possession of the corresponding public key, the message, and the VRF output, can verify if the digest has been computed correctly and by the correct signer. Using a VRF in the ticket generation process allows anyone to verify if a block comes from an eligible block producer (see Ticket Generation for more details).

BLS signature can be used as the basis to construct a VRF. Filecoin transforms the BLS signature scheme it uses (see Signatures into a VRF, Filecoin uses the random oracle model and deterministically hashes the signature (using blake2b to produce a 256 bit output) to produce the final digest.

These digests are often used as entropy for randomness in the protocol (see Randomness).

type VRFPublicKey PublicKey
type VRFSecretKey SecretKey

// VRFKeyPair holds the private key and respectively the public key to create 
// and respectively verify a VRF output.
type VRFKeyPair struct {
    VRFPublicKey
    VRFSecretKey

    // Generate a VRF from the given input with the SecretKey that can be
    // verified with the PublicKey
    Generate(input Bytes) VRFResult
}

type VRFResult struct {
    Output            Bytes  // @(internal)

    Proof             Bytes
    Digest            Bytes
    MaxValue()        Bytes
    ValidateSyntax()  bool

    Verify(input Bytes, pk VRFPublicKey) bool
}
package crypto

import (
	util "github.com/filecoin-project/specs/util"
	"golang.org/x/crypto/blake2b"
)

func (self *VRFResult_I) ValidateSyntax() bool {
	panic("TODO")
	return false
}

func (self *VRFResult_I) Verify(input util.Bytes, pk VRFPublicKey) bool {
	// return new(BLS).Verify(self.Proof, pk.(*BLSPublicKey), input)
	return false
}

func (self *VRFResult_I) MaxValue() util.Bytes {
	panic("")
	// return new(BLS).MaxSigValue()
}

func (self *VRFKeyPair_I) Generate(input util.Bytes) VRFResult {
	// sig := new(BLS).Sign(input, self.SecretKey)
	var blsSig util.Bytes

	digest := blake2b.Sum256(blsSig)
	ret := &VRFResult_I{
		Proof_:  blsSig,
		Digest_: digest[:],
	}
	return ret
}