Skip to content

Commit 238d83b

Browse files
AdamDawidKrolWondertan
authored andcommitted
fix: give each RCOT consumer its own instance to avoid preprocess deadlock
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>
1 parent ab63237 commit 238d83b

2 files changed

Lines changed: 58 additions & 45 deletions

File tree

crates/tlsn/src/deps/prover.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,45 +54,50 @@ impl ProverMpcDeps {
5454
let mut rng = rand::rng();
5555
let delta = Delta::new(Block::random(&mut rng));
5656

57-
let base_ot_send = co::Sender::default();
58-
let base_ot_recv = co::Receiver::default();
59-
let rcot_send = kos::Sender::new(
60-
kos::SenderConfig::default(),
61-
delta.into_inner(),
62-
base_ot_recv,
63-
);
64-
let rcot_recv = kos::Receiver::new(kos::ReceiverConfig::default(), base_ot_send);
65-
let rcot_recv = ferret::Receiver::new(
66-
ferret::FerretConfig::builder()
67-
.lpn_type(ferret::LpnType::Regular)
68-
.build()
69-
.expect("ferret config is valid"),
70-
Block::random(&mut rng),
71-
rcot_recv,
72-
);
73-
74-
let rcot_send = SharedRCOTSender::new(rcot_send);
75-
let rcot_recv = SharedRCOTReceiver::new(rcot_recv);
57+
// Each RCOT consumer gets its own instance instead of sharing one. A shared
58+
// RCOT only flushes once all its clones reach the flush barrier, but the
59+
// preprocess branches (ke / record_layer / vm) don't all flush together, so a
60+
// shared instance deadlocks. All senders use the same global delta.
61+
let new_send = || {
62+
SharedRCOTSender::new(kos::Sender::new(
63+
kos::SenderConfig::default(),
64+
delta.into_inner(),
65+
co::Receiver::default(),
66+
))
67+
};
68+
let new_recv = |rng: &mut rand::rngs::ThreadRng| {
69+
let rcot_recv =
70+
kos::Receiver::new(kos::ReceiverConfig::default(), co::Sender::default());
71+
let rcot_recv = ferret::Receiver::new(
72+
ferret::FerretConfig::builder()
73+
.lpn_type(ferret::LpnType::Regular)
74+
.build()
75+
.expect("ferret config is valid"),
76+
Block::random(rng),
77+
rcot_recv,
78+
);
79+
SharedRCOTReceiver::new(rcot_recv)
80+
};
7681

7782
let mpc = cfg_select! {
7883
tlsn_insecure => { mpz_ideal_vm::IdealVm::new() }
7984
_ => {
80-
ProverMpc::new(DerandCOTSender::new(rcot_send.clone()), rng.random(), delta)
85+
ProverMpc::new(DerandCOTSender::new(new_send()), rng.random(), delta)
8186
}
8287
};
8388

8489
let zk = cfg_select! {
8590
tlsn_insecure => { mpz_ideal_vm::IdealVm::new() }
86-
_ => { ProverZk::new(Default::default(), rcot_recv.clone()) }
91+
_ => { ProverZk::new(Default::default(), new_recv(&mut rng)) }
8792
};
8893

8994
let vm = Arc::new(Mutex::new(Deap::new(tlsn_deap::Role::Leader, mpc, zk)));
9095
let mpc_tls = MpcTlsLeader::new(
9196
build_mpc_tls_config(config),
9297
ctx,
9398
vm.clone(),
94-
(rcot_send.clone(), rcot_send.clone(), rcot_send),
95-
rcot_recv,
99+
(new_send(), new_send(), new_send()),
100+
new_recv(&mut rng),
96101
);
97102

98103
Self {

crates/tlsn/src/deps/verifier.rs

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,43 +54,51 @@ impl VerifierMpcDeps {
5454
let mut rng = rand::rng();
5555

5656
let delta = Delta::random(&mut rng);
57-
let base_ot_send = co::Sender::default();
58-
let base_ot_recv = co::Receiver::default();
59-
let rcot_send = kos::Sender::new(
60-
kos::SenderConfig::default(),
61-
delta.into_inner(),
62-
base_ot_recv,
63-
);
64-
let rcot_send = ferret::Sender::new(
65-
ferret::FerretConfig::builder()
66-
.lpn_type(ferret::LpnType::Regular)
67-
.build()
68-
.expect("ferret config is valid"),
69-
Block::random(&mut rng),
70-
rcot_send,
71-
);
72-
let rcot_recv = kos::Receiver::new(kos::ReceiverConfig::default(), base_ot_send);
7357

74-
let rcot_send = SharedRCOTSender::new(rcot_send);
75-
let rcot_recv = SharedRCOTReceiver::new(rcot_recv);
58+
// Each RCOT consumer gets its own instance instead of sharing one. A shared
59+
// RCOT only flushes once all its clones reach the flush barrier, but the
60+
// preprocess branches don't all flush together, so it deadlocks. All senders
61+
// use the same global delta.
62+
let new_send = |rng: &mut rand::rngs::ThreadRng| {
63+
let rcot_send = kos::Sender::new(
64+
kos::SenderConfig::default(),
65+
delta.into_inner(),
66+
co::Receiver::default(),
67+
);
68+
let rcot_send = ferret::Sender::new(
69+
ferret::FerretConfig::builder()
70+
.lpn_type(ferret::LpnType::Regular)
71+
.build()
72+
.expect("ferret config is valid"),
73+
Block::random(rng),
74+
rcot_send,
75+
);
76+
SharedRCOTSender::new(rcot_send)
77+
};
78+
let new_recv = || {
79+
SharedRCOTReceiver::new(kos::Receiver::new(
80+
kos::ReceiverConfig::default(),
81+
co::Sender::default(),
82+
))
83+
};
7684

7785
let mpc = cfg_select! {
7886
tlsn_insecure => { mpz_ideal_vm::IdealVm::new() }
79-
_ => { VerifierMpc::new(DerandCOTReceiver::new(rcot_recv.clone())) }
87+
_ => { VerifierMpc::new(DerandCOTReceiver::new(new_recv())) }
8088
};
8189

8290
let zk = cfg_select! {
8391
tlsn_insecure => { mpz_ideal_vm::IdealVm::new() }
84-
_ => { VerifierZk::new(Default::default(), delta, rcot_send.clone()) }
92+
_ => { VerifierZk::new(Default::default(), delta, new_send(&mut rng)) }
8593
};
8694

8795
let vm = Arc::new(Mutex::new(Deap::new(tlsn_deap::Role::Follower, mpc, zk)));
8896
let mpc_tls = MpcTlsFollower::new(
8997
build_mpc_tls_config(config),
9098
ctx,
9199
vm.clone(),
92-
rcot_send,
93-
(rcot_recv.clone(), rcot_recv.clone(), rcot_recv),
100+
new_send(&mut rng),
101+
(new_recv(), new_recv(), new_recv()),
94102
);
95103

96104
Self {

0 commit comments

Comments
 (0)