Silence Laboratories Learn more

Benchmark · 2-of-3 threshold signatures

DKLS23 vs CGGMP21 — benchmark comparison

Two 2-of-3 threshold signature protocols, benchmarked on plain Ubuntu VMs in Google Cloud. DKLS23 runs from a pinned trio image; CGGMP21 is LFDT-Lockness/cggmp21@b870883.

DKG means generating a key. DSG means signing with a key that already exists. DKG and DSG were measured on three VM sizes at loads from 1 to 200 requests in flight, then again with bandwidth capped, with delay added between the machines, and with the three machines spread across three regions. Presigning was measured separately on four VM sizes.

The load always comes from a separate machine that is not one of the three parties. How this was run covers the setup and where each number comes from.

01

One request at a time

One request per row, no concurrency, no repeats. All four runs are on n2d-standard-16 in one region. Files: oc-single-dkls-dkg.csv, oc-single-dkls-dsg.csv, oc-single-cggmp-dkg.csv, oc-single-cggmp-dsg.csv.

DKLS23 CGGMP21
What each column is
Request latency
Timed by the machine sending the request, for one request.
Party-VM TX and RX
Bytes leaving and arriving at the party VMs, read from the network counters before and after the run. TX counts each packet once, where it was sent. RX is there as a cross-check on TX, not as a second measurement.
How many VMs are read
For CGGMP all three party VMs are read and added up. For DKLS only the VM running the client-party adapter is read, so its rows are one machine, not three. Compare rows within a protocol, not across the two.
Three-VM CPU
CPU counters from the three VMs, again read before and after.
What the bytes include
The small HTTP request and reply, plus the traffic from reading the counters. These are not pure protocol bytes.
One sample each
Every row is a single run. The p50, p90 and p99 columns in those four files all repeat the same one number, so there is no distribution to read.
One note on the CGGMP key generation row: its Paillier primes were built when the process started, so that work is not inside the time shown.
One region
02

Signing by VM size

Signing at 1, 50, 100 and 200 requests in flight, on three VM sizes, one region, no bandwidth limit. The first three charts show p99 latency by VM size; the last two show throughput.

DKLS23 p99 CGGMP21 p99
03

Key generation

Key generation on the same three VM sizes: one request, then 30 seconds of 5 and 10 at a time. Here CGGMP builds its Paillier aux info during every key generation. Section 04 shows what happens when that work is done once and reused. DKLS has no such step, so its numbers are the same in both sections.

DKLS23, single CGGMP21, single
04

Key generation with reused aux info

CGGMP needs Paillier aux info — a key and some proofs — before it can generate a key. That work can be done once per party and saved, so later key generations skip it, which is how a production deployment would run it. Measured with bench-node --reuse-aux. Cold rows build the aux info every time, as in section 03. Warm rows reuse it.

aux reused (warm) aux per keygen (cold)
05

Bandwidth caps

Signing with 100 requests in flight on n2d-standard-16, with each VM's outbound bandwidth capped at 20, 10, 5, 3, 2 and 1 Mbit/s. Scope update (2026-09-11): sub-gigabit caps are out of scope — the production baseline starts at 5 Gbit/s, so these points are archived for reference only, not a control point.

DKLS23 CGGMP21
06

Added network delay

Signing with 50 requests in flight on n2d-standard-16, with delay added between the VMs using tc netem. The ~0 point is the real network in one zone, from section 02. This adds delay and nothing else: no jitter, no packet loss, no bandwidth change. Section 07 has real multi-region numbers.

DKLS23 CGGMP21
Three regions
07

Across three regions

The three VMs in europe-west3-a, europe-north1-a and us-east1-b, n2d-standard-16, no bandwidth limit. A real network this time, not added delay.

DKLS23 CGGMP21
Presigning
08

Presigning, offline and online

Presigning produces a presignature with no message attached; the online finish phase consumes one to sign. Both protocols use two of the three parties per operation. Every row below is sequential — one request at a time — on n2d-standard-16 in one region, with each party VM's network counters read before and after the run and corrected for 120 seconds of measured idle traffic.

Interactive calculator. Compare protocol, pool size, VM size, concurrency, and topology in the presign calculator.
DKLS23 CGGMP21

Then the same harness ran 100,000 sequential DKLS presignatures on the same trio: zero errors in 6,398.0 s (1 h 46 m 38 s), 15.63 per second, average 63.86 ms and p99 65.70 ms. Per-party-VM traffic, net of idle:

Throughput vs concurrency (measured pools only)

