From c6c8ddb7e4117628549afdb382b0d46f830f242d Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 8 Nov 2026 03:36:26 +0100 Subject: crash: show and verify the revealed seed in the TUI and GUI The crash board gained a fairness line: the short commit while the round runs, then the short seed marked verified when sha256(seed) and the recomputed crash point both match. The terminal board grew from six to seven lines and the GUI sidebar shows the same values. --- src/client/games/crash.rs | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'src/client/games') diff --git a/src/client/games/crash.rs b/src/client/games/crash.rs index affb642..c6dbbd5 100644 --- a/src/client/games/crash.rs +++ b/src/client/games/crash.rs @@ -1,7 +1,8 @@ use super::traits::{Game, GameState}; use crate::client::view::CrashView; +use crate::crash::{crash_point_from_seed, seed_from_hex, verify_seed}; -pub const CRASH_BOARD_LINES: usize = 6; +pub const CRASH_BOARD_LINES: usize = 7; pub struct CrashGame; @@ -29,6 +30,38 @@ impl CrashGame { } } + /// Commitment line. The seed is shown only after the round ends, and the + /// client recomputes both the hash and the crash point. + fn fairness_text(view: &CrashView) -> String { + let short = |hash: &str| { + hash.char_indices() + .nth(12) + .map(|(index, _)| &hash[..index]) + .unwrap_or(hash) + .to_string() + }; + let Some(commit) = view.commit.as_deref() else { + return "Commit: —".to_string(); + }; + let Some(seed) = view.seed.as_deref() else { + return format!("Commit {} Seed hidden until the round ends", short(commit)); + }; + let commit_ok = verify_seed(seed, commit); + let point_ok = seed_from_hex(seed) + .map(|bytes| { + let expected = crash_point_from_seed(&bytes); + view.crash_point + .map(|point| (expected - point).abs() < 1e-9) + .unwrap_or(false) + }) + .unwrap_or(false); + if commit_ok && point_ok { + format!("Commit {} Seed {} verified", short(commit), short(seed)) + } else { + format!("Commit {} Seed {} VERIFICATION FAILED", short(commit), short(seed)) + } + } + fn controls(view: &CrashView) -> &'static str { if view.status == "running" { "[C] Cash out [Q] Forfeit" @@ -46,19 +79,21 @@ impl CrashGame { if let Some(error) = &view.error { return format!( - "=== CRASH ===\r\nBalance: {balance} Kr Bet: {} Kr\r\n\r\nERROR: {error}\r\n\r\n[SPACE] Play [+/=/-] Bet [Q] Quit", - view.bet + "=== CRASH ===\r\nBalance: {balance} Kr Bet: {} Kr\r\n\r\nERROR: {error}\r\n\r\n{}\r\n[SPACE] Play [+/=/-] Bet [Q] Quit", + view.bet, + Self::fairness_text(view) ); } format!( - "=== CRASH ===\r\nBalance: {} Kr Bet: {} Kr\r\nMultiplier: {:.2}x\r\nPotential: {} Kr\r\n{}\r\n{}", + "=== CRASH ===\r\nBalance: {} Kr Bet: {} Kr\r\nMultiplier: {:.2}x\r\nPotential: {} Kr\r\n{}\r\n{}\r\n{}", balance, view.bet, view.multiplier, view.potential, Self::status_text(view), - Self::controls(view) + Self::controls(view), + Self::fairness_text(view) ) } } -- cgit v1.2.3