1use crate::chain::tracker::{ChainTracker, ListenSlot};
2use alloc::sync::Arc;
3use bitcoin::hashes::sha256::Hash as Sha256Hash;
4use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine};
5use bitcoin::secp256k1::PublicKey;
6use bitcoin::OutPoint;
7use core::fmt::{Debug, Display};
8use core::ops::Index;
9use lightning::sign::EntropySource;
10
11use crate::channel::{Channel, ChannelId, ChannelStub};
12use crate::monitor::{ChainMonitor, State as ChainMonitorState};
13use crate::node::{NodeConfig, NodeState};
14use crate::policy::validator::ValidatorFactory;
15use crate::prelude::*;
16
17pub mod model;
19
20#[derive(Clone)]
22#[must_use]
23pub struct Mutations(Vec<(String, (u64, Vec<u8>))>);
24
25impl Mutations {
26 pub fn new() -> Self {
28 Mutations(vec![])
29 }
30
31 pub fn from_vec(mutations: Vec<(String, (u64, Vec<u8>))>) -> Self {
33 Mutations(mutations)
34 }
35
36 pub fn add(&mut self, key: String, version: u64, value: Vec<u8>) {
38 self.0.push((key, (version, value)));
39 }
40
41 pub fn inner(&self) -> &Vec<(String, (u64, Vec<u8>))> {
43 &self.0
44 }
45
46 pub fn into_inner(self) -> Vec<(String, (u64, Vec<u8>))> {
48 self.0
49 }
50
51 pub fn iter(&self) -> impl Iterator<Item = &(String, (u64, Vec<u8>))> {
53 self.0.iter()
54 }
55
56 pub fn into_iter(self) -> impl Iterator<Item = (String, (u64, Vec<u8>))> {
58 self.0.into_iter()
59 }
60
61 pub fn is_empty(&self) -> bool {
63 self.0.is_empty()
64 }
65
66 pub fn len(&self) -> usize {
68 self.0.len()
69 }
70}
71
72impl Index<usize> for Mutations {
73 type Output = (String, (u64, Vec<u8>));
74
75 fn index(&self, index: usize) -> &Self::Output {
76 &self.0[index]
77 }
78}
79
80impl Debug for Mutations {
82 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
83 f.debug_list()
84 .entries(self.0.iter().map(|(k, v)| (k.clone(), (&v.0, DebugBytes(&v.1[..])))))
85 .finish()
86 }
87}
88
89#[derive(Clone, Debug)]
90pub enum Error {
92 Unavailable(String),
94 NotFound(String),
96 AlreadyExists(String),
98 Internal(String),
100 VersionMismatch,
102 SerdeError(String),
104}
105
106impl Display for Error {
107 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
108 match self {
109 Error::Unavailable(s) => write!(f, "Unavailable: {}", s),
110 Error::NotFound(s) => write!(f, "Not found: {}", s),
111 Error::AlreadyExists(s) => write!(f, "Already exists: {}", s),
112 Error::Internal(s) => write!(f, "Internal error: {}", s),
113 Error::VersionMismatch => write!(f, "Version mismatch"),
114 Error::SerdeError(s) => write!(f, "Serialization error: {}", s),
115 }
116 }
117}
118
119#[cfg(feature = "std")]
120impl std::error::Error for Error {}
121
122pub struct ChainTrackerListenerEntry(pub OutPoint, pub (ChainMonitorState, ListenSlot));
124
125pub type SignerId = [u8; 16];
127
128pub trait Persist: SendSync {
143 fn enter(&self) -> Result<(), Error> {
151 Ok(())
152 }
153
154 fn prepare(&self) -> Mutations {
158 Mutations::new()
159 }
160
161 fn commit(&self) -> Result<(), Error> {
166 Ok(())
167 }
168
169 fn put_batch_unlogged(&self, _m: Mutations) -> Result<(), Error> {
173 unimplemented!("put_batch_unlogged is only implemented for KVV persisters")
174 }
175
176 fn new_node(
178 &self,
179 node_id: &PublicKey,
180 config: &NodeConfig,
181 state: &NodeState,
182 ) -> Result<(), Error>;
183
184 fn update_node(&self, node_id: &PublicKey, state: &NodeState) -> Result<(), Error>;
186
187 fn delete_node(&self, node_id: &PublicKey) -> Result<(), Error>;
189
190 fn new_channel(&self, node_id: &PublicKey, stub: &ChannelStub) -> Result<(), Error>;
192
193 fn delete_channel(&self, node_id: &PublicKey, channel: &ChannelId) -> Result<(), Error>;
195
196 fn new_tracker(
198 &self,
199 node_id: &PublicKey,
200 tracker: &ChainTracker<ChainMonitor>,
201 ) -> Result<(), Error>;
202
203 fn update_tracker(
205 &self,
206 node_id: &PublicKey,
207 tracker: &ChainTracker<ChainMonitor>,
208 ) -> Result<(), Error>;
209
210 fn get_tracker(
212 &self,
213 node_id: PublicKey,
214 validator_factory: Arc<dyn ValidatorFactory>,
215 ) -> Result<(ChainTracker<ChainMonitor>, Vec<ChainTrackerListenerEntry>), Error>;
216
217 fn update_channel(&self, node_id: &PublicKey, channel: &Channel) -> Result<(), Error>;
222
223 fn get_channel(
225 &self,
226 node_id: &PublicKey,
227 channel_id: &ChannelId,
228 ) -> Result<model::ChannelEntry, Error>;
229
230 fn get_node_channels(
232 &self,
233 node_id: &PublicKey,
234 ) -> Result<Vec<(ChannelId, model::ChannelEntry)>, Error>;
235
236 fn update_node_allowlist(
238 &self,
239 node_id: &PublicKey,
240 allowlist: Vec<String>,
241 ) -> Result<(), Error>;
242
243 fn get_node_allowlist(&self, node_id: &PublicKey) -> Result<Vec<String>, Error>;
245
246 fn get_nodes(&self) -> Result<Vec<(PublicKey, model::NodeEntry)>, Error>;
248
249 fn clear_database(&self) -> Result<(), Error>;
251
252 fn on_initial_restore(&self) -> bool {
258 false
259 }
260
261 fn recovery_required(&self) -> bool {
265 false
266 }
267
268 fn begin_replication(&self) -> Result<Mutations, Error> {
274 unimplemented!("begin_replication is only implemented for KVV persisters")
275 }
276
277 fn signer_id(&self) -> SignerId;
279}
280
281pub struct DummyPersister;
283
284impl SendSync for DummyPersister {}
285
286#[allow(unused_variables)]
287impl Persist for DummyPersister {
288 fn new_node(
289 &self,
290 node_id: &PublicKey,
291 config: &NodeConfig,
292 state: &NodeState,
293 ) -> Result<(), Error> {
294 Ok(())
295 }
296
297 fn update_node(&self, node_id: &PublicKey, state: &NodeState) -> Result<(), Error> {
298 Ok(())
299 }
300
301 fn delete_node(&self, node_id: &PublicKey) -> Result<(), Error> {
302 Ok(())
303 }
304
305 fn new_channel(&self, node_id: &PublicKey, stub: &ChannelStub) -> Result<(), Error> {
306 Ok(())
307 }
308
309 fn delete_channel(&self, node_id: &PublicKey, channel_id: &ChannelId) -> Result<(), Error> {
310 Ok(())
311 }
312
313 fn new_tracker(
314 &self,
315 node_id: &PublicKey,
316 tracker: &ChainTracker<ChainMonitor>,
317 ) -> Result<(), Error> {
318 Ok(())
319 }
320
321 fn update_tracker(
322 &self,
323 node_id: &PublicKey,
324 tracker: &ChainTracker<ChainMonitor>,
325 ) -> Result<(), Error> {
326 Ok(())
327 }
328
329 fn get_tracker(
330 &self,
331 node_id: PublicKey,
332 validator_factory: Arc<dyn ValidatorFactory>,
333 ) -> Result<(ChainTracker<ChainMonitor>, Vec<ChainTrackerListenerEntry>), Error> {
334 Err(Error::Internal(format!("get_tracker unimplemented")))
335 }
336
337 fn update_channel(&self, node_id: &PublicKey, channel: &Channel) -> Result<(), Error> {
338 Ok(())
339 }
340
341 fn get_channel(
342 &self,
343 node_id: &PublicKey,
344 channel_id: &ChannelId,
345 ) -> Result<model::ChannelEntry, Error> {
346 Err(Error::Internal(format!("get_channel unimplemented")))
347 }
348
349 fn get_node_channels(
350 &self,
351 node_id: &PublicKey,
352 ) -> Result<Vec<(ChannelId, model::ChannelEntry)>, Error> {
353 Ok(Vec::new())
354 }
355
356 fn update_node_allowlist(
357 &self,
358 node_id: &PublicKey,
359 allowlist: Vec<String>,
360 ) -> Result<(), Error> {
361 Ok(())
362 }
363
364 fn get_node_allowlist(&self, node_id: &PublicKey) -> Result<Vec<String>, Error> {
365 Ok(Vec::new())
366 }
367
368 fn get_nodes(&self) -> Result<Vec<(PublicKey, model::NodeEntry)>, Error> {
369 Ok(Vec::new())
370 }
371
372 fn clear_database(&self) -> Result<(), Error> {
373 Ok(())
374 }
375
376 fn signer_id(&self) -> [u8; 16] {
377 unimplemented!("unused in tests")
378 }
379}
380
381pub trait SeedPersist: Sync + Send {
386 fn put(&self, key: &str, seed: &[u8]);
388 fn get(&self, key: &str) -> Option<Vec<u8>>;
390 fn list(&self) -> Vec<String>;
392}
393
394pub struct DummySeedPersister;
396
397impl SeedPersist for DummySeedPersister {
398 fn put(&self, _key: &str, _seed: &[u8]) {}
399
400 fn get(&self, _key: &str) -> Option<Vec<u8>> {
401 None
402 }
403
404 fn list(&self) -> Vec<String> {
405 Vec::new()
406 }
407}
408
409pub struct MemorySeedPersister {
411 seed: Vec<u8>,
412}
413
414impl MemorySeedPersister {
415 pub fn new(seed: Vec<u8>) -> Self {
417 Self { seed }
418 }
419}
420
421impl SeedPersist for MemorySeedPersister {
422 fn put(&self, _key: &str, _seed: &[u8]) {
423 unimplemented!()
424 }
425
426 fn get(&self, _key: &str) -> Option<Vec<u8>> {
427 Some(self.seed.clone())
428 }
429
430 fn list(&self) -> Vec<String> {
431 Vec::new()
432 }
433}
434
435#[cfg(feature = "std")]
436pub mod fs {
438 use crate::persist::SeedPersist;
439 use bitcoin::hashes::hex::FromHex;
440 use std::fs;
441 use std::path::PathBuf;
442
443 use vls_common::HexEncode;
444
445 pub struct FileSeedPersister {
449 path: PathBuf,
450 }
451
452 impl FileSeedPersister {
453 pub fn new<P: Into<PathBuf>>(path: P) -> Self {
455 Self { path: path.into() }
456 }
457
458 fn seed_path_for_key(&self, node_id: &str) -> PathBuf {
459 let mut path = self.path.clone();
460 path.push(format!("{}.seed", node_id));
461 path
462 }
463 }
464
465 impl SeedPersist for FileSeedPersister {
466 fn put(&self, key: &str, seed: &[u8]) {
467 write_seed(self.seed_path_for_key(key), seed);
468 }
469
470 fn get(&self, key: &str) -> Option<Vec<u8>> {
471 read_seed(self.seed_path_for_key(key))
472 }
473
474 fn list(&self) -> Vec<String> {
475 let mut keys = Vec::new();
476 for entry in fs::read_dir(&self.path).unwrap() {
477 let entry = entry.unwrap();
478 let path = entry.path();
479 if let Some(fileext) = path.extension() {
480 if fileext == "seed" {
481 let key = path.file_stem().unwrap().to_str().unwrap();
482 keys.push(key.to_string());
483 }
484 }
485 }
486 keys
487 }
488 }
489
490 fn write_seed(path: PathBuf, seed: &[u8]) {
491 fs::write(path.clone(), seed.to_hex()).expect("unable to write the seed to file");
492
493 let mut permission =
495 fs::metadata(path.to_owned()).expect("unable to get metadata").permissions();
496 permission.set_readonly(true);
497 fs::set_permissions(path, permission).expect("unable to set the permission to file");
498 }
499
500 fn read_seed(path: PathBuf) -> Option<Vec<u8>> {
501 fs::read_to_string(path).ok().map(|s| Vec::from_hex(s.trim()).expect("bad hex seed"))
502 }
503
504 #[cfg(test)]
505 mod test {
506 use crate::persist::SeedPersist;
507
508 use super::FileSeedPersister;
509
510 use tempfile::tempdir;
511
512 #[test]
513 fn test_list() {
514 let temp_dir = tempdir().unwrap();
515 let persister = FileSeedPersister::new(temp_dir.path());
516 let seeds = vec![("node1", b"seed1"), ("node2", b"seed2"), ("node3", b"seed3")];
517 for (node, seed) in &seeds {
518 persister.put(node, seed.as_slice());
519 }
520 let listed_seeds = persister.list();
521 assert_eq!(listed_seeds.len(), seeds.len());
522 for (node, _) in &seeds {
523 assert!(listed_seeds.contains(&node.to_string()));
524 }
525 }
526 }
527}
528
529#[derive(Clone)]
531pub struct ExternalPersistHelper {
532 shared_secret: [u8; 32],
533 last_nonce: [u8; 32],
534}
535
536impl ExternalPersistHelper {
537 pub fn new(shared_secret: [u8; 32]) -> Self {
539 Self { shared_secret, last_nonce: [0; 32] }
540 }
541
542 pub fn new_nonce(&mut self, entropy_source: &dyn EntropySource) -> [u8; 32] {
544 let nonce = entropy_source.get_secure_random_bytes();
545 self.last_nonce = nonce;
546 nonce
547 }
548
549 pub fn client_hmac(&self, kvs: &Mutations) -> [u8; 32] {
551 compute_shared_hmac(&self.shared_secret, &[0x01], kvs)
552 }
553
554 pub fn server_hmac(&self, kvs: &Mutations) -> [u8; 32] {
557 compute_shared_hmac(&self.shared_secret, &[0x02], kvs)
558 }
559
560 pub fn check_hmac(&self, kvs: &Mutations, received_hmac: Vec<u8>) -> bool {
564 let hmac = compute_shared_hmac(&self.shared_secret, &self.last_nonce, &kvs); received_hmac == hmac
566 }
567}
568
569use crate::util::debug_utils::DebugBytes;
570#[cfg(feature = "std")]
571pub use simple_entropy::SimpleEntropy;
572
573#[cfg(feature = "std")]
574mod simple_entropy {
575 use super::EntropySource;
576 use bitcoin::secp256k1::rand::{self, RngCore};
577 pub struct SimpleEntropy {}
579
580 impl SimpleEntropy {
581 pub fn new() -> Self {
583 Self {}
584 }
585 }
586
587 impl EntropySource for SimpleEntropy {
588 fn get_secure_random_bytes(&self) -> [u8; 32] {
589 let mut bytes = [0u8; 32];
590 let mut rng = rand::thread_rng();
591 rng.fill_bytes(&mut bytes);
592 bytes
593 }
594 }
595}
596
597pub fn compute_shared_hmac(secret: &[u8], nonce: &[u8], kvs: &Mutations) -> [u8; 32] {
600 let mut hmac_engine = HmacEngine::<Sha256Hash>::new(&secret);
601 hmac_engine.input(secret);
602 hmac_engine.input(nonce);
603 for (key, (version, value)) in kvs.iter() {
604 add_to_hmac(key, *version, value, &mut hmac_engine);
605 }
606 Hmac::from_engine(hmac_engine).to_byte_array()
607}
608
609fn add_to_hmac(key: &str, version: u64, value: &[u8], hmac: &mut HmacEngine<Sha256Hash>) {
610 hmac.input(key.as_bytes());
611 hmac.input(&version.to_be_bytes());
612 hmac.input(&value);
613}
614
615#[cfg(test)]
616mod tests {
617 use super::*;
618
619 #[test]
620 fn hmac_test() {
621 let shared_secret = [0; 32];
622 let mut helper = ExternalPersistHelper::new(shared_secret);
623 let mut kvs = Mutations::new();
624 kvs.add("foo".to_string(), 0, vec![0x01]);
625 kvs.add("bar".to_string(), 0, vec![0x02]);
626
627 let nonce = helper.new_nonce(&SimpleEntropy::new());
628 let hmac = compute_shared_hmac(&shared_secret, &nonce, &kvs);
629 assert!(helper.check_hmac(&kvs, hmac.to_vec()));
630
631 kvs.add("baz".to_string(), 0, vec![0x03]);
633 assert!(!helper.check_hmac(&kvs, hmac.to_vec()));
634
635 let client_secret = "2e3c1864370a95cbd641d09ae0cf7c0dd5bd0b1c30707ee5ec23775e41f19f2e";
636
637 assert_eq!(client_secret, hex::encode(helper.client_hmac(&kvs)));
638
639 let server_secret = "8fe3d55b41ae5f1c0d2b1015e3d190ff4c6d419bd792fccf8f349505031f9fec";
640
641 assert_eq!(server_secret, hex::encode(helper.server_hmac(&kvs)));
642 }
643}