Test grid: 10,000 and 100,000 presignatures, 4/16/32 vCPU, concurrency 1, 10, 50, 200, 400 and 800, same region. Every point in the two chart sets and in the table is a completed timed pool run on the current binary, except the rows marked †, which are estimates derived from measured rates. A red F marks the measured failure boundary: a setting where completed runs started returning request errors.

F = concurrency where measured runs started erroring
DKLS23 CGGMP21

† estimated pool time derived from the measured 10k run (×10) or the measured c=1 rate; not a completed 100k run.

Cross-region pools (west3 / north1 / us-east1)

The same presign grid across three regions. DKLS signing legs cross the Atlantic (client adapter in us-east1-b calling the trio in europe-west3-a and europe-north1-a); CGGMP signs between the two European VMs. Measured cells only, table form for now; the cross-region chart set lands with the calculator refresh.

Bandwidth headroom

One DKLS23 presignature costs about 120 KiB of aggregate party egress, one CGGMP21 presignature about 88 KiB. A 1 Gbit/s link carries roughly 1,020 DKLS presigns/s, 2.3x the fastest clean DKLS cell in the grid (439/s) and 3.2x the fastest sustained 100k pool (316/s, about 0.31 Gbit/s). Compute saturates before bandwidth on any link of 1 Gbit/s or better. CGGMP21 tops out at 10.7/s, about 7.7 Mbit/s, two orders of magnitude below any network constraint.

Compute and bandwidth per transaction (32 vCPU, same region)

ProtocolOperationCompute per txBytes per tx (one-way, all parties)Sustained rateTraffic at measured rate
DKLS23Presigning0.11 core-s120 KiB316 presigns/s0.31 Gbit/s
DKLS23Online signing round~7.5 ms p504.4 KB
CGGMP21Presigning3.0 core-s88 KiB10.7 presigns/s7.7 Mbit/s
CGGMP21Online signing round~26 ms p504–7 KB

Per presign, CGGMP21 spends ≈27× more compute and moves ≈28% fewer bytes. Both online rounds are small (4–7 KB) and finish in tens of milliseconds.

Bytes vs the published dkls23 figures (per party)

Operationdkls23 site (raw)Our measurement (end-to-end)Note
Presigning(t−1)·57 KB = 57 KB~61 KB+7%, framing
Online signing96 B~2.2 KBharness transport (~23×); the protocol itself is 96 B
DKG(n−1)·53 KB = 106 KB~150 KBextra trio rounds + framing

Our end-to-end counters include WebSocket/HTTP framing, bincode headers and message signing; the published figures are protocol payload only.

Method
09

How this was run

Each protocol runs three parties, one per VM. A fourth machine sends the load and is not a party.

VMWhat it runs for CGGMP21What it runs for DKLS23
VM0party 0, the hubtrio-svc-first
VM1party 1, a leaftrio-svc-second
VM2party 2, a leafthe client party — an HTTP adapter around trio-client
The load generator
A fourth machine sends every request. It is not a party, so its CPU time and its network traffic are left out of every number on this page. Two machines were used for this: a driver VM inside the same VPC, and the operator's own workstation. VM2 is always a party, never the generator.
Where the numbers come from
Each party VM serves a /metrics page with CPU and network-interface counters. The runner reads it before and after a run and reports the difference.
How many VMs each protocol's counters cover
For CGGMP the runner reads all three party VMs and adds them up. For DKLS it reads only the VM running the client-party adapter. So a DKLS CPU or byte figure is one machine and a CGGMP one is three machines added together. They are not directly comparable, and the difference is larger for CPU than the numbers alone suggest.
What RPS means
Successful operations divided by how long the run lasted, timed at the generator, with a fixed number of requests in flight the whole time.
What counts as one request
One CGGMP key generation is three requests sent at once, one CGGMP signature is two (the 2-of-3 signer set), and one DKLS operation is one call to the adapter.
How CGGMP talks between parties
One websocket per run of the protocol, carrying raw bincode frames, with a barrier between rounds and a thread dedicated to accepting leaf connections. Paillier primes are made when the process starts, not during a request.
How DKLS talks between parties
Its own trio relay. It was not changed at any point in this work.
Failed requests
Five cells have one or two failures out of hundreds or thousands of requests. Every other cell has none. The counts are in each table's Success column.
The same everywhere
2-of-3 (t = 2, n = 3), plain Ubuntu 24.04, no Confidential Space, three parties on three VMs of the same size.

Get in touch

Unlock privacy preserving collaboration with Silence Laboratories

Book a Call