hydra-plutus
Safe HaskellSafe-Inferred
LanguageGHC2021

Hydra.Contract.KZGTrustedSetup

Description

KZG trusted setup parameters for Hydra's accumulator-based partial fanout.

Background

Hydra's partial fanout uses KZG polynomial commitments to prove on-chain that a distributed batch of UTxOs is a genuine subset of the UTxOs committed in the Closed head datum. The accumulator polynomial encodes all snapshot UTxOs as roots:

A(X) = ∏ (X − sᵢ)   where sᵢ = hash(TxOutᵢ)

The accumulator commitment is A(τ)·G1 — a single G1 point (48 bytes) stored in the Closed datum. The membership proof for a distributed subset S is the quotient Q(X) = A(X) / P_S(X) committed as Q(τ)·G1. The on-chain validator verifies the pairing identity:

e(A(τ)·G1, G2) = e(Q(τ)·G1, P_S(τ)·G2)

where P_S(τ)·G2 is computed on-chain via a G2 MSM using the on-chain G2 CRS.

The Trusted Setup

Computing A(τ)·G1 and Q(τ)·G1 off-chain, and P_S(τ)·G2 on-chain, all require the same secret τ (powers of tau). We embed the __EIP-4844 KZG trusted setup__ produced by the Ethereum KZG ceremony (2023):

The setup provides:

  • 4096 G1 points [G1, τ·G1, ..., τ^4095·G1] — used off-chain to build the accumulator commitment and membership proofs
  • 65 G2 points [G2, τ·G2, ..., τ^64·G2] — used as the on-chain verification CRS (G2 MSM to evaluate P_S(τ)·G2)

Accumulator size limit

The accumulator polynomial has degree n (one root per UTxO). Computing A(τ)·G1 off-chain needs n+1 G1 points. EIP-4844 provides 4096 G1 points, so a head can hold up to 4095 UTxOs. This is enforced by maxAccumulatorSize. The on-chain G2 CRS only needs batch-size-many points per partial fanout step, so the 65 G2 points do not constrain the accumulator size.

Synopsis

Documentation

data KZGSetupError Source #

Errors that can occur when loading the embedded KZG trusted setup.

In practice these should never occur — the trusted setup JSON is embedded at compile time and its integrity is validated by the test suite. A Left here would indicate binary tampering (IntegrityCheckFailed) or a corrupted build artefact.

Constructors

IntegrityCheckFailed

SHA-256 digest of the embedded file does not match the known-good value.

Fields

JsonDecodeFailed

The embedded bytes could not be decoded as JSON at all.

JsonParseFailed

The JSON decoded but failed the structural parser (missing keys etc.).

Fields

InvalidG1Point

A G1 point hex string could not be hex-decoded or BLS-decompressed.

Fields

InvalidG2Point

A G2 point hex string could not be hex-decoded or BLS-decompressed.

Fields

Instances

Instances details
Generic KZGSetupError Source # 
Instance details

Defined in Hydra.Contract.KZGTrustedSetup

Associated Types

type Rep KZGSetupError :: Type -> Type Source #

Show KZGSetupError Source # 
Instance details

Defined in Hydra.Contract.KZGTrustedSetup

Eq KZGSetupError Source # 
Instance details

Defined in Hydra.Contract.KZGTrustedSetup

type Rep KZGSetupError Source # 
Instance details

Defined in Hydra.Contract.KZGTrustedSetup

type Rep KZGSetupError = D1 ('MetaData "KZGSetupError" "Hydra.Contract.KZGTrustedSetup" "hydra-plutus-2.3.0-GZuRkjMlaaiDs5DtXvwJLz" 'False) ((C1 ('MetaCons "IntegrityCheckFailed" 'PrefixI 'True) (S1 ('MetaSel ('Just "expectedHash") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text) :*: S1 ('MetaSel ('Just "actualHash") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text)) :+: C1 ('MetaCons "JsonDecodeFailed" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "JsonParseFailed" 'PrefixI 'True) (S1 ('MetaSel ('Just "parseError") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text)) :+: (C1 ('MetaCons "InvalidG1Point" 'PrefixI 'True) (S1 ('MetaSel ('Just "hexPoint") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text)) :+: C1 ('MetaCons "InvalidG2Point" 'PrefixI 'True) (S1 ('MetaSel ('Just "hexPoint") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Text)))))

warmup :: Either KZGSetupError Int Source #

Force the whole embedded trusted setup into memory, yielding the number of G1 points loaded.

Both halves are forced: the G1 CRS the off-chain commitment path consumes, and the G2 CRS behind canonicalG2Points, which the head validator binds. A caller gets a corrupt setup as a Left here rather than as the error those two would otherwise raise from pure code, mid-session.

The forcing lives in this module on purpose. g1Points currently decompresses every point just to decide between Left and Right, so any WHNF happens to do the work — but that is a property of the representation, not a promise. Should either list become a lazy structure, this is the one place obliged to keep forcing, rather than a caller's length silently degenerating into a spine walk.

g1Points :: Either KZGSetupError [Point1] Source #

G1 powers of tau [G1, τ·G1, ..., τ^4095·G1] from the EIP-4844 ceremony (monomial form). 4096 points; used off-chain to build accumulator commitments and membership proofs.

g2Points :: Either KZGSetupError [Point2] Source #

G2 powers of tau [G2, τ·G2, ..., τ^64·G2] from the EIP-4844 ceremony (monomial form). 65 points; used as the on-chain verification CRS (G2 MSM to evaluate P_S(τ)·G2).

g1BuiltinPoints :: Either KZGSetupError [BuiltinBLS12_381_G1_Element] Source #

G1 points as Plutus built-in type, for use in off-chain accumulator commitment. Derived from g1Points by re-compressing to bytes; shares the same parsed data.

g2BuiltinPoints :: Either KZGSetupError [BuiltinBLS12_381_G2_Element] Source #

G2 points as Plutus built-in type, for use in on-chain verification CRS. Derived from g2Points by re-compressing to bytes; shares the same parsed data.

maxAccumulatorSize :: Int Source #

Maximum accumulator element count supported by the currently embedded G1 CRS. The EIP-4844 setup provides exactly 4096 G1 monomial points [G1, τ·G1, ..., τ^4095·G1], so the accumulator supports up to 4095 elements (n elements need n+1 G1 points).

maxFanoutBatchSize :: Int Source #

Theoretical upper bound on partial fanout batch size, derived from the embedded EIP-4844 trusted setup: 65 G2 monomial points give room for a polynomial of degree 64 (one (X - sᵢ) factor per fanned-out element).

NOTE: this is the ceiling implied by the trusted-setup file, not the deployed cap. The on-chain CRS UTxO only embeds the first defaultItems G2 points, so the production batch limit is currently defaultItems - 1. Raising the deployed cap requires re-publishing the CRS UTxO with more G2 points (bounded above by this value).

defaultItems :: Int Source #

Number of G2 monomial points published in the on-chain CRS reference UTxO (see createCRSG2Datum), hence the size of the canonical CRS datum the head validator binds. Bounded above by maxFanoutBatchSize + 1; raising it requires re-publishing the CRS UTxO.

canonicalG2Points :: [BuiltinBLS12_381_G2_Element] Source #

The canonical on-chain CRS datum: the first defaultItems G2 monomial points of the embedded EIP-4844 setup, as the on-chain builtin element type. This is exactly what createCRSG2Datum publishes and what the head validator binds via its baked datum hash. Errors only if the embedded setup is corrupt.