ADR-002 — VRF Implementation: HMAC-based vs @noble/curves

Status: PROPOSED
Date: 2026-04-07
Domain: Legitimacy (π Governance, θ Consensus, arbitration)

Context

Verifiable Random Functions (VRFs) are used in three places in Colibri’s legitimacy layer:

  1. Entropy injection (π Governance, P6.2): VRF selects 10% of voters for equal-weight ballots on proposals with >5% numeric delta.
  2. Arbiter selection (θ Consensus / arbitration): VRF selects arbiters for dispute resolution (S09, EVT-B02 ArbitersAssigned).
  3. Leader election (θ Consensus): VRF elects a BFT round leader per epoch.

A VRF must satisfy three properties:

  • Verifiable: anyone can confirm the output is correct given the proof
  • Deterministic: same input always produces the same output
  • Unpredictable: output cannot be predicted before the VRF seed is revealed

Reference algorithm: VRF specification documented in extraction files.

The reference implementation used HMAC-SHA256 as a simplified stand-in for the full ECVRF-EDWARDS25519-SHA512-TAI construction from RFC 9381.

Reference: See pseudocode in docs/reference/extractions/ for algorithm details.

Decision

TBD — requires PM decision.

This ADR documents the two viable approaches. The PM should consider whether strict RFC 9381 compliance is required for external interoperability, or whether a simpler HMAC-based approach is sufficient for Colibri’s internal use.

Options

Option A: HMAC-SHA256 internal implementation (port the Python approach)

Implement a HMAC-SHA256 VRF using node:crypto (built-in). This is a simplified VRF approach (not full EC-VRF per RFC 9381).

Target file: src/rules/vrf.js (Phase 1+)

Pros:

  • Zero new dependencies — uses only node:crypto (built-in)
  • Sufficient for Colibri’s internal use (governance, arbitration, leader election are internal consensus mechanisms, not externally-verifiable proofs)
  • Fast: HMAC-SHA256 is a single call

Cons:

  • Not a compliant RFC 9381 ECVRF — cannot interoperate with external VRF verifiers
  • A production-grade system should use proper EC-VRF for external verifiability
  • If Colibri later exposes VRF proofs to external observers, the proofs would not be verifiable by standard tools

Option B: @noble/curves (Ed25519 EC-VRF per RFC 9381)

Use the @noble/curves library (@noble/curves/ed25519) which provides audited, pure-JavaScript Ed25519 operations. Implement the RFC 9381 ECVRF-EDWARDS25519-SHA512-TAI construction on top.

Target file: src/rules/vrf.js (Phase 1+)

Pros:

  • RFC 9381 compliant — VRF proofs verifiable by external tools
  • @noble/curves is widely used, audited, pure JS (no native addon)
  • Future-proof: if Colibri P2P layer ever exposes proofs publicly, they are standard
  • Ed25519 is consistent with Colibri identity system

Cons:

  • Adds a new npm dependency to audit and maintain
  • Implementing RFC 9381 correctly is non-trivial (~200 lines)
  • Overkill if VRF proofs are never exposed externally

Consequences

If Option A (HMAC, port Python):

  • 1-day implementation: direct port of vrf.py
  • Governance entropy injection and arbiter selection work immediately
  • Technical debt: comment in code must warn that this is not RFC 9381 compliant
  • Risk: if external verifiability is ever needed, full rewrite required

If Option B (@noble/curves):

  • 3-5 day implementation: RFC 9381 has specific hash-to-curve, nonce generation, and serialization requirements
  • VRF proofs are externally verifiable from day one
  • @noble/curves is a peer dependency of @noble/hashes (likely already in the tree via other deps)

Alternatives Considered

  • libsodium.js (wasm): provides Ed25519 but not ECVRF directly; would still need RFC 9381 layer on top
  • @peculiar/webcrypto: WebCrypto polyfill; supports Ed25519 signing but not VRF prove/verify
  • Build custom native addon with libsodium C: too heavy; native addon for a utility function is not warranted

References

  • Reference algorithm in docs/reference/extractions/
  • RFC 9381: Verifiable Random Functions (VRFs) — https://www.rfc-editor.org/rfc/rfc9381
  • @noble/curves — https://github.com/paulmillr/noble-curves
  • S09 — Arbitration — arbiter selection uses VRF
  • S18 — Governance Protocol §2.4 — entropy injection uses VRF
  • ADR-003 — BFT library decision (VRF for leader election)

Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.