|
16 | 16 | use std::fmt; |
17 | 17 | use std::str::FromStr; |
18 | 18 |
|
| 19 | +use hex_conservative::{DisplayHex, FromHex}; |
19 | 20 | use ldk_server_client::ldk_server_grpc::types::{ForwardedPayment, PageToken, Payment}; |
20 | 21 | use serde::Serialize; |
21 | 22 |
|
@@ -119,6 +120,26 @@ impl FromStr for Amount { |
119 | 120 | } |
120 | 121 | } |
121 | 122 |
|
| 123 | +/// A validated 32-byte payment preimage, parsed from a 64-character hex string. |
| 124 | +#[derive(Debug, Clone)] |
| 125 | +pub struct Preimage(pub [u8; 32]); |
| 126 | + |
| 127 | +impl Preimage { |
| 128 | + pub fn to_hex_string(&self) -> String { |
| 129 | + self.0.to_lower_hex_string() |
| 130 | + } |
| 131 | +} |
| 132 | + |
| 133 | +impl FromStr for Preimage { |
| 134 | + type Err = String; |
| 135 | + |
| 136 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 137 | + <[u8; 32]>::from_hex(s) |
| 138 | + .map(Preimage) |
| 139 | + .map_err(|_| "must be a 64-character hex string (32 bytes)".to_string()) |
| 140 | + } |
| 141 | +} |
| 142 | + |
122 | 143 | #[cfg(test)] |
123 | 144 | mod tests { |
124 | 145 | use super::*; |
@@ -185,4 +206,25 @@ mod tests { |
185 | 206 | let big = format!("{}sat", u64::MAX); |
186 | 207 | assert!(Amount::from_str(&big).is_err()); |
187 | 208 | } |
| 209 | + |
| 210 | + #[test] |
| 211 | + fn preimage_parsing_and_roundtrip() { |
| 212 | + // valid 64-char hex string |
| 213 | + let hex = "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b"; |
| 214 | + let preimage = Preimage::from_str(hex).unwrap(); |
| 215 | + assert_eq!(preimage.0, [0x2b; 32]); |
| 216 | + assert_eq!(preimage.to_hex_string(), hex); |
| 217 | + |
| 218 | + // rejects empty string |
| 219 | + assert!(Preimage::from_str("").is_err()); |
| 220 | + |
| 221 | + // rejects too short (62 chars) |
| 222 | + assert!(Preimage::from_str(&"ab".repeat(31)).is_err()); |
| 223 | + |
| 224 | + // rejects too long (66 chars) |
| 225 | + assert!(Preimage::from_str(&"ab".repeat(33)).is_err()); |
| 226 | + |
| 227 | + // rejects non-hex characters |
| 228 | + assert!(Preimage::from_str(&"zz".repeat(32)).is_err()); |
| 229 | + } |
188 | 230 | } |
0 commit comments