Skip to content

Commit 74bb0e8

Browse files
authored
Exclude closed session from get session ids method (payjoin#806)
Failing to exclude closed sessions causes payjoin-cli to resume a sender or receiver sessions that has already reached their final state. This update also extends the v2 e2e test to verify that no sessions are resumed after completion.
2 parents f6d4a61 + 0096bb3 commit 74bb0e8

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

payjoin-cli/src/db/v2.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,12 @@ impl Database {
175175
let recv_tree = self.0.open_tree("recv_sessions")?;
176176
let mut session_ids = Vec::new();
177177
for item in recv_tree.iter() {
178-
let (key, _) = item?;
178+
let (key, value) = item?;
179+
let wrapper: SessionWrapper<ReceiverSessionEvent> =
180+
serde_json::from_slice(&value).map_err(Error::Deserialize)?;
181+
if wrapper.completed_at.is_some() {
182+
continue;
183+
}
179184
session_ids.push(SessionId::new(u64::from_be_bytes(
180185
key.as_ref().try_into().map_err(Error::TryFromSlice)?,
181186
)));
@@ -187,8 +192,15 @@ impl Database {
187192
let send_tree = self.0.open_tree("send_sessions")?;
188193
let mut session_ids = Vec::new();
189194
for item in send_tree.iter() {
190-
let (key, _) = item?;
191-
session_ids.push(SessionId::new(u64::from_be_bytes(key.as_ref().try_into().unwrap())));
195+
let (key, value) = item?;
196+
let wrapper: SessionWrapper<SenderSessionEvent> =
197+
serde_json::from_slice(&value).map_err(Error::Deserialize)?;
198+
if wrapper.completed_at.is_some() {
199+
continue;
200+
}
201+
session_ids.push(SessionId::new(u64::from_be_bytes(
202+
key.as_ref().try_into().map_err(Error::TryFromSlice)?,
203+
)));
192204
}
193205
Ok(session_ids)
194206
}

payjoin-cli/tests/e2e.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,38 @@ mod e2e {
276276
.spawn()
277277
.expect("Failed to execute payjoin-cli");
278278
check_payjoin_sent(cli_send_resumer).await?;
279+
280+
// Check that neither the sender or the receiver have sessions to resume
281+
let cli_receive_resumer = Command::new(payjoin_cli)
282+
.arg("--rpchost")
283+
.arg(&receiver_rpchost)
284+
.arg("--cookie-file")
285+
.arg(cookie_file)
286+
.arg("--db-path")
287+
.arg(&receiver_db_path)
288+
.arg("--ohttp-relays")
289+
.arg(ohttp_relay)
290+
.arg("resume")
291+
.stdout(Stdio::piped())
292+
.stderr(Stdio::inherit())
293+
.spawn()
294+
.expect("Failed to execute payjoin-cli");
295+
check_resume_has_no_sessions(cli_receive_resumer).await?;
296+
let cli_send_resumer = Command::new(payjoin_cli)
297+
.arg("--rpchost")
298+
.arg(&sender_rpchost)
299+
.arg("--cookie-file")
300+
.arg(cookie_file)
301+
.arg("--db-path")
302+
.arg(&sender_db_path)
303+
.arg("--ohttp-relays")
304+
.arg(ohttp_relay)
305+
.arg("resume")
306+
.stdout(Stdio::piped())
307+
.stderr(Stdio::inherit())
308+
.spawn()
309+
.expect("Failed to execute payjoin-cli");
310+
check_resume_has_no_sessions(cli_send_resumer).await?;
279311
Ok(())
280312
}
281313

@@ -338,6 +370,21 @@ mod e2e {
338370
Ok(())
339371
}
340372

373+
async fn check_resume_has_no_sessions(mut cli_resumer: Child) -> Result<()> {
374+
let mut stdout =
375+
cli_resumer.stdout.take().expect("Failed to take stdout of child process");
376+
let timeout = tokio::time::Duration::from_secs(10);
377+
let res = tokio::time::timeout(
378+
timeout,
379+
wait_for_stdout_match(&mut stdout, |line| line.contains("No sessions to resume.")),
380+
)
381+
.await?;
382+
383+
terminate(cli_resumer).await.expect("Failed to kill payjoin-cli");
384+
assert!(res.is_some(), "Expected no sessions to resume");
385+
Ok(())
386+
}
387+
341388
/// Read lines from `child_stdout` until `match_pattern` is found and the corresponding
342389
/// line is returned.
343390
/// Also writes every read line to tokio::io::stdout();

0 commit comments

Comments
 (0)