Skip to content

Commit cb2909e

Browse files
committed
Support signing BOLT 12 messages in NodeSigner
BOLT 12 messages need to be signed in the following scenarios: - constructing an InvoiceRequest after scanning an Offer, - constructing an Invoice after scanning a Refund, and - constructing an Invoice when handling an InvoiceRequest. Extend the NodeSigner trait to support signing BOLT 12 messages such that it can be used in these contexts. The method could be used then in OnionMessenger and an OffersMessageHandler.
1 parent 226dbf9 commit cb2909e

File tree

5 files changed

+63
-3
lines changed

5 files changed

+63
-3
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use crate::utils::test_persister::TestPersister;
5858
use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
5959
use bitcoin::secp256k1::ecdh::SharedSecret;
6060
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
61+
use bitcoin::secp256k1::schnorr;
6162

6263
use std::mem;
6364
use std::cmp::{self, Ordering};
@@ -212,6 +213,12 @@ impl NodeSigner for KeyProvider {
212213
unreachable!()
213214
}
214215

216+
fn sign_bolt12_message(
217+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
218+
) -> Result<schnorr::Signature, ()> {
219+
unreachable!()
220+
}
221+
215222
fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
216223
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
217224
let secp_ctx = Secp256k1::signing_only();

fuzz/src/full_stack.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use crate::utils::test_persister::TestPersister;
5757
use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
5858
use bitcoin::secp256k1::ecdh::SharedSecret;
5959
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
60+
use bitcoin::secp256k1::schnorr;
6061

6162
use std::cell::RefCell;
6263
use hashbrown::{HashMap, hash_map};
@@ -317,6 +318,12 @@ impl NodeSigner for KeyProvider {
317318
unreachable!()
318319
}
319320

321+
fn sign_bolt12_message(
322+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
323+
) -> Result<schnorr::Signature, ()> {
324+
unreachable!()
325+
}
326+
320327
fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
321328
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
322329
let secp_ctx = Secp256k1::signing_only();

fuzz/src/onion_message.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Imports that need to be added manually
22
use bitcoin::bech32::u5;
33
use bitcoin::blockdata::script::Script;
4-
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
4+
use bitcoin::secp256k1::{Message, PublicKey, Scalar, Secp256k1, SecretKey};
55
use bitcoin::secp256k1::ecdh::SharedSecret;
66
use bitcoin::secp256k1::ecdsa::RecoverableSignature;
7+
use bitcoin::secp256k1::schnorr;
78

89
use lightning::chain::keysinterface::{Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
910
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -158,6 +159,12 @@ impl NodeSigner for KeyProvider {
158159
unreachable!()
159160
}
160161

162+
fn sign_bolt12_message(
163+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
164+
) -> Result<schnorr::Signature, ()> {
165+
unreachable!()
166+
}
167+
161168
fn sign_gossip_message(&self, _msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
162169
unreachable!()
163170
}

lightning/src/chain/keysinterface.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ use bitcoin::hashes::sha256::Hash as Sha256;
2525
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
2626
use bitcoin::hash_types::WPubkeyHash;
2727

28-
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, Signing};
28+
use bitcoin::secp256k1::{Message, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
2929
use bitcoin::secp256k1::ecdh::SharedSecret;
3030
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
31+
use bitcoin::secp256k1::schnorr;
3132
use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};
3233

3334
use crate::util::transaction_utils;
@@ -494,6 +495,19 @@ pub trait NodeSigner {
494495
/// Errors if the [`Recipient`] variant is not supported by the implementation.
495496
fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()>;
496497

498+
/// Signs a BOLT 12 message.
499+
///
500+
/// The message is given in `bytes` as a serialized TLV stream with `tag` identifying the
501+
/// message type as defined in the BOLT 12 spec's "Signature Calculation" section. The `digest`
502+
/// is the tagged merkle root to be signed and can be re-calculated using `tag` and `bytes` if
503+
/// blindly signing the digest should be avoided.
504+
///
505+
/// `metadata` is either the payer or offer metadata, depending on the message type and origin,
506+
/// and may be useful in order to derive the signing keys.
507+
fn sign_bolt12_message(
508+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
509+
) -> Result<schnorr::Signature, ()>;
510+
497511
/// Sign a gossip message.
498512
///
499513
/// Note that if this fails, LDK may panic and the message will not be broadcast to the network
@@ -1286,6 +1300,12 @@ impl NodeSigner for KeysManager {
12861300
Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
12871301
}
12881302

1303+
fn sign_bolt12_message(
1304+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
1305+
) -> Result<schnorr::Signature, ()> {
1306+
todo!()
1307+
}
1308+
12891309
fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
12901310
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
12911311
Ok(sign(&self.secp_ctx, &msg_hash, &self.node_secret))
@@ -1394,6 +1414,12 @@ impl NodeSigner for PhantomKeysManager {
13941414
Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
13951415
}
13961416

1417+
fn sign_bolt12_message(
1418+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
1419+
) -> Result<schnorr::Signature, ()> {
1420+
todo!()
1421+
}
1422+
13971423
fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
13981424
self.inner.sign_gossip_message(msg)
13991425
}

lightning/src/util/test_utils.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ use bitcoin::blockdata::block::Block;
4040
use bitcoin::network::constants::Network;
4141
use bitcoin::hash_types::{BlockHash, Txid};
4242

43-
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
43+
use bitcoin::secp256k1::{Message, PublicKey, Scalar, Secp256k1, SecretKey};
4444
use bitcoin::secp256k1::ecdh::SharedSecret;
4545
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
46+
use bitcoin::secp256k1::schnorr;
4647

4748
use regex;
4849

@@ -711,6 +712,12 @@ impl NodeSigner for TestNodeSigner {
711712
unreachable!()
712713
}
713714

715+
fn sign_bolt12_message(
716+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
717+
) -> Result<schnorr::Signature, ()> {
718+
unreachable!()
719+
}
720+
714721
fn sign_gossip_message(&self, _msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
715722
unreachable!()
716723
}
@@ -751,6 +758,12 @@ impl NodeSigner for TestKeysInterface {
751758
self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
752759
}
753760

761+
fn sign_bolt12_message(
762+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
763+
) -> Result<schnorr::Signature, ()> {
764+
self.backing.sign_bolt12_message(digest, tag, bytes, metadata)
765+
}
766+
754767
fn sign_gossip_message(&self, msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
755768
self.backing.sign_gossip_message(msg)
756769
}

0 commit comments

Comments
 (0)