Ethereum EIP-4844 KZG Powers of Tau ceremony client
MIT License
This repository contains an implementation of a client to participate in the Powers of Tau ceremony for EIP-4844 in Ethereum. This is a multi-party ceremony to generate an SRS needed for KZG commitments.
For bls12-381 elliptic curve operations such as group multiplication and pairings, the implementation uses the gnark-crypto library (audited Oct-2022).
Used by:
If you're confused about these terms, the best place to understand them better is the official ceremony website which gives a high-level explanation of these concepts. It also has a useful FAQ section that digs a bit deeper into the details.
This client implementation has the following features:
Using external entropy does not interfere with contribution time. It's pulled before starting to ask for our turn to the sequencer, so drand and/or the REST API can't add a failure case or extra delays. This is important to contribute as fast as possible, and allow the sequencer to give the turn to another contributor!
Contributing to the ceremony is very easy, you only need at least one of:
kzgcli
CLI commandThe kzgcli
command is the CLI of this ceremony client, you can get it in different ways:
go
compiler. Pull this repo, and run make build
or go build -o kzgcli ./cmd/kzgcli
. This will leave the kzgcli
binary in your current folder (you might want to sudo mv kzgcli /usr/local/bin
or your PATH for convenience).You'll need a session-id
to participate in the ceremony. A session-id
is a GUID string that you'll need to pass to the kzgcli
CLI as a flag.
To get your session-id
do the following:
session_id
field with a value similar to 504d898c-e975-4e13-9a48-4f8b95d754fb
. This string is your session-id
, copy it to your clipboard.Note that this step of the process is done on an external website unrelated to this ceremony client. This website is related to the sequencer which all clients target and is managed by the Ethereum Foundation.
If you got an error trying to get your session-id
, it could be one of the following ones:
AuthErrorPayload::UserCreatedAfterDeadline
: your Ethereum address isn't matching the sequencer minimal conditions. Your Ethereum address should have sent at least 3 transactions at block 15537393. If that isn't true, you can't participate with this Ethereum address.AuthErrorPayload::InvalidAuthCode
: your request link got stale. Start the login process from scratch.AuthErrorPayload::UserAlreadyContributed
: you can only contribute once per GitHub account or Ethereum address.Optionally, you can first check the status of the lobby:
$ kzgcli status
Lobby size: 0
Number of contributions: 7915
Sequencer address: 0x5afE36d82dE8990B777f82651B96608Ec54d190d
This can provide some context around how many people are waiting for their turn to contribute and a sense of waiting times.
Contribute to the ceremony by running:
$ kzgcli contribute --session-id <paste-your-session-id>
Waiting for our turn to contribute...
It's our turn! Contributing...
Contribution ready, took 2.91s
Sending contribution...
Success!
That's it! Two files will appear in your current directory:
my_contribution.json
is exactly the contribution that was submitted to the sequencer.contribution_receipt.json
is the receipt returned by the sequencer for your contribution.If you want to leverage the optional external sources of entropy, you can provide some extra flags. Please check the External entropy section below for more details and examples.
The sequencer has a public transcript that contains everyone that has participated correctly in the ceremony. A friendly way is looking at the ceremony website contributors list.
The kzgcli contribute
command has two optional flags:
--drand
: if this flag is provided, the client will pull the latest entropy available from the drand network, which will be mixed with the CSRNG source when contributing to the ceremony.--urlrand <url>
: is a URL that the client will do a GET
request, and use the returned body bytes as entropy to be mixed with the CSRNG source when contributing to the ceremony.You can provide only one of these flags, or both at the same time:
$ kzgcli contribute --session-id <session-id> --drand --urlrand https://ihagopian.com
Pulling entropy from drand... Got it! (length: 32, round: 2578668)
Pulling entropy from https://ihagopian.com... Got it! (length: 52919)
Waiting for our turn to contribute...
It's our turn! Contributing...
Contribution ready, took 3.01s
Sending contribution...
Success!
If you want to understand in more detail how the external entropy is mixed with the CSRNG, please see this code section.
This section is only interesting if you're contributing from constrained environments.
Apart from conforming to the specification for the Powers of Tau protocol, participating in the ceremony involves interacting with the sequencer in a defined API flow. If you are contributing from a constraint environment (e.g: air-gapped or bandwidth constrained), you might be interested in narrowing down the contribution step independently from getting the state and sending the contribution.
The CLI tool provides an offline subcommand:
kzgcli offline download-state <file-path>
: downloads the current state of the ceremony from the sequencer and saves it in a file.kzgcli offline contribute <current-state-path> <contribution-path>
: opens a previously downloaded current state of the ceremony, makes the contribution and saves it in a new file.kzgcli offline send-contribution --session-id <...> <contribution-path>
: sends a previously generated contribution file to the sequencer.You might not need kzgcli offline download-state
you're pulling the current state out-of-band (e.g: direct download or the sequencer sent it to you). If that isn't the case, you can use it in an environment that has internet access (not necessarily your contribution environment).
The kzgcli offline contribute
command doesn't require internet access, and will probably be the only command you'll run in your constrained environment. This command also accepts the --urlrand
and --hex-entropy
flag if you want to pull entropy from an external source of randomness available in your environment or provided directly to the client, respectively.
The kzgcli offline send-contribution
command sends the previously generated file by kzgcli offline contribute
to the sequencer.
An example of running the first two commands:
$ kzgcli offline download-state current.json
Downloading current state... OK
Encoding and saving to current.json... OK
Saved current state in current.json
$ kzgcli offline contribute current.json new.json
Opening and parsing offline current state file...OK
Calculating contribution... OK
Success, saved contribution in new.json
In all commands you can use the --sequencer-url
flag to override the sequencer API URL to target a different sequencer than in the mainnet environment. For example, --sequencer-url "https://kzg-ceremony-sequencer-dev.fly.dev"
.
The sequencer has an API that provides a full transcript of all the contributions, so anyone can double-check the calculations to see if the result matches all the received contributions.
Having clients double-check sequencer calculations avoids having to trust that the sequencer is in the latest powers of Tau calculation.
To verify the current transcript:
$ kzgcli verify-transcript
Pulling current transcript from sequencer... OK
Verifying transcript... Valid! (took 13.08s)
Note that you don't need a --session-id
, so anyone can run the verifying logic.
You can run the tests for the repo doing make test
or go test ./... -race
.
You can run benchmarks with make bench
or go test ./... -run=none -bench=.
:
goos: linux
goarch: amd64
pkg: github.com/jsign/go-kzg-ceremony-client/contribution
cpu: AMD Ryzen 7 3800XT 8-Core Processor
BenchmarkDecodeJSON-16 1 2341867398 ns/op
BenchmarkContribute-16 1 2964969708 ns/op
As shown, in a modern desktop CPU the contribution calculation takes less than 3 seconds. The only "optimization" done in the client is leveraging multiple cores to calculate your contribution. If your CPU is ~modern, gnark-crypto library might leverage special CPU instructions such as ADX to do some elliptic curve operations way faster (no configuration needed).
While creating this ceremony client, I contributed to other repositories in the ecosystem:
eth-rs
or go-ethereum
implement the EIP. This potential bug doesn't allow this client to verify ECDSA signatures in the transcript. go-ethereum
PR)Despite this client is ready to contribute to the ceremony, there're a couple of things that it doesn't support but could if I can convince myself of some tradeoffs:
gnark-crypto
library doesn't support BLS signing yet, which is incredibly unfortunate. This doesn't allow the client to do BLS signing or verification in the transcript. This is an optional feature for clients, so it isn't a big deal or create any risk. Despite gnark-crypto has support for group multiplication and pairings, the biggest pending work for signing is implementing the hash to curve step of signing which isn't entirely trivial. As a workaround, I could use a separate BLS library to do signing/verification, but that would mean using two BLS libraries and I'd prefer to be 100% clear about which library is used in this repo for all cryptographic operations just by looking at the go.mod file.MIT