1use crate::credentials::{RuneProvider, TlsConfigProvider};
2use crate::metrics::{savings_percent, signer_state_response_wire_bytes};
3use crate::pb::scheduler::{scheduler_client::SchedulerClient, NodeInfoRequest, UpgradeRequest};
4use crate::pb::scheduler::{
5 signer_request, signer_response, ApprovePairingRequest, ApprovePairingResponse, SignerResponse,
6};
7use crate::pb::{node_client::NodeClient, Empty, HsmRequest, HsmRequestContext, HsmResponse};
11use crate::pb::{PendingRequest, SignerStateEntry};
12use crate::runes;
13use crate::signer::resolve::Resolver;
14use crate::tls::TlsConfig;
15use crate::{node, node::Client};
16use anyhow::{anyhow, Result};
17use base64::engine::general_purpose;
18use base64::Engine;
19use bytes::BufMut;
20use http::uri::InvalidUri;
21use lightning_signer::bitcoin::hashes::Hash;
22use lightning_signer::bitcoin::secp256k1::{
23 ecdsa::Signature as SecpSignature, Message as SecpMessage, PublicKey, Secp256k1, SecretKey,
24};
25use lightning_signer::bitcoin::Network;
26use lightning_signer::node::NodeServices;
27use lightning_signer::policy::filter::FilterRule;
28use lightning_signer::util::crypto_utils;
29use log::{debug, error, info, trace, warn};
30use ring::digest::{digest, SHA256};
31use ring::signature::{UnparsedPublicKey, ECDSA_P256_SHA256_FIXED};
32use runeauth::{Condition, Restriction, Rune, RuneError};
33use std::convert::{TryFrom, TryInto};
34use std::sync::Arc;
35use std::sync::Mutex;
36use std::time::SystemTime;
37use tokio::sync::mpsc;
38use tokio::time::{sleep, Duration};
39use tokio_stream::wrappers::ReceiverStream;
40use tonic::transport::{Endpoint, Uri};
41use tonic::{Code, Request};
42use vls_protocol::msgs::{DeBolt, HsmdInitReplyV4};
43use vls_protocol::serde_bolt::Octets;
44use vls_protocol_signer::approver::{Approve, MemoApprover};
45use vls_protocol_signer::handler;
46use vls_protocol_signer::handler::Handler;
47
48mod approver;
49mod auth;
50pub mod model;
51mod report;
52mod resolve;
53
54const VERSION: &str = "v25.12";
55const GITHASH: &str = env!("GIT_HASH");
56const RUNE_VERSION: &str = "gl0";
57const RUNE_DERIVATION_SECRET: &str = "gl-commando";
59const STATE_DERIVATION_SECRET: &str = "greenlight/state-signing/v1";
60const STATE_SIGNING_DOMAIN: &[u8] = b"greenlight/state-signing/v1\0";
61const STATE_SIGNATURE_OVERRIDE_ACK: &str = "I_ACCEPT_OPERATOR_ASSISTED_STATE_OVERRIDE";
62const COMPACT_SIGNATURE_LEN: usize = 64;
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
65pub enum StateSignatureMode {
66 Off,
67 Soft,
68 Hard,
69}
70
71impl Default for StateSignatureMode {
72 fn default() -> Self {
73 Self::Soft
74 }
75}
76
77#[derive(Clone, Debug, PartialEq, Eq)]
78pub struct StateSignatureOverrideConfig {
79 pub ack: String,
80 pub note: Option<String>,
81}
82
83#[derive(Clone, Debug, Default)]
84pub struct SignerConfig {
85 pub state_signature_mode: StateSignatureMode,
86 pub state_signature_override: Option<StateSignatureOverrideConfig>,
87}
88
89#[derive(Debug, Default)]
90struct OverrideSignatureUsage {
91 missing_keys: Vec<String>,
92 invalid_keys: Vec<String>,
93}
94
95impl OverrideSignatureUsage {
96 fn is_used(&self) -> bool {
97 !self.missing_keys.is_empty() || !self.invalid_keys.is_empty()
98 }
99}
100
101#[derive(Clone)]
102pub struct Signer {
103 secret: [u8; 32],
104 state_signing_secret: SecretKey,
105 state_signing_pubkey: PublicKey,
106 state_signature_mode: StateSignatureMode,
107 state_signature_override_enabled: bool,
108 state_signature_override_note: Option<String>,
109 master_rune: Rune,
110 services: NodeServices,
111 tls: TlsConfig,
112 id: Vec<u8>,
113
114 init: Vec<u8>,
116
117 network: Network,
118 state: Arc<Mutex<crate::persist::State>>,
119}
120
121#[derive(thiserror::Error, Debug)]
122pub enum Error {
123 #[error("could not connect to scheduler: ")]
124 SchedulerConnection(),
125
126 #[error("scheduler returned an error: {0}")]
127 Scheduler(tonic::Status),
128
129 #[error("could not connect to node: {0}")]
130 NodeConnection(#[from] tonic::transport::Error),
131
132 #[error("connection to node lost: {0}")]
133 NodeDisconnect(#[from] tonic::Status),
134
135 #[error("authentication error: {0}")]
136 Auth(crate::Error),
137
138 #[error("scheduler returned faulty URI: {0}")]
139 InvalidUri(#[from] InvalidUri),
140
141 #[error("resolver error: request {0:?}, context: {1:?}")]
142 Resolver(Vec<u8>, Vec<crate::signer::model::Request>),
143
144 #[error("error asking node to be upgraded: {0}")]
145 Upgrade(tonic::Status),
146
147 #[error("protocol error: {0}")]
148 Protocol(#[from] vls_protocol::Error),
149
150 #[error("other: {0}")]
151 Other(anyhow::Error),
152
153 #[error("could not approve pairing request: {0}")]
154 ApprovePairingRequestError(String),
155}
156
157impl Signer {
158 pub fn new<T>(secret: Vec<u8>, network: Network, creds: T) -> Result<Signer, anyhow::Error>
159 where
160 T: TlsConfigProvider,
161 {
162 Self::new_with_config(secret, network, creds, SignerConfig::default())
163 }
164
165 pub fn new_with_config<T>(
166 secret: Vec<u8>,
167 network: Network,
168 creds: T,
169 config: SignerConfig,
170 ) -> Result<Signer, anyhow::Error>
171 where
172 T: TlsConfigProvider,
173 {
174 use lightning_signer::policy::{
175 filter::PolicyFilter, simple_validator::SimpleValidatorFactory,
176 };
177 use lightning_signer::signer::ClockStartingTimeFactory;
178 use lightning_signer::util::clock::StandardClock;
179
180 info!("Initializing signer for {VERSION} ({GITHASH}) (VLS)");
181 let state_signature_mode = config.state_signature_mode;
182 let (state_signature_override_enabled, state_signature_override_note) =
183 match config.state_signature_override {
184 Some(override_config) => {
185 if state_signature_mode == StateSignatureMode::Off {
186 return Err(anyhow!(
187 "state signature override is incompatible with state signature mode off"
188 ));
189 }
190
191 if override_config.ack != STATE_SIGNATURE_OVERRIDE_ACK {
192 return Err(anyhow!(
193 "invalid state signature override ack, expected {}",
194 STATE_SIGNATURE_OVERRIDE_ACK
195 ));
196 }
197
198 let note = override_config
199 .note
200 .and_then(|n| {
201 let trimmed = n.trim().to_string();
202 if trimmed.is_empty() {
203 None
204 } else {
205 Some(trimmed)
206 }
207 });
208 (true, note)
209 }
210 None => (false, None),
211 };
212 let mut sec: [u8; 32] = [0; 32];
213 sec.copy_from_slice(&secret[0..32]);
214
215 let persister = Arc::new(crate::persist::MemoryPersister::new());
218 let mut policy =
219 lightning_signer::policy::simple_validator::make_default_simple_policy(network);
220
221 policy.filter = PolicyFilter::default();
222 policy.filter.merge(PolicyFilter {
223 rules: vec![
225 FilterRule::new_warn("policy-channel-safe-type-anchors"),
226 FilterRule::new_warn("policy-routing-balanced"),
227 FilterRule::new_warn("policy-commitment-retry-same"),
228 ],
229 });
230
231 {
235 policy.max_feerate_per_kw = 150_000;
236 policy.filter.merge(PolicyFilter {
237 rules: vec![
238 FilterRule::new_warn("policy-commitment-fee-range"),
239 FilterRule::new_warn("policy-mutual-fee-range"),
240 ],
241 });
242 }
243
244 policy.filter.merge(PolicyFilter {
245 rules: vec![
247 FilterRule::new_warn("policy-routing-balanced"),
248 FilterRule::new_warn("policy-htlc-fee-range"),
249 ],
250 });
251
252 policy.filter.merge(PolicyFilter {
254 rules: vec![
255 FilterRule::new_warn("policy-revoke-new-commitment-signed"),
259 FilterRule::new_warn("policy-other"),
264 ],
265 });
266
267 policy.max_invoices = 10_000usize;
270
271 policy.max_routing_fee_msat = 1_000_000;
274
275 let validator_factory = Arc::new(SimpleValidatorFactory::new_with_policy(policy));
276 let starting_time_factory = ClockStartingTimeFactory::new();
277 let clock = Arc::new(StandardClock());
278
279 let services = NodeServices {
280 validator_factory,
281 starting_time_factory,
282 persister: persister.clone(),
283 trusted_oracle_pubkeys: vec![],
284 clock,
285 };
286
287 let mut handler = handler::HandlerBuilder::new(network, 0 as u64, services.clone(), sec)
288 .build()
289 .map_err(|e| anyhow!("building root_handler: {:?}", e))?;
290
291 let init = Signer::initmsg(&mut handler)?;
295
296 let init = HsmdInitReplyV4::from_vec(init)
297 .map_err(|e| anyhow!("Failed to parse init message as HsmdInitReplyV4: {:?}", e))?;
298
299 let id = init.node_id.0.to_vec();
300 use vls_protocol::msgs::SerBolt;
301 let init = init.as_vec();
302
303 let rune_secret = crypto_utils::hkdf_sha256(&sec, RUNE_DERIVATION_SECRET.as_bytes(), &[]);
306 let mr = Rune::new_master_rune(&rune_secret, vec![], None, Some(RUNE_VERSION.to_string()))?;
307 let state_signing_secret = Self::derive_state_signing_secret(&sec)?;
308 let state_signing_pubkey =
309 PublicKey::from_secret_key(&Secp256k1::signing_only(), &state_signing_secret);
310
311 trace!("Initialized signer for node_id={}", hex::encode(&id));
312 Ok(Signer {
313 secret: sec,
314 state_signing_secret,
315 state_signing_pubkey,
316 state_signature_mode,
317 state_signature_override_enabled,
318 state_signature_override_note,
319 master_rune: mr,
320 services,
321 tls: creds.tls_config(),
322 id,
323 init,
324 network,
325 state: persister.state(),
326 })
327 }
328
329 fn init_handler(&self) -> Result<handler::InitHandler, anyhow::Error> {
330 let h = handler::HandlerBuilder::new(
331 self.network,
332 0 as u64,
333 self.services.clone(),
334 self.secret,
335 )
336 .build()
337 .map_err(|e| anyhow!("building root_handler: {:?}", e))?;
338
339 Ok(h)
340 }
341
342 fn handler(&self) -> Result<handler::RootHandler, anyhow::Error> {
343 let mut h = self.init_handler()?;
344 h.handle(Signer::initreq())
345 .map_err(|e| anyhow!("Failed to handle hsmd_init message: {:?}", e))?;
346 Ok(h.into())
347 }
348
349 fn handler_with_approver(
350 &self,
351 approver: Arc<dyn Approve>,
352 ) -> Result<handler::RootHandler, Error> {
353 let mut h = handler::HandlerBuilder::new(
354 self.network,
355 0 as u64,
356 self.services.clone(),
357 self.secret,
358 )
359 .approver(approver)
360 .build()
361 .map_err(|e| crate::signer::Error::Other(anyhow!("Could not create handler: {:?}", e)))?;
362 h.handle(Signer::initreq())
363 .map_err(|e| Error::Other(anyhow!("Failed to handle hsmd_init message: {:?}", e)))?;
364 Ok(h.into())
365 }
366
367 fn initreq() -> vls_protocol::msgs::Message {
369 vls_protocol::msgs::Message::HsmdInit(vls_protocol::msgs::HsmdInit {
370 key_version: vls_protocol::model::Bip32KeyVersion {
371 pubkey_version: 0,
372 privkey_version: 0,
373 },
374 chain_params: lightning_signer::bitcoin::BlockHash::all_zeros(),
375 encryption_key: None,
376 dev_privkey: None,
377 dev_bip32_seed: None,
378 dev_channel_secrets: None,
379 dev_channel_secrets_shaseed: None,
380 hsm_wire_min_version: 4,
381 hsm_wire_max_version: 6,
382 })
383 }
384
385 fn initmsg(handler: &mut vls_protocol_signer::handler::InitHandler) -> Result<Vec<u8>, Error> {
386 let (_req, response) = handler
387 .handle(Signer::initreq())
388 .map_err(|e| Error::Other(anyhow!("Failed to handle init request: {:?}", e)))?;
389 Ok(response.map(|a| a.as_vec()).unwrap_or_default())
390 }
391
392 fn derive_state_signing_secret(secret: &[u8; 32]) -> Result<SecretKey, anyhow::Error> {
393 let key = crypto_utils::hkdf_sha256(secret, STATE_DERIVATION_SECRET.as_bytes(), &[]);
394 SecretKey::from_slice(&key).map_err(|e| anyhow!("failed to derive state signing key: {e}"))
395 }
396
397 fn state_signature_digest(key: &str, version: u64, value: &[u8]) -> [u8; 32] {
398 let mut payload =
399 Vec::with_capacity(STATE_SIGNING_DOMAIN.len() + 4 + key.len() + 8 + 4 + value.len());
400 payload.extend_from_slice(STATE_SIGNING_DOMAIN);
401 payload.extend_from_slice(&(key.len() as u32).to_be_bytes());
402 payload.extend_from_slice(key.as_bytes());
403 payload.extend_from_slice(&version.to_be_bytes());
404 payload.extend_from_slice(&(value.len() as u32).to_be_bytes());
405 payload.extend_from_slice(value);
406 let hash = digest(&SHA256, &payload);
407 let mut out = [0u8; 32];
408 out.copy_from_slice(hash.as_ref());
409 out
410 }
411
412 fn sign_state_payload(
413 &self,
414 key: &str,
415 version: u64,
416 value: &[u8],
417 ) -> Result<Vec<u8>, anyhow::Error> {
418 let digest = Self::state_signature_digest(key, version, &value);
419 let msg = SecpMessage::from_digest_slice(&digest).map_err(|e| {
420 anyhow!(
421 "failed to build state signature digest for key {}: {}",
422 key,
423 e
424 )
425 })?;
426 let sig = Secp256k1::signing_only().sign_ecdsa(&msg, &self.state_signing_secret);
427 Ok(sig.serialize_compact().to_vec())
428 }
429
430 fn verify_state_entry_signature(&self, entry: &SignerStateEntry) -> Result<(), anyhow::Error> {
431 if entry.signature.len() != COMPACT_SIGNATURE_LEN {
432 return Err(anyhow!(
433 "expected {} signature bytes, got {}",
434 COMPACT_SIGNATURE_LEN,
435 entry.signature.len()
436 ));
437 }
438 let digest = Self::state_signature_digest(&entry.key, entry.version, &entry.value);
439 let msg = SecpMessage::from_digest_slice(&digest)
440 .map_err(|e| anyhow!("failed to build digest message: {}", e))?;
441 let sig = SecpSignature::from_compact(&entry.signature)
442 .map_err(|e| anyhow!("invalid compact signature: {}", e))?;
443 Secp256k1::verification_only()
444 .verify_ecdsa(&msg, &sig, &self.state_signing_pubkey)
445 .map_err(|e| anyhow!("signature verification failed: {}", e))?;
446 Ok(())
447 }
448
449 fn state_signature_mode_label(&self) -> &'static str {
450 match self.state_signature_mode {
451 StateSignatureMode::Off => "off",
452 StateSignatureMode::Soft => "soft",
453 StateSignatureMode::Hard => "hard",
454 }
455 }
456
457 fn inspect_incoming_state_signatures(
458 &self,
459 entries: &[SignerStateEntry],
460 ) -> Result<OverrideSignatureUsage, Error> {
461 if self.state_signature_mode == StateSignatureMode::Off {
462 return Ok(OverrideSignatureUsage::default());
463 }
464
465 let mut usage = OverrideSignatureUsage::default();
466 let mut first_error: Option<anyhow::Error> = None;
467
468 for entry in entries.iter() {
469 if entry.signature.is_empty() {
470 if self.state_signature_mode == StateSignatureMode::Hard {
471 usage.missing_keys.push(entry.key.clone());
472 if first_error.is_none() {
473 first_error = Some(anyhow!("missing state signature for key {}", entry.key));
474 }
475 }
476 continue;
477 }
478
479 if let Err(e) = self.verify_state_entry_signature(entry) {
480 usage.invalid_keys.push(entry.key.clone());
481 if first_error.is_none() {
482 first_error = Some(anyhow!("invalid state signature for key {}: {}", entry.key, e));
483 }
484 }
485 }
486
487 if usage.is_used() && !self.state_signature_override_enabled {
488 return Err(Error::Other(
489 first_error
490 .unwrap_or_else(|| anyhow!("state signature verification failed unexpectedly")),
491 ));
492 }
493
494 Ok(usage)
495 }
496
497 async fn report_state_signature_override_enabled(&self) {
498 if !self.state_signature_override_enabled {
499 return;
500 }
501
502 let message = report::build_state_signature_override_enabled_message(
503 self.state_signature_mode_label(),
504 &self.id,
505 self.state_signature_override_note.as_deref(),
506 );
507 warn!("{}", message);
508 report::Reporter::report(crate::pb::scheduler::SignerRejection {
509 msg: message,
510 request: None,
511 git_version: GITHASH.to_string(),
512 node_id: self.node_id(),
513 })
514 .await;
515 }
516
517 async fn report_state_signature_override_usage(
518 &self,
519 req: &HsmRequest,
520 usage: &OverrideSignatureUsage,
521 ) {
522 if !usage.is_used() || !self.state_signature_override_enabled {
523 return;
524 }
525
526 let message = report::build_state_signature_override_used_message(
527 self.state_signature_mode_label(),
528 req.request_id as u64,
529 &usage.missing_keys,
530 &usage.invalid_keys,
531 self.state_signature_override_note.as_deref(),
532 );
533 warn!("{}", message);
534 report::Reporter::report(crate::pb::scheduler::SignerRejection {
535 msg: message,
536 request: Some(req.clone()),
537 git_version: GITHASH.to_string(),
538 node_id: self.node_id(),
539 })
540 .await;
541 }
542
543 fn check_request_auth(
550 &self,
551 requests: Vec<crate::pb::PendingRequest>,
552 ) -> Vec<Result<crate::pb::PendingRequest, anyhow::Error>> {
553 requests
556 .into_iter()
557 .filter(|r| !r.pubkey.is_empty() && !r.signature.is_empty() && !r.rune.is_empty())
558 .map(|r| {
559 let pk = UnparsedPublicKey::new(&ECDSA_P256_SHA256_FIXED, &r.pubkey);
560 let mut data = r.request.clone();
561
562 if r.timestamp != 0 {
566 data.put_u64(r.timestamp);
567 }
568
569 pk.verify(&data, &r.signature)
570 .map_err(|e| anyhow!("signature verification failed: {}", e))?;
571
572 self.verify_rune(r.clone())
573 .map(|_| r)
574 .map_err(|e| anyhow!("rune verification failed: {}", e))
575 })
576 .collect()
577 }
578
579 fn verify_rune(&self, request: crate::pb::PendingRequest) -> Result<(), anyhow::Error> {
582 let rune64 = general_purpose::URL_SAFE.encode(request.rune);
583 let rune = Rune::from_base64(&rune64)?;
584
585 if !rune.to_string().contains("pubkey=") {
589 return Err(anyhow!("rune is missing pubkey field"));
590 }
591
592 let unique_id = rune.get_id();
597 let ver_id = match unique_id {
598 Some(id) => format!("{}-{}", id, RUNE_VERSION),
599 None => String::default(),
600 };
601
602 let mut parts = request.uri.split('/');
604 parts.next();
605 match parts.next() {
606 Some(service) => {
607 if service != "cln.Node" && service != "greenlight.Node" {
608 debug!("request from unknown service {}.", service);
609 return Err(anyhow!("service {} is not valid", service));
610 }
611 }
612 None => {
613 debug!("could not extract service from the uri while verifying rune.");
614 return Err(anyhow!("can not extract service from uri"));
615 }
616 };
617
618 let method = match parts.next() {
621 Some(m) => m.to_lowercase(),
622 None => {
623 debug!("could not extract method from uri while verifying rune.");
624 return Err(anyhow!("can not extract uri form request"));
625 }
626 };
627
628 let ctx = runes::Context {
629 method,
630 pubkey: hex::encode(request.pubkey),
631 time: SystemTime::now(),
632 unique_id: ver_id,
633 };
634
635 match self.master_rune.check_with_reason(&rune64, ctx) {
636 Ok(_) => Ok(()),
637 Err(e) => Err(e.into()),
638 }
639 }
640
641 pub async fn run_once(&self, node_uri: Uri) -> Result<(), Error> {
645 info!("Connecting to node at {}", node_uri);
646
647 let tls_config = if node_uri.host().unwrap_or_default().contains("blckstrm") {
648 self.tls.inner.clone()
649 } else {
650 self.tls.inner.clone().domain_name("localhost")
651 };
652
653 let c = Endpoint::from_shared(node_uri.to_string())?
654 .tls_config(tls_config)?
655 .tcp_keepalive(Some(crate::TCP_KEEPALIVE))
656 .http2_keep_alive_interval(crate::TCP_KEEPALIVE)
657 .keep_alive_timeout(crate::TCP_KEEPALIVE_TIMEOUT)
658 .keep_alive_while_idle(true)
659 .connect_lazy();
660
661 let mut client = NodeClient::new(c);
662
663 let mut stream = client
664 .stream_hsm_requests(Request::new(Empty::default()))
665 .await?
666 .into_inner();
667
668 info!("Starting to stream signer requests");
669 loop {
670 let req = match stream
671 .message()
672 .await
673 .map_err(|e| Error::NodeDisconnect(e))?
674 {
675 Some(r) => r,
676 None => {
677 warn!("Signer request stream ended, the node shouldn't do this.");
678 return Ok(());
679 }
680 };
681 let request_id = req.request_id;
682 let hex_req = hex::encode(&req.raw);
683 let signer_state = req.signer_state.clone();
684 trace!("Received request {}", hex_req);
685
686 match self.process_request(req.clone()).await {
687 Ok(response) => {
688 trace!("Sending response {}", hex::encode(&response.raw));
689 client
690 .respond_hsm_request(response)
691 .await
692 .map_err(|e| Error::NodeDisconnect(e))?;
693 }
694 Err(e) => {
695 report::Reporter::report(crate::pb::scheduler::SignerRejection {
699 msg: format!("Error in run_once loop: {:?}", e),
700 request: Some(req.clone()),
701 git_version: GITHASH.to_string(),
702 node_id: self.node_id(),
703 })
704 .await;
705
706 let response = HsmResponse {
707 raw: vec![],
708 request_id,
709 error: format!("{:?}", e),
710 signer_state: vec![],
711 };
712 client
713 .respond_hsm_request(response)
714 .await
715 .map_err(|e| Error::NodeDisconnect(e))?;
716 warn!(
717 "Rejected request {} with error: {}. State: {:?}",
718 hex_req, e, signer_state,
719 )
720 }
721 };
722 }
723 }
724
725 fn authenticate_request(
726 &self,
727 msg: &vls_protocol::msgs::Message,
728 reqs: &Vec<model::Request>,
729 ) -> Result<(), Error> {
730 log::trace!(
731 "Resolving signature request against pending grpc commands: {:?}",
732 reqs
733 );
734
735 Resolver::try_resolve(msg, &reqs)?;
738
739 Ok(())
740 }
741
742 async fn process_request(&self, req: HsmRequest) -> Result<HsmResponse, Error> {
743 debug!("Processing request {:?}", req);
744 let req = req;
745
746 let signature_usage = self.inspect_incoming_state_signatures(&req.signer_state)?;
747 if signature_usage.is_used() {
748 self.report_state_signature_override_usage(&req, &signature_usage)
749 .await;
750 }
751
752 let incoming_state = crate::persist::State::try_from(req.signer_state.as_slice())
753 .map_err(|e| Error::Other(anyhow!("Failed to decode signer state: {e}")))?;
754
755
756 let prestate_sketch = incoming_state.sketch();
760
761 let prestate_log = {
762 debug!("Updating local signer state with state from node");
763 let mut state = self.state.lock().map_err(|e| {
764 Error::Other(anyhow!("Failed to acquire state lock: {:?}", e))
765 })?;
766 let merge_res = state.merge(&incoming_state).map_err(|e| {
767 Error::Other(anyhow!("Failed to merge signer state: {:?}", e))
768 })?;
769 if merge_res.has_conflicts() {
770 debug!(
771 "State merge ignored stale versions (count={})",
772 merge_res.conflict_count
773 );
774 }
775 trace!("Processing request {}", hex::encode(&req.raw));
776 serde_json::to_string(&*state).map_err(|e| {
777 Error::Other(anyhow!("Failed to serialize signer state for logging: {:?}", e))
778 })?
779 };
780
781 if let &[h, l, ..] = req.raw.as_slice() {
784 let typ = ((h as u16) << 8) | (l as u16);
785 if typ == 23 {
786 warn!("Refusing to process sign-message request");
787 return Err(Error::Other(anyhow!(
788 "Cannot process sign-message requests from node."
789 )));
790 }
791 }
792
793 let ctxrequests: Vec<model::Request> = self
794 .check_request_auth(req.requests.clone())
795 .into_iter()
796 .filter_map(|r| r.ok())
797 .map(|r| decode_request(r))
798 .filter_map(|r| match r {
799 Ok(r) => Some(r),
800 Err(e) => {
801 log::error!("Unable to decode request in context: {}", e);
802 None
803 }
804 })
805 .collect::<Vec<model::Request>>();
806
807 let msg = vls_protocol::msgs::from_vec(req.raw.clone()).map_err(|e| Error::Protocol(e))?;
808 log::debug!("Handling message {:?}", msg);
809 log::trace!("Signer state {}", prestate_log);
810
811 if let Err(e) = self.authenticate_request(&msg, &ctxrequests) {
812 report::Reporter::report(crate::pb::scheduler::SignerRejection {
813 msg: e.to_string(),
814 request: Some(req.clone()),
815 git_version: GITHASH.to_string(),
816 node_id: self.node_id(),
817 })
818 .await;
819 #[cfg(not(feature = "permissive"))]
820 return Err(Error::Resolver(req.raw, ctxrequests));
821 };
822
823 for parsed_request in ctxrequests.iter() {
825 match parsed_request {
826 model::Request::GlConfig(gl_config) => {
827 let pubkey = PublicKey::from_slice(&self.id);
828 match pubkey {
829 Ok(p) => {
830 let _ = self
831 .services
832 .persister
833 .update_node_allowlist(&p, vec![gl_config.close_to_addr.clone()]);
834 }
835 Err(e) => debug!("Could not parse public key {:?}: {:?}", self.id, e),
836 }
837 }
838 _ => {}
839 }
840 }
841
842 use auth::Authorizer;
843 let auth = auth::GreenlightAuthorizer {};
844 let approvals = auth.authorize(&ctxrequests).map_err(|e| Error::Auth(e))?;
845 debug!("Current approvals: {:?}", approvals);
846
847 let approver = Arc::new(MemoApprover::new(approver::ReportingApprover::new(
848 #[cfg(feature = "permissive")]
849 vls_protocol_signer::approver::PositiveApprover(),
850 #[cfg(not(feature = "permissive"))]
851 vls_protocol_signer::approver::NegativeApprover(),
852 )));
853 approver.approve(approvals);
854 let root_handler = self.handler_with_approver(approver)?;
855
856 log::trace!("Updating state from context");
857 if let Err(e) = update_state_from_context(&ctxrequests, &root_handler) {
858 error!("Failed to update state from context: {:?}", e);
859 report::Reporter::report(crate::pb::scheduler::SignerRejection {
860 msg: format!("Failed to update state from context: {:?}", e),
861 request: Some(req.clone()),
862 git_version: GITHASH.to_string(),
863 node_id: self.node_id(),
864 })
865 .await;
866 return Err(Error::Other(anyhow!(
867 "Failed to update state from context: {:?}",
868 e
869 )));
870 }
871 log::trace!("State updated");
872
873 let response = match req.context.clone() {
875 Some(HsmRequestContext { dbid: 0, .. }) | None => {
876 root_handler.handle(msg)
878 }
879 Some(c) => {
880 let node_id_len = c.node_id.len();
881 let pk: [u8; 33] = c.node_id.try_into().map_err(|_| {
882 Error::Other(anyhow!(
883 "Invalid node_id length in context: expected 33 bytes, got {}",
884 node_id_len
885 ))
886 })?;
887 let pk = vls_protocol::model::PubKey(pk);
888 root_handler
889 .for_new_client(1 as u64, pk, c.dbid)
890 .handle(msg)
891 }
892 };
893
894 let response = match response {
895 Ok(r) => r,
896 Err(e) => {
897 report::Reporter::report(crate::pb::scheduler::SignerRejection {
898 msg: format!("{:?}", e),
899 request: Some(req.clone()),
900 git_version: GITHASH.to_string(),
901 node_id: self.node_id(),
902 })
903 .await;
904 return Err(Error::Other(anyhow!("processing request: {e:?}")));
905 }
906 };
907
908 let signer_state: Vec<crate::pb::SignerStateEntry> = {
909 debug!("Serializing state changes to report to node");
910 let mut state = self.state.lock().map_err(|e| {
911 Error::Other(anyhow!(
912 "Failed to acquire state lock for serialization: {:?}",
913 e
914 ))
915 })?;
916 state
917 .resign_signatures(|key, version, value| {
918 self.sign_state_payload(key, version, value)
919 })
920 .map_err(|e| Error::Other(anyhow!("Failed to sign signer state entries: {e}")))?;
921 let full_wire_bytes = {
922 let full_entries: Vec<crate::pb::SignerStateEntry> = state.clone().into();
923 signer_state_response_wire_bytes(&full_entries)
924 };
925 let diff_state = prestate_sketch.diff_state(&state);
926 let diff_entries: Vec<crate::pb::SignerStateEntry> = diff_state.into();
927 let diff_wire_bytes = signer_state_response_wire_bytes(&diff_entries);
928 let saved_percent = savings_percent(full_wire_bytes, diff_wire_bytes);
929 trace!(
930 "Signer state diff entries={}, wire_bytes={}, full_wire_bytes={}, saved {}% bandwidth syncing the state",
931 diff_entries.len(),
932 diff_wire_bytes,
933 full_wire_bytes,
934 saved_percent
935 );
936 diff_entries
937 };
938 Ok(HsmResponse {
939 raw: response.as_vec(),
940 request_id: req.request_id,
941 signer_state,
942 error: "".to_owned(),
943 })
944 }
945
946 pub fn node_id(&self) -> Vec<u8> {
947 self.id.clone()
948 }
949
950 pub fn get_init(&self) -> Vec<u8> {
951 self.init.clone()
952 }
953
954 pub fn get_startup_messages(&self) -> Vec<StartupMessage> {
959 let mut init_handler = self.init_handler().unwrap();
960
961 let init = StartupMessage {
962 request: Signer::initreq().inner().as_vec(),
963 response: init_handler
964 .handle(Signer::initreq())
965 .unwrap()
966 .1
967 .map(|a| a.as_vec())
968 .unwrap_or_default(),
969 };
970
971 let requests = vec![
972 vls_protocol::msgs::Message::DeriveSecret(vls_protocol::msgs::DeriveSecret {
975 info: Octets("bolt12-invoice-base".as_bytes().to_vec()),
976 }),
977 vls_protocol::msgs::Message::DeriveSecret(vls_protocol::msgs::DeriveSecret {
979 info: Octets("scb secret".as_bytes().to_vec()),
980 }),
981 vls_protocol::msgs::Message::DeriveSecret(vls_protocol::msgs::DeriveSecret {
983 info: Octets("commando".as_bytes().to_vec()),
984 }),
985 vls_protocol::msgs::Message::DeriveSecret(vls_protocol::msgs::DeriveSecret {
987 info: Octets("node-alias-base".as_bytes().to_vec()),
988 }),
989 vls_protocol::msgs::Message::DeriveSecret(vls_protocol::msgs::DeriveSecret {
990 info: Octets("offer-blinded-path".as_bytes().to_vec()),
991 }),
992 ];
993
994 let serialized: Vec<Vec<u8>> = requests.iter().map(|m| m.inner().as_vec()).collect();
995 let responses: Vec<Vec<u8>> = requests
996 .into_iter()
997 .map(|r| self.handler().unwrap().handle(r).unwrap().as_vec())
998 .collect();
999
1000 let mut msgs: Vec<StartupMessage> = serialized
1001 .into_iter()
1002 .zip(responses)
1003 .map(|r| {
1004 log::debug!("Storing canned request-response: {:?} -> {:?}", r.0, r.1);
1005
1006 StartupMessage {
1007 request: r.0,
1008 response: r.1,
1009 }
1010 })
1011 .collect();
1012
1013 msgs.insert(0, init);
1014
1015 msgs
1016 }
1017
1018 pub fn bip32_ext_key(&self) -> Vec<u8> {
1019 use vls_protocol::{msgs, msgs::Message};
1020 let initmsg = msgs::from_vec(self.init.clone())
1022 .expect("init message should be valid (validated during Signer::new)");
1023
1024 match initmsg {
1025 Message::HsmdInit2Reply(m) => m.bip32.0.to_vec(),
1026 Message::HsmdInitReplyV4(m) => m.bip32.0.to_vec(),
1027 Message::HsmdInitReplyV2(m) => m.bip32.0.to_vec(),
1028 m => {
1029 error!("Unknown initmsg type {:?}, cannot extract bip32 key", m);
1031 vec![]
1032 }
1033 }
1034 }
1035
1036 pub fn legacy_bip32_ext_key(&self) -> Vec<u8> {
1037 let mut handler = match self.init_handler() {
1038 Ok(h) => h,
1039 Err(e) => {
1040 error!("Failed to retrieve handler for legacy bip32 key: {:?}", e);
1041 return vec![];
1042 }
1043 };
1044 let req = vls_protocol::msgs::Message::HsmdInit(vls_protocol::msgs::HsmdInit {
1045 key_version: vls_protocol::model::Bip32KeyVersion {
1046 pubkey_version: 0,
1047 privkey_version: 0,
1048 },
1049 chain_params: lightning_signer::bitcoin::BlockHash::all_zeros(),
1050 encryption_key: None,
1051 dev_privkey: None,
1052 dev_bip32_seed: None,
1053 dev_channel_secrets: None,
1054 dev_channel_secrets_shaseed: None,
1055 hsm_wire_min_version: 1,
1056 hsm_wire_max_version: 2,
1057 });
1058
1059 let initmsg = match handler.handle(req) {
1060 Ok((_req, response)) => response.map(|a| a.as_vec()).unwrap_or_default(),
1061 Err(e) => {
1062 error!("Failed to handle legacy init message: {:?}", e);
1063 return vec![];
1064 }
1065 };
1066
1067 if initmsg.len() <= 35 {
1068 error!(
1069 "Legacy init message too short: expected >35 bytes, got {}",
1070 initmsg.len()
1071 );
1072 return vec![];
1073 }
1074 initmsg[35..].to_vec()
1075 }
1076
1077 pub async fn run_forever(&self, shutdown: mpsc::Receiver<()>) -> Result<(), anyhow::Error> {
1082 let scheduler_uri = crate::utils::scheduler_uri();
1083 debug!("Starting signer run loop");
1084 self.report_state_signature_override_enabled().await;
1085 let res = Self::run_forever_with_uri(&self, shutdown, scheduler_uri).await;
1086 debug!("Exited signer run loop");
1087 res
1088 }
1089
1090 async fn init_scheduler(
1092 &self,
1093 scheduler_uri: String,
1094 ) -> Result<SchedulerClient<tonic::transport::channel::Channel>> {
1095 info!("Connecting to scheduler at {scheduler_uri}");
1096
1097 let channel = Endpoint::from_shared(scheduler_uri.clone())?
1098 .tls_config(self.tls.inner.clone())?
1099 .tcp_keepalive(Some(crate::TCP_KEEPALIVE))
1100 .http2_keep_alive_interval(crate::TCP_KEEPALIVE)
1101 .keep_alive_timeout(crate::TCP_KEEPALIVE_TIMEOUT)
1102 .keep_alive_while_idle(true)
1103 .connect_lazy();
1104 let mut scheduler = SchedulerClient::new(channel);
1105
1106 loop {
1109 let call_start = tokio::time::Instant::now();
1110 debug!("Sending maybe_upgrade to {}", self.version());
1111 #[allow(deprecated)]
1112 let res = scheduler
1113 .maybe_upgrade(UpgradeRequest {
1114 initmsg: self.init.clone(),
1115 signer_version: self.version().to_owned(),
1116 startupmsgs: self
1117 .get_startup_messages()
1118 .into_iter()
1119 .map(|s| s.into())
1120 .collect(),
1121 })
1122 .await;
1123 debug!(
1124 "Server returned {:?} after {}s",
1125 res,
1126 call_start.elapsed().as_secs()
1127 );
1128
1129 match res {
1130 Err(e) => match e.code() {
1131 Code::Unavailable => {
1132 debug!("Cannot connect to scheduler, sleeping and retrying");
1133 sleep(Duration::from_secs(3)).await;
1134 continue;
1135 }
1136 _ => Err(Error::Upgrade(e))?,
1137 },
1138 Ok(r) => {
1139 debug!("Server reports version {}", r.into_inner().old_version)
1140 }
1141 }
1142 break;
1143 }
1144 Ok(scheduler)
1145 }
1146
1147 async fn run_forever_inner(
1151 &self,
1152 mut scheduler: SchedulerClient<tonic::transport::channel::Channel>,
1153 ) -> Result<(), anyhow::Error> {
1154 loop {
1155 info!("Calling scheduler.get_node_info");
1156 let node_info_res = scheduler
1157 .get_node_info(NodeInfoRequest {
1158 node_id: self.id.clone(),
1159
1160 wait: true,
1166 })
1167 .await;
1168
1169 let node_info = match node_info_res.map(|v| v.into_inner()) {
1170 Ok(v) => {
1171 info!("Got node_info from scheduler: {:?}", v);
1172 v
1173 }
1174 Err(e) => {
1175 trace!("Got an error from the scheduler: {e}. Sleeping before retrying");
1176 sleep(Duration::from_millis(1000)).await;
1177 continue;
1178 }
1179 };
1180
1181 if node_info.grpc_uri.is_empty() {
1182 trace!("Got an empty GRPC URI, node is not scheduled, sleeping and retrying");
1183 sleep(Duration::from_millis(1000)).await;
1184 continue;
1185 }
1186
1187 if let Err(e) = self
1188 .run_once(Uri::from_maybe_shared(node_info.grpc_uri)?)
1189 .await
1190 {
1191 warn!("Error running against node: {e}");
1192 }
1193 }
1194 }
1195
1196 pub async fn run_forever_with_uri(
1197 &self,
1198 mut shutdown: mpsc::Receiver<()>,
1199 scheduler_uri: String,
1200 ) -> Result<(), anyhow::Error> {
1201 let scheduler = self.init_scheduler(scheduler_uri).await?;
1202 tokio::select! {
1203 run_forever_inner_res = self.run_forever_inner(scheduler.clone()) => {
1204 error!("Inner signer loop exited unexpectedly: {run_forever_inner_res:?}");
1205 },
1206 run_forever_scheduler_res = self.run_forever_scheduler(scheduler) => {
1207 error!("Scheduler signer loop exited unexpectedly: {run_forever_scheduler_res:?}")
1208 }
1209 _ = shutdown.recv() => debug!("Received the signal to exit the signer loop")
1210 };
1211
1212 info!("Exiting the signer loop");
1213 Ok(())
1214 }
1215
1216 async fn run_forever_scheduler(
1217 &self,
1218 scheduler: SchedulerClient<tonic::transport::Channel>,
1219 ) -> Result<(), anyhow::Error> {
1220 loop {
1221 if let Err(e) = self.run_once_scheduler(scheduler.clone()).await {
1222 warn!("Error running schduler, trying again: {e}");
1223 }
1224 }
1225 }
1226
1227 async fn run_once_scheduler(
1228 &self,
1229 mut scheduler: SchedulerClient<tonic::transport::Channel>,
1230 ) -> Result<(), anyhow::Error> {
1231 let (sender, rx) = mpsc::channel(1);
1232 let outbound = ReceiverStream::new(rx);
1233 let mut stream = scheduler
1236 .signer_requests_stream(outbound)
1237 .await?
1238 .into_inner();
1239
1240 trace!("Starting to stream signer requests from scheduler");
1241
1242 loop {
1243 match stream.message().await {
1244 Ok(Some(msg)) => {
1245 let req_id = msg.request_id;
1246 trace!("Processing scheduler request {}", req_id);
1247 match msg.request {
1248 Some(signer_request::Request::ApprovePairing(req)) => {
1249 if let Err(e) = self
1250 .process_pairing_approval(req_id, req, sender.clone())
1251 .await
1252 {
1253 debug!("Could not process pairing approval: {:?}", e);
1254 }
1255 }
1256 None => {
1257 debug!("Received an empty signing request");
1258 }
1259 };
1260 }
1261 Ok(None) => {
1262 debug!("End of stream, this should not happen by the server");
1263 return Err(anyhow!("Scheduler closed the stream"));
1264 }
1265 Err(e) => {
1266 debug!("Got an error from the scheduler {}", e);
1267 return Err(anyhow!("Scheduler stream error {e:?}"));
1268 }
1269 };
1270 }
1271 }
1272
1273 async fn process_pairing_approval(
1274 &self,
1275 req_id: u32,
1276 req: ApprovePairingRequest,
1277 stream: mpsc::Sender<SignerResponse>,
1278 ) -> Result<()> {
1279 let node_id = self.node_id();
1281
1282 let mut data = vec![];
1283 data.put(req.device_id.as_bytes());
1284 data.put_u64(req.timestamp);
1285 data.put(&node_id[..]);
1286 data.put(req.device_name.as_bytes());
1287 data.put(req.restrictions.as_bytes());
1288
1289 let pk = UnparsedPublicKey::new(&ECDSA_P256_SHA256_FIXED, req.pubkey.clone());
1291 pk.verify(&data, &req.sig)
1292 .map_err(|e| Error::ApprovePairingRequestError(e.to_string()))?;
1293
1294 let rune = general_purpose::URL_SAFE
1296 .decode(req.rune.clone())
1297 .map_err(|e| Error::ApprovePairingRequestError(e.to_string()))?;
1298
1299 self.verify_rune(PendingRequest {
1301 request: vec![],
1302 uri: "/cln.Node/ApprovePairing".to_string(),
1303 signature: req.sig,
1304 pubkey: req.pubkey,
1305 timestamp: req.timestamp,
1306 rune,
1307 })?;
1308
1309 let restrs: Vec<Vec<&str>> = req
1310 .restrictions
1311 .split('&')
1312 .map(|s| s.split('|').collect::<Vec<&str>>())
1313 .collect();
1314
1315 let rune = self.create_rune(None, restrs)?;
1317
1318 let _ = stream
1319 .send(SignerResponse {
1320 request_id: req_id,
1321 response: Some(signer_response::Response::ApprovePairing(
1322 ApprovePairingResponse {
1323 device_id: req.device_id,
1324 node_id,
1325 rune,
1326 },
1327 )),
1328 })
1329 .await?;
1330
1331 Ok(())
1332 }
1333
1334 pub fn sign_challenge(&self, challenge: Vec<u8>) -> Result<Vec<u8>, anyhow::Error> {
1336 if challenge.len() != 32 {
1337 return Err(anyhow!("challenge is not 32 bytes long"));
1338 }
1339 let (sig, _) = self.sign_message(challenge)?;
1340 Ok(sig)
1341 }
1342
1343 pub fn sign_device_key(&self, key: &[u8]) -> Result<Vec<u8>, anyhow::Error> {
1351 if key.len() != 65 {
1352 return Err(anyhow!("key is not 65 bytes long"));
1353 }
1354 let (sig, _) = self.sign_message(key.to_vec())?;
1355 Ok(sig)
1356 }
1357
1358 pub fn sign_message(&self, msg: Vec<u8>) -> Result<(Vec<u8>, u8), anyhow::Error> {
1361 if msg.len() > u16::MAX as usize {
1362 return Err(anyhow!("Message exceeds max len of {}", u16::MAX));
1363 }
1364
1365 let len = u16::to_be_bytes(msg.len() as u16);
1366 if len.len() != 2 {
1367 return Err(anyhow!(
1368 "Message to be signed has unexpected len {}",
1369 len.len()
1370 ));
1371 }
1372
1373 let req = vls_protocol::msgs::SignMessage {
1374 message: Octets(msg),
1375 };
1376 let response = self
1377 .handler()?
1378 .handle(vls_protocol::msgs::Message::SignMessage(req))
1379 .unwrap();
1380
1381 let complete_sig = response.as_vec();
1384 let sig = complete_sig[2..66].to_vec();
1385 let recovery_id = complete_sig[66];
1386 Ok((sig, recovery_id))
1387 }
1388
1389 pub fn sign_invoice(&self, msg: Vec<u8>) -> Result<Vec<u8>, anyhow::Error> {
1391 if msg.len() > u16::MAX as usize {
1392 return Err(anyhow!("Message exceeds max len of {}", u16::MAX));
1393 }
1394
1395 let sig = self
1396 .handler()?
1397 .handle(vls_protocol::msgs::from_vec(msg.clone())?)
1398 .map_err(|_| anyhow!("Sign invoice failed"))?;
1399 Ok(sig.as_vec()[2..67].to_vec())
1400 }
1401
1402 pub async fn node<Creds>(&self, creds: Creds) -> Result<Client, anyhow::Error>
1405 where
1406 Creds: TlsConfigProvider + RuneProvider,
1407 {
1408 node::Node::new(self.node_id(), creds)?.schedule().await
1409 }
1410
1411 pub fn version(&self) -> &'static str {
1412 VERSION
1413 }
1414
1415 pub fn create_rune(
1453 &self,
1454 rune: Option<&str>,
1455 restrictions: Vec<Vec<&str>>,
1456 ) -> Result<String, anyhow::Error> {
1457 if let Some(rune) = rune {
1458 let mut rune: Rune = Rune::from_base64(rune)?;
1460 restrictions.into_iter().for_each(|alts| {
1461 let joined = alts.join("|");
1462 _ = rune.add_restriction(joined.as_str())
1463 });
1464 return Ok(rune.to_base64());
1465 } else {
1466 let res: Vec<Restriction> = restrictions
1467 .into_iter()
1468 .map(|alts| {
1469 let joined = alts.join("|");
1470 Restriction::try_from(joined.as_str())
1471 })
1472 .collect::<Result<Vec<Restriction>, RuneError>>()?;
1473
1474 let unique_id = 0;
1477
1478 let has_pubkey_field = res.iter().any(|r: &Restriction| {
1480 r.alternatives
1481 .iter()
1482 .any(|a| a.get_field() == *"pubkey" && a.get_condition() == Condition::Equal)
1483 });
1484 if !has_pubkey_field {
1485 return Err(anyhow!("Missing a restriction on the pubkey"));
1486 }
1487
1488 let rune = Rune::new(
1489 self.master_rune.authcode(),
1490 res,
1491 Some(unique_id.to_string()),
1492 Some(RUNE_VERSION.to_string()),
1493 )?;
1494 Ok(rune.to_base64())
1495 }
1496 }
1497}
1498
1499fn update_state_from_context(
1503 requests: &Vec<model::Request>,
1504 handler: &handler::RootHandler,
1505) -> Result<(), Error> {
1506 log::debug!("Updating state from {} context request", requests.len());
1507 let node = handler.node();
1508
1509 requests.iter().for_each(|r| {
1510 if let Err(e) = update_state_from_request(r, &node) {
1511 log::warn!("Failed to update state from request: {:?}", e);
1512 }
1513 });
1514 Ok(())
1515}
1516
1517fn update_state_from_request(
1518 request: &model::Request,
1519 node: &lightning_signer::node::Node,
1520) -> Result<(), Error> {
1521 use lightning_signer::invoice::Invoice;
1522 use std::str::FromStr;
1523 match request {
1524 model::Request::SendPay(model::cln::SendpayRequest {
1525 bolt11: Some(inv), ..
1526 }) => match Invoice::from_str(inv) {
1527 Ok(invoice) => {
1528 log::debug!(
1529 "Adding invoice {:?} as side-effect of this sendpay {:?}",
1530 invoice,
1531 request
1532 );
1533 if let Err(e) = node.add_invoice(invoice) {
1534 log::warn!("Failed to add invoice to node state: {:?}", e);
1535 }
1536 }
1537 Err(e) => {
1538 log::warn!("Failed to parse invoice from sendpay request: {:?}", e);
1539 }
1540 },
1541 _ => {}
1542 }
1543
1544 Ok(())
1545}
1546
1547fn decode_request(r: crate::pb::PendingRequest) -> Result<model::Request, anyhow::Error> {
1553 assert_eq!(r.request[0], 0u8);
1560 let payload = &r.request[5..];
1561
1562 crate::signer::model::cln::decode_request(&r.uri, payload)
1563 .or_else(|_| crate::signer::model::greenlight::decode_request(&r.uri, payload))
1564}
1565
1566pub struct StartupMessage {
1569 request: Vec<u8>,
1570 response: Vec<u8>,
1571}
1572
1573impl From<StartupMessage> for crate::pb::scheduler::StartupMessage {
1574 fn from(r: StartupMessage) -> Self {
1575 Self {
1576 request: r.request,
1577 response: r.response,
1578 }
1579 }
1580}
1581
1582#[cfg(test)]
1583mod tests {
1584 use super::*;
1585 use crate::credentials;
1586 use crate::pb;
1587 use serde_json::json;
1588 use vls_protocol::msgs::SerBolt;
1589
1590 fn test_override_config(note: Option<&str>) -> StateSignatureOverrideConfig {
1591 StateSignatureOverrideConfig {
1592 ack: STATE_SIGNATURE_OVERRIDE_ACK.to_string(),
1593 note: note.map(str::to_string),
1594 }
1595 }
1596
1597 fn mk_signer(mode: StateSignatureMode) -> Signer {
1598 Signer::new_with_config(
1599 vec![0u8; 32],
1600 Network::Bitcoin,
1601 credentials::Nobody::default(),
1602 SignerConfig {
1603 state_signature_mode: mode,
1604 state_signature_override: None,
1605 },
1606 )
1607 .unwrap()
1608 }
1609
1610 fn mk_signer_with_override(mode: StateSignatureMode, note: Option<&str>) -> Signer {
1611 Signer::new_with_config(
1612 vec![0u8; 32],
1613 Network::Bitcoin,
1614 credentials::Nobody::default(),
1615 SignerConfig {
1616 state_signature_mode: mode,
1617 state_signature_override: Some(test_override_config(note)),
1618 },
1619 )
1620 .unwrap()
1621 }
1622
1623 fn heartbeat_raw() -> Vec<u8> {
1624 vls_protocol::msgs::GetHeartbeat {}.as_vec()
1625 }
1626
1627 fn mk_state_entry(key: &str, version: u64, value: serde_json::Value) -> SignerStateEntry {
1628 SignerStateEntry {
1629 version,
1630 key: key.to_string(),
1631 value: serde_json::to_vec(&value).unwrap(),
1632 signature: vec![],
1633 }
1634 }
1635
1636 #[tokio::test]
1642 async fn test_sign_message_rejection() {
1643 let signer = Signer::new(
1644 vec![0 as u8; 32],
1645 Network::Bitcoin,
1646 credentials::Nobody::default(),
1647 )
1648 .unwrap();
1649
1650 let msg = hex::decode("0017000B48656c6c6f20776f726c64").unwrap();
1651 assert!(signer
1652 .process_request(HsmRequest {
1653 request_id: 0,
1654 context: None,
1655 raw: msg,
1656 signer_state: vec![],
1657 requests: Vec::new(),
1658 },)
1659 .await
1660 .is_err());
1661 }
1662
1663 #[tokio::test]
1665 async fn test_empty_message() {
1666 let signer = Signer::new(
1667 vec![0 as u8; 32],
1668 Network::Bitcoin,
1669 credentials::Nobody::default(),
1670 )
1671 .unwrap();
1672
1673 assert_eq!(
1674 signer
1675 .process_request(HsmRequest {
1676 request_id: 0,
1677 context: None,
1678 raw: vec![],
1679 signer_state: vec![],
1680 requests: Vec::new(),
1681 },)
1682 .await
1683 .unwrap_err()
1684 .to_string(),
1685 *"protocol error: ShortRead"
1686 )
1687 }
1688
1689 #[test]
1690 fn test_state_signature_roundtrip() {
1691 let signer = mk_signer(StateSignatureMode::Soft);
1692 let mut entry = mk_state_entry("state/test", 1, json!({"v": 1}));
1693 entry.signature = signer
1694 .sign_state_payload(&entry.key, entry.version, &entry.value)
1695 .unwrap();
1696 assert!(signer.verify_state_entry_signature(&entry).is_ok());
1697 }
1698
1699 #[tokio::test]
1700 async fn test_soft_mode_accepts_missing_signature_and_repairs() {
1701 let signer = mk_signer(StateSignatureMode::Soft);
1702 let key = "state/test".to_string();
1703 let req = HsmRequest {
1704 request_id: 42,
1705 context: None,
1706 raw: heartbeat_raw(),
1707 signer_state: vec![mk_state_entry(&key, 1, json!({"v": 1}))],
1708 requests: vec![],
1709 };
1710 let response = signer.process_request(req).await.unwrap();
1711 let repaired = response
1712 .signer_state
1713 .iter()
1714 .find(|e| e.key == key)
1715 .expect("expected repaired entry in diff");
1716 assert_eq!(repaired.signature.len(), COMPACT_SIGNATURE_LEN);
1717 }
1718
1719 #[tokio::test]
1720 async fn test_soft_mode_rejects_invalid_signature() {
1721 let signer = mk_signer(StateSignatureMode::Soft);
1722 let mut entry = mk_state_entry("state/test", 1, json!({"v": 1}));
1723 entry.signature = vec![1u8; COMPACT_SIGNATURE_LEN];
1724 let err = signer
1725 .process_request(HsmRequest {
1726 request_id: 0,
1727 context: None,
1728 raw: heartbeat_raw(),
1729 signer_state: vec![entry],
1730 requests: vec![],
1731 })
1732 .await
1733 .unwrap_err()
1734 .to_string();
1735 assert!(err.contains("invalid state signature"));
1736 }
1737
1738 #[tokio::test]
1739 async fn test_hard_mode_rejects_missing_signature() {
1740 let signer = mk_signer(StateSignatureMode::Hard);
1741 let err = signer
1742 .process_request(HsmRequest {
1743 request_id: 0,
1744 context: None,
1745 raw: heartbeat_raw(),
1746 signer_state: vec![mk_state_entry("state/test", 1, json!({"v": 1}))],
1747 requests: vec![],
1748 })
1749 .await
1750 .unwrap_err()
1751 .to_string();
1752 assert!(err.contains("missing state signature"));
1753 }
1754
1755 #[tokio::test]
1756 async fn test_hard_mode_rejects_invalid_signature() {
1757 let signer = mk_signer(StateSignatureMode::Hard);
1758 let mut entry = mk_state_entry("state/test", 1, json!({"v": 1}));
1759 entry.signature = vec![2u8; COMPACT_SIGNATURE_LEN];
1760 let err = signer
1761 .process_request(HsmRequest {
1762 request_id: 0,
1763 context: None,
1764 raw: heartbeat_raw(),
1765 signer_state: vec![entry],
1766 requests: vec![],
1767 })
1768 .await
1769 .unwrap_err()
1770 .to_string();
1771 assert!(err.contains("invalid state signature"));
1772 }
1773
1774 #[tokio::test]
1775 async fn test_hard_mode_accepts_valid_signature() {
1776 let signer = mk_signer(StateSignatureMode::Hard);
1777 let mut entry = mk_state_entry("state/test", 1, json!({"v": 1}));
1778 entry.signature = signer
1779 .sign_state_payload(&entry.key, entry.version, &entry.value)
1780 .unwrap();
1781
1782 let res = signer
1783 .process_request(HsmRequest {
1784 request_id: 0,
1785 context: None,
1786 raw: heartbeat_raw(),
1787 signer_state: vec![entry],
1788 requests: vec![],
1789 })
1790 .await;
1791 assert!(res.is_ok());
1792 }
1793
1794 #[tokio::test]
1795 async fn test_off_mode_accepts_invalid_and_missing_signatures() {
1796 let signer = mk_signer(StateSignatureMode::Off);
1797 let mut invalid = mk_state_entry("state/invalid", 1, json!({"v": 1}));
1798 invalid.signature = vec![3u8; COMPACT_SIGNATURE_LEN];
1799 let missing = mk_state_entry("state/missing", 1, json!({"v": 2}));
1800 let res = signer
1801 .process_request(HsmRequest {
1802 request_id: 0,
1803 context: None,
1804 raw: heartbeat_raw(),
1805 signer_state: vec![invalid, missing],
1806 requests: vec![],
1807 })
1808 .await;
1809 assert!(res.is_ok());
1810 }
1811
1812 #[tokio::test]
1813 async fn test_soft_mode_override_accepts_invalid_across_requests() {
1814 let signer = mk_signer_with_override(StateSignatureMode::Soft, Some("test override"));
1815
1816 let mut invalid1 = mk_state_entry("state/invalid1", 1, json!({"v": 1}));
1817 invalid1.signature = vec![4u8; COMPACT_SIGNATURE_LEN];
1818 signer
1819 .process_request(HsmRequest {
1820 request_id: 1,
1821 context: None,
1822 raw: heartbeat_raw(),
1823 signer_state: vec![invalid1],
1824 requests: vec![],
1825 })
1826 .await
1827 .unwrap();
1828 let snapshot1: Vec<SignerStateEntry> = {
1829 let state_guard = signer.state.lock().unwrap();
1830 state_guard.clone().into()
1831 };
1832 let persisted1 = snapshot1.iter().find(|e| e.key == "state/invalid1").unwrap();
1833 assert_eq!(persisted1.signature, vec![4u8; COMPACT_SIGNATURE_LEN]);
1834
1835 let mut invalid2 = mk_state_entry("state/invalid2", 1, json!({"v": 2}));
1836 invalid2.signature = vec![5u8; COMPACT_SIGNATURE_LEN];
1837 let res2 = signer
1838 .process_request(HsmRequest {
1839 request_id: 2,
1840 context: None,
1841 raw: heartbeat_raw(),
1842 signer_state: vec![invalid2],
1843 requests: vec![],
1844 })
1845 .await;
1846 assert!(res2.is_ok());
1847
1848 let snapshot2: Vec<SignerStateEntry> = {
1849 let state_guard = signer.state.lock().unwrap();
1850 state_guard.clone().into()
1851 };
1852 let persisted2 = snapshot2.iter().find(|e| e.key == "state/invalid2").unwrap();
1853 assert_eq!(persisted2.signature, vec![5u8; COMPACT_SIGNATURE_LEN]);
1854 }
1855
1856 #[tokio::test]
1857 async fn test_hard_mode_override_accepts_missing_across_requests() {
1858 let signer = mk_signer_with_override(StateSignatureMode::Hard, Some("test override"));
1859
1860 for (key, request_id) in [("state/missing1", 10u32), ("state/missing2", 11u32)] {
1861 signer
1862 .process_request(HsmRequest {
1863 request_id,
1864 context: None,
1865 raw: heartbeat_raw(),
1866 signer_state: vec![mk_state_entry(key, 1, json!({"v": request_id}))],
1867 requests: vec![],
1868 })
1869 .await
1870 .unwrap();
1871 let snapshot: Vec<SignerStateEntry> = {
1872 let state_guard = signer.state.lock().unwrap();
1873 state_guard.clone().into()
1874 };
1875 let persisted = snapshot.iter().find(|entry| entry.key == key).unwrap();
1876 assert_eq!(persisted.signature.len(), COMPACT_SIGNATURE_LEN);
1877 }
1878 }
1879
1880 #[tokio::test]
1881 async fn test_hard_mode_override_accepts_invalid_signature() {
1882 let signer = mk_signer_with_override(StateSignatureMode::Hard, Some("test override"));
1883 let mut invalid = mk_state_entry("state/invalid-hard", 1, json!({"v": 3}));
1884 invalid.signature = vec![6u8; COMPACT_SIGNATURE_LEN];
1885
1886 signer
1887 .process_request(HsmRequest {
1888 request_id: 12,
1889 context: None,
1890 raw: heartbeat_raw(),
1891 signer_state: vec![invalid],
1892 requests: vec![],
1893 })
1894 .await
1895 .unwrap();
1896
1897 let snapshot: Vec<SignerStateEntry> = {
1898 let state_guard = signer.state.lock().unwrap();
1899 state_guard.clone().into()
1900 };
1901 let persisted = snapshot
1902 .iter()
1903 .find(|entry| entry.key == "state/invalid-hard")
1904 .unwrap();
1905 assert_eq!(persisted.signature, vec![6u8; COMPACT_SIGNATURE_LEN]);
1906 }
1907
1908 #[tokio::test]
1909 async fn test_override_preserves_invalid_signature_without_touching_valid_signature() {
1910 let signer = mk_signer_with_override(StateSignatureMode::Soft, Some("repair"));
1911
1912 let mut valid = mk_state_entry("state/valid", 1, json!({"v": 1}));
1913 valid.signature = signer
1914 .sign_state_payload(&valid.key, valid.version, &valid.value)
1915 .unwrap();
1916 let mut invalid = mk_state_entry("state/invalid", 1, json!({"v": 2}));
1917 invalid.signature = vec![7u8; COMPACT_SIGNATURE_LEN];
1918
1919 signer
1920 .process_request(HsmRequest {
1921 request_id: 13,
1922 context: None,
1923 raw: heartbeat_raw(),
1924 signer_state: vec![valid.clone(), invalid],
1925 requests: vec![],
1926 })
1927 .await
1928 .unwrap();
1929
1930 let snapshot: Vec<SignerStateEntry> = {
1931 let state_guard = signer.state.lock().unwrap();
1932 state_guard.clone().into()
1933 };
1934
1935 let persisted_valid = snapshot.iter().find(|entry| entry.key == "state/valid").unwrap();
1936 let preserved_invalid = snapshot
1937 .iter()
1938 .find(|entry| entry.key == "state/invalid")
1939 .unwrap();
1940
1941 assert_eq!(persisted_valid.signature, valid.signature);
1942 assert_eq!(preserved_invalid.signature, vec![7u8; COMPACT_SIGNATURE_LEN]);
1943 }
1944
1945 #[test]
1946 fn test_override_rejected_when_mode_off() {
1947 let signer = Signer::new_with_config(
1948 vec![0u8; 32],
1949 Network::Bitcoin,
1950 credentials::Nobody::default(),
1951 SignerConfig {
1952 state_signature_mode: StateSignatureMode::Off,
1953 state_signature_override: Some(test_override_config(Some("test"))),
1954 },
1955 );
1956 let err = signer.err().unwrap().to_string();
1957 assert!(err.contains("incompatible with state signature mode off"));
1958 }
1959
1960 #[test]
1961 fn test_override_rejected_for_invalid_ack() {
1962 let signer = Signer::new_with_config(
1963 vec![0u8; 32],
1964 Network::Bitcoin,
1965 credentials::Nobody::default(),
1966 SignerConfig {
1967 state_signature_mode: StateSignatureMode::Soft,
1968 state_signature_override: Some(StateSignatureOverrideConfig {
1969 ack: "WRONG".to_string(),
1970 note: None,
1971 }),
1972 },
1973 );
1974 let err = signer.err().unwrap().to_string();
1975 assert!(err.contains("invalid state signature override ack"));
1976 }
1977
1978 #[tokio::test]
1979 async fn test_malformed_state_value_returns_error() {
1980 let signer = mk_signer(StateSignatureMode::Soft);
1981 let entry = SignerStateEntry {
1982 version: 1,
1983 key: "nodes/bad".to_string(),
1984 value: b"{".to_vec(),
1985 signature: vec![],
1986 };
1987 let err = signer
1988 .process_request(HsmRequest {
1989 request_id: 0,
1990 context: None,
1991 raw: heartbeat_raw(),
1992 signer_state: vec![entry],
1993 requests: vec![],
1994 })
1995 .await
1996 .unwrap_err()
1997 .to_string();
1998 assert!(err.contains("Failed to decode signer state"));
1999 }
2000
2001 #[test]
2002 fn test_sign_message_max_size() {
2003 let signer = Signer::new(
2004 vec![0u8; 32],
2005 Network::Bitcoin,
2006 credentials::Nobody::default(),
2007 )
2008 .unwrap();
2009
2010 let msg = [0u8; u16::MAX as usize + 1];
2012 assert_eq!(
2013 signer.sign_message(msg.to_vec()).unwrap_err().to_string(),
2014 format!("Message exceeds max len of {}", u16::MAX)
2015 );
2016 }
2017
2018 #[test]
2023 fn test_legacy_bip32_key() {
2024 let signer = Signer::new(
2025 vec![0u8; 32],
2026 Network::Bitcoin,
2027 credentials::Nobody::default(),
2028 )
2029 .unwrap();
2030
2031 let bip32 = signer.legacy_bip32_ext_key();
2032 let expected: Vec<u8> = vec![
2033 4, 136, 178, 30, 2, 175, 86, 45, 251, 0, 0, 0, 0, 119, 232, 160, 181, 114, 16, 182, 23,
2034 70, 246, 204, 254, 122, 233, 131, 242, 174, 134, 193, 120, 104, 70, 176, 202, 168, 243,
2035 142, 127, 239, 60, 157, 212, 3, 162, 85, 18, 86, 240, 176, 177, 84, 94, 241, 92, 64,
2036 175, 69, 165, 146, 101, 79, 180, 195, 27, 117, 8, 66, 110, 100, 36, 246, 115, 48, 193,
2037 189, 3, 247, 195, 58, 236, 143, 230, 177, 91, 217, 66, 67, 19, 204, 22, 96, 65, 140,
2038 86, 195, 109, 50, 228, 94, 193, 173, 103, 252, 196, 192, 173, 243, 223,
2039 ];
2040
2041 assert_eq!(bip32, expected);
2042 }
2043
2044 #[test]
2047 fn test_rune_expects_pubkey() {
2048 let signer = Signer::new(
2049 vec![0u8; 32],
2050 Network::Bitcoin,
2051 credentials::Nobody::default(),
2052 )
2053 .unwrap();
2054
2055 let alt = "pubkey=112233";
2056 let wrong_alt = "pubkey^112233";
2057
2058 assert!(signer.create_rune(None, vec![]).is_err());
2060
2061 assert!(signer.create_rune(None, vec![vec![wrong_alt]]).is_err());
2063
2064 assert!(signer.create_rune(None, vec![vec![alt]]).is_ok());
2066
2067 assert!(signer
2069 .create_rune(None, vec![vec![wrong_alt], vec![wrong_alt, alt]])
2070 .is_ok());
2071 }
2072
2073 #[test]
2074 fn test_rune_expansion() {
2075 let signer = Signer::new(
2076 vec![0u8; 32],
2077 Network::Bitcoin,
2078 credentials::Nobody::default(),
2079 )
2080 .unwrap();
2081 let rune = "wjEjvKoFJToMLBv4QVbJpSbMoGFlnYVxs8yy40PIBgs9MC1nbDAmcHVia2V5PTAwMDAwMA==";
2082
2083 let new_rune = signer
2084 .create_rune(Some(rune), vec![vec!["method^get"]])
2085 .unwrap();
2086 let stream = Rune::from_base64(&new_rune).unwrap().to_string();
2087 assert!(stream.contains("0-gl0&pubkey=000000&method^get"))
2088 }
2089
2090 #[test]
2091 fn test_rune_checks_method() {
2092 let signer = Signer::new(
2093 vec![0u8; 32],
2094 Network::Bitcoin,
2095 credentials::Nobody::default(),
2096 )
2097 .unwrap();
2098
2099 let pubkey = signer.node_id();
2101 let pubkey_rest = format!("pubkey={}", hex::encode(&pubkey));
2102
2103 let rune = signer
2105 .create_rune(None, vec![vec![&pubkey_rest], vec!["method^create"]])
2106 .unwrap();
2107
2108 let uri = "/cln.Node/CreateInvoice".to_string();
2110 let r = pb::PendingRequest {
2111 request: vec![],
2112 uri,
2113 signature: vec![],
2114 pubkey: pubkey.clone(),
2115 timestamp: 0,
2116 rune: general_purpose::URL_SAFE.decode(&rune).unwrap(),
2117 };
2118 assert!(signer.verify_rune(r).is_ok());
2119
2120 let uri = "/cln.Node/Pay".to_string();
2122 let r = pb::PendingRequest {
2123 request: vec![],
2124 uri,
2125 signature: vec![],
2126 pubkey: pubkey.clone(),
2127 timestamp: 0,
2128 rune: general_purpose::URL_SAFE.decode(&rune).unwrap(),
2129 };
2130 assert!(signer.verify_rune(r).is_err());
2131
2132 let uri = "/greenlight.Node/CreateInvoice".to_string();
2135 let r = pb::PendingRequest {
2136 request: vec![],
2137 uri,
2138 signature: vec![],
2139 pubkey: pubkey.clone(),
2140 timestamp: 0,
2141 rune: general_purpose::URL_SAFE.decode(&rune).unwrap(),
2142 };
2143 assert!(signer.verify_rune(r).is_ok());
2144
2145 let uri = "/wrong.Service/CreateInvoice".to_string();
2148 let r = pb::PendingRequest {
2149 request: vec![],
2150 uri,
2151 signature: vec![],
2152 pubkey: pubkey.clone(),
2153 timestamp: 0,
2154 rune: general_purpose::URL_SAFE.decode(&rune).unwrap(),
2155 };
2156 assert!(signer.verify_rune(r).is_err());
2157 }
2158
2159 #[test]
2160 fn test_empty_rune_is_valid() {
2161 let creds = credentials::Nobody::default();
2162 let signer = Signer::new(vec![0u8; 32], Network::Bitcoin, creds).unwrap();
2163
2164 let pubkey = signer.node_id();
2166 let pubkey_rest = format!("pubkey={}", hex::encode(&pubkey));
2167
2168 let rune = signer.create_rune(None, vec![vec![&pubkey_rest]]).unwrap();
2169 let uri = "/cln.Node/Pay".to_string();
2170 assert!(signer
2171 .verify_rune(crate::pb::PendingRequest {
2172 request: vec![],
2173 uri,
2174 signature: vec![],
2175 pubkey,
2176 timestamp: 0,
2177 rune: general_purpose::URL_SAFE.decode(rune).unwrap(),
2178 })
2179 .is_ok());
2180 }
2181
2182 #[test]
2183 fn test_empty_rune_checks_pubkey() {
2184 let creds = credentials::Nobody::default();
2185 let signer = Signer::new(vec![0u8; 32], Network::Bitcoin, creds).unwrap();
2186
2187 let pubkey = signer.node_id();
2189 let pubkey_rest = format!("pubkey={}", hex::encode(&pubkey));
2190
2191 let rune = signer.create_rune(None, vec![vec![&pubkey_rest]]).unwrap();
2192 let uri = "/cln.Node/Pay".to_string();
2193 assert!(signer
2194 .verify_rune(crate::pb::PendingRequest {
2195 request: vec![],
2196 uri,
2197 signature: vec![],
2198 pubkey: hex::decode("33aabb").unwrap(),
2199 timestamp: 0,
2200 rune: general_purpose::URL_SAFE.decode(rune).unwrap(),
2201 })
2202 .is_err());
2203 }
2204}