Skip to content

Add directory fallback behavior#1695

Merged
DanGould merged 1 commit into
payjoin:masterfrom
benalleng:fallback-directories
Jun 30, 2026
Merged

Add directory fallback behavior#1695
DanGould merged 1 commit into
payjoin:masterfrom
benalleng:fallback-directories

Conversation

@benalleng

Copy link
Copy Markdown
Collaborator

This adds the ability for a backup directory to be chosen by the receiver incase of a failure on the ohttp key fetch.

As well now that there is Relay and directory management the Struct is better suited as MailroomManager.

Supersedes #1294

relates to the directory fallbacks in #1007

Pull Request Checklist

Please confirm the following before requesting review:

This adds the ability for a backup directory to be chosen by the
receiver incase of a failure on the ohttp key fetch.

As well now that there is Relay and directory management the Struct is
better suited as MailroomManager.

Co-authored-by: Oladapo Oyindamola <111582215+0xZaddyy@users.noreply.github.com>
@benalleng benalleng marked this pull request as ready for review June 29, 2026 16:37
@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 28387717154

Coverage decreased (-0.002%) to 85.515%

Details

  • Coverage decreased (-0.002%) from the base build.
  • Patch coverage: 16 uncovered changes across 2 files (36 of 52 lines covered, 69.23%).
  • 1 coverage regression across 1 file.

Uncovered Changes

File Changed Covered %
payjoin-cli/src/app/v2/ohttp.rs 37 22 59.46%
payjoin-cli/src/app/v2/mod.rs 2 1 50.0%
Total (3 files) 52 36 69.23%

Coverage Regressions

1 previously-covered line in 1 file lost coverage.

File Lines Losing Coverage Coverage
payjoin-cli/src/app/config.rs 1 81.01%

Coverage Stats

Coverage Status
Relevant Lines: 15161
Covered Lines: 12965
Line Coverage: 85.52%
Coverage Strength: 361.12 hits per line

💛 - Coveralls

@DanGould DanGould 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.

utACK f5906fe

Thank you @0xZaddyy and @benalleng. This one seems a little bit debt-y to me, but that's fine to ship payjoin-cli-1.0 by me if we're explicit about it & are looking to follow up with something like #1696

Comment on lines +282 to +297
let (directory, ohttp_keys) = loop {
let directory = self.mailroom_manager.choose_directory()?;
match self
.mailroom_manager
.unwrap_ohttp_keys_or_else_fetch_from_directory(&directory)
.await
{
Ok(keys) => break (directory, keys.ohttp_keys),
Err(e) => {
tracing::debug!("Directory {directory} failed: {e:#}");
self.mailroom_manager.add_failed_directory(directory);
self.mailroom_manager.clear_failed_relays();
continue;
}
}
};

@DanGould DanGould Jun 30, 2026

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.

Really seems like a function deserving its own documentation. A good time to refactor this ~tech debt out would be #1035.

I had to check, but it looks like this will fail if all directories do when choose_directory()? throws, I think. Originally I was concerned this might loop forever, but it looks like it will close.

Comment thread payjoin-cli/src/app/v2/ohttp.rs
Comment on lines +66 to +82
pub fn choose_directory(&self) -> Result<Url> {
use payjoin::bitcoin::secp256k1::rand::prelude::SliceRandom;
let directories = &self.config.v2()?.pj_directories;
let failed_directories =
self.failed_directories.lock().expect("Lock should not be poisoned");
let remaining_directories: Vec<_> =
directories.iter().filter(|d| !failed_directories.contains(d)).cloned().collect();

if remaining_directories.is_empty() {
return Err(anyhow!("No valid directories available"));
}

remaining_directories
.choose(&mut payjoin::bitcoin::key::rand::thread_rng())
.cloned()
.ok_or_else(|| anyhow!("Failed to select from remaining directories"))
}

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.

NBD, I duplicate first as well, just noticing: could be DRY'd up with the choose_relay function

@DanGould DanGould merged commit 00a9783 into payjoin:master Jun 30, 2026
13 checks passed
@ValeraFinebits

Copy link
Copy Markdown
Contributor

@bc1cindy @benalleng
#1547 documents "pick one relay at random per request", while #1695 seems to implement randomized multi-relay / multi-directory fallback within a single request flow. I'm fine with the reliability tradeoff if that's intentional, just want to confirm whether the CLI is now expected to prioritize availability over the stricter privacy guidance, or whether the docs should be updated to describe that distinction explicitly.

@benalleng

benalleng commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

So this is just the addition for the directory fallback at the session start for the receiver. Once a directory is chosen for a session it cannot be changed as the counterparty would no longer be abel to find your messages. Per request randomization was implemented in #1628 which forces a new ohhtp relay to be used per request only as a proxy for messages to the shared directory.

Is that what you are asking?

@ValeraFinebits

Copy link
Copy Markdown
Contributor

So this is just the addition for the directory fallback at the session start for the receiver. Once a directory is chosen for a session it cannot be changed as the counterparty would no longer be abel to find your messages. Per request randomization was implemented in #1628 which forces a new ohhtp relay to be used per request only as a proxy for messages to the shared directory.

Is that what you are asking?

Yes, that clarifies it, thanks @benalleng

I was mainly checking whether #1695 was intentionally changing the privacy guidance described in #1547, but with your explanation it sounds like these are separate concerns:

  • relay selection is still randomized per request,
  • directory fallback only happens when initializing the receiver session,
  • and once a directory is chosen for that session it stays fixed so the counterparty can keep finding the messages.

That makes sense to me.

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.

4 participants