Files
archy/core/archipelago/src/content_payment_admission.rs
T
archipelago fba3273c67 Add durable buyer-bound Lightning recovery and explicit native retry
Preserve original invoice preimages, private snapshots and exposure provenance; serialize rail admission and retire native-only failures before explicit replacement. Qualify 55 focused UI tests and vue-tsc. Expanded 17 engine cases and combined backend acceptance remain pending; six earlier engine cases passed in isolation. No live payment or publication.
2026-10-07 00:32:39 -04:00

45 lines
1.5 KiB
Rust

//! Outermost cross-rail admission, before wallet or payment journals.
use anyhow::Result;
use sha2::{Digest, Sha256};
use std::{fs, path::Path};
pub(crate) struct Guard {
_file: fs::File,
}
pub(crate) async fn lock(data: &Path, buyer: &str, seller: &str, content: &str) -> Result<Guard> {
let root = data.join("content-payment-admission");
let key = hex::encode(Sha256::digest(serde_json::to_vec(&(
buyer, seller, content,
))?));
tokio::task::spawn_blocking(move || {
use std::os::{
fd::AsRawFd,
unix::fs::{OpenOptionsExt, PermissionsExt},
};
fs::create_dir_all(&root)?;
anyhow::ensure!(
fs::symlink_metadata(&root)?.is_dir(),
"Invalid payment admission directory"
);
fs::set_permissions(&root, fs::Permissions::from_mode(0o700))?;
let file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.mode(0o600)
.custom_flags(libc::O_NOFOLLOW | libc::O_NONBLOCK)
.open(root.join(key))?;
anyhow::ensure!(file.metadata()?.is_file(), "Invalid payment admission lock");
loop {
if unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_EX) } == 0 {
break;
}
let error = std::io::Error::last_os_error();
if error.kind() != std::io::ErrorKind::Interrupted {
return Err(error.into());
}
}
Ok(Guard { _file: file })
})
.await?
}