Skip to content

fix(MPC deadlock): give each RCOT consumer its own instance - #1173

Open
AdamDawidKrol wants to merge 2 commits into
tlsnotary:mainfrom
AdamDawidKrol:adam/rcot-deadlock-fix-upstream
Open

fix(MPC deadlock): give each RCOT consumer its own instance#1173
AdamDawidKrol wants to merge 2 commits into
tlsnotary:mainfrom
AdamDawidKrol:adam/rcot-deadlock-fix-upstream

Conversation

@AdamDawidKrol

@AdamDawidKrol AdamDawidKrol commented Jun 30, 2026

Copy link
Copy Markdown

MPC preprocess (crates/tlsn/src/deps/{prover,verifier}.rs) builds one SharedRCOT and hands clones to the concurrent try_join3 branches (key-exchange / record-layer / vm). A SharedRCOT only performs its single batched flush once all live clones reach the flush barrier — but the branches don't all flush in the same round, so a clone whose flush() is parked behind a sibling branch never arrives. The barrier then waits forever (alive=N, arrived=1) → an intermittent deadlock during preprocessing.

Fix:
Give each RCOT consumer its own SharedRCOT instance instead of clones of a shared one, so every barrier rendezvous is independent and can't wait on a clone parked in another branch. All senders keep using the same global delta.

…dlock

MPC preprocess shared one SharedRCOT across the try_join3 branches (ke /
record_layer / vm). The flush barrier waits for all clones to flush, but the
branches don't all flush in the same round, so a clone parked behind a sibling
branch never arrives -> rendezvous deadlock. Give each consumer its own
instance (same global delta) so every barrier rendezvous is independent.

Signed-off-by: Adam Król <adam.dawid.krol@gmail.com>
@AdamDawidKrol AdamDawidKrol changed the title fix: give each RCOT consumer its own instance to avoid preprocess deadlock fix(MPC deadlock): give each RCOT consumer its own instance Jun 30, 2026

@sinui0 sinui0 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a subtle security flaw: the kos protocol gets instantiated with the same delta correlation and the receiver has the opportunity to re-use the same base OT setup. Our kos implementation does not do domain separation by instance, so I think this gives the receiver the opportunity to outright learn (fatal) or at least sample delta.

Two options:

  1. Add instance domain separation to the kos implementation
  2. Use independent instances (run base OT twice)

@AdamDawidKrol

Copy link
Copy Markdown
Author

@sinui0 Thank you for the comment! I'll answer in a few days.

@AdamDawidKrol

AdamDawidKrol commented Jul 22, 2026

Copy link
Copy Markdown
Author

@sinui0 I reproduced the attack you described as a test in mpz: AdamDawidKrol/mpz#1

But I've been trying to see how a malicious party actually accesses the data it needs, and I can't. The recovery reads the honest sender's COT keys (keys_A ^ keys_B = delta). In the tlsn setup the malicious party is the receiver, and its own output is the choice-independent value (delta-free) — the sender folds the receiver's choice into its keys, so flipping choices across two instances just returns the same masked value, not the complementary key. So I don't see a path where prover or notary observes the delta-bearing keys.

Am I missing something?

AdamDawidKrol added a commit to AdamDawidKrol/tlsn that referenced this pull request Jul 23, 2026
Each RCOT consumer now gets its own KOS instance (deadlock fix), but they all
reuse one global delta. Give each logical consumer a distinct `instance_id`
salt so the instances are domain-separated, closing the shared-delta leak
flagged in review of tlsnotary/tlsn#1173.

Ids are assigned explicitly per consumer so prover and verifier stay matched
(sender id N pairs with receiver id N); proxy mode uses a single fixed id.
Depends on the mpz salt (AdamDawidKrol/mpz#2), pulled via the [patch] block.
AdamDawidKrol added a commit to AdamDawidKrol/tlsn that referenced this pull request Jul 23, 2026
Each RCOT consumer now gets its own KOS instance (deadlock fix), but they all
reuse one global delta. Give each logical consumer a distinct `instance_id`
salt so the instances are domain-separated, closing the shared-delta leak
flagged in review of tlsnotary/tlsn#1173.

Ids are assigned explicitly per consumer so prover and verifier stay matched
(sender id N pairs with receiver id N); proxy mode uses a single fixed id.
Depends on the mpz salt (AdamDawidKrol/mpz#2), pulled via the [patch] block.
AdamDawidKrol added a commit to AdamDawidKrol/mpz that referenced this pull request Jul 23, 2026
Demonstrates the attack from review of tlsnotary/tlsn#1173: a malicious KOS
receiver runs two extensions under the same global `delta` and reuses the same
base OT. With no per-instance domain separation the two runs derive identical
extension columns, so at any column where the receiver's internal choice bits
differ, XOR-ing the sender's (raw, correlated) keys yields `delta` exactly.

Test only; no protocol change. Runs against stock KOS.
AdamDawidKrol added a commit to AdamDawidKrol/tlsn that referenced this pull request Jul 23, 2026
Each RCOT consumer now gets its own KOS instance (deadlock fix), but they all
reuse one global delta. Give each logical consumer a distinct `instance_id`
salt so the instances are domain-separated, closing the shared-delta leak
flagged in review of tlsnotary/tlsn#1173.

Ids are assigned explicitly per consumer so prover and verifier stay matched
(sender id N pairs with receiver id N); proxy mode uses a single fixed id.
Depends on the mpz salt (AdamDawidKrol/mpz#2), pulled via the [patch] block.
Addresses the review on this PR: each RCOT consumer gets its own KOS instance
but they all share one global `delta`. Give each logical consumer a distinct
`instance_id` (matched across prover and verifier: sender id N ↔ receiver id N;
proxy uses a single fixed id) so the same-`delta` instances are
domain-separated.

Depends on the KOS `instance_id` change (privacy-ethereum/mpz#446). Until that
lands in a release, the `[patch]` block temporarily points mpz at an
alpha.6-compatible build of the same change.
@AdamDawidKrol

Copy link
Copy Markdown
Author

Domain separation pushed (privacy-ethereum/mpz#446 + commit here)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants