Skip to content

Commit 82dfdae

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 2dae1fb commit 82dfdae

File tree

5 files changed

+65
-3
lines changed

5 files changed

+65
-3
lines changed

fuzz/src/chanmon_consistency.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::mem;
6263
use std::cmp::{self, Ordering};
@@ -211,6 +212,12 @@ impl NodeSigner for KeyProvider {
211212
unreachable!()
212213
}
213214

215+
fn sign_bolt12_message(
216+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
217+
) -> Result<schnorr::Signature, ()> {
218+
unreachable!()
219+
}
220+
214221
fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
215222
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
216223
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
@@ -55,6 +55,7 @@ use crate::utils::test_persister::TestPersister;
5555
use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
5656
use bitcoin::secp256k1::ecdh::SharedSecret;
5757
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
58+
use bitcoin::secp256k1::schnorr;
5859

5960
use std::cell::RefCell;
6061
use hashbrown::{HashMap, hash_map};
@@ -316,6 +317,12 @@ impl NodeSigner for KeyProvider {
316317
unreachable!()
317318
}
318319

320+
fn sign_bolt12_message(
321+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
322+
) -> Result<schnorr::Signature, ()> {
323+
unreachable!()
324+
}
325+
319326
fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
320327
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
321328
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::sign::{Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
910
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -153,6 +154,12 @@ impl NodeSigner for KeyProvider {
153154
unreachable!()
154155
}
155156

157+
fn sign_bolt12_message(
158+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
159+
) -> Result<schnorr::Signature, ()> {
160+
unreachable!()
161+
}
162+
156163
fn sign_gossip_message(&self, _msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
157164
unreachable!()
158165
}

lightning/src/sign/mod.rs

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

29-
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, Signing};
29+
use bitcoin::secp256k1::{KeyPair, Message, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
3030
use bitcoin::secp256k1::ecdh::SharedSecret;
3131
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
32+
use bitcoin::secp256k1::schnorr;
3233
use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};
3334

3435
use crate::util::transaction_utils;
@@ -620,6 +621,19 @@ pub trait NodeSigner {
620621
/// Errors if the [`Recipient`] variant is not supported by the implementation.
621622
fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()>;
622623

624+
/// Signs a BOLT 12 message.
625+
///
626+
/// The message is given in `bytes` as a serialized TLV stream with `tag` identifying the
627+
/// message type as defined in the BOLT 12 spec's "Signature Calculation" section. The `digest`
628+
/// is the tagged merkle root to be signed and can be re-calculated using `tag` and `bytes` if
629+
/// blindly signing the digest should be avoided.
630+
///
631+
/// `metadata` is either the payer or offer metadata, depending on the message type and origin,
632+
/// and may be useful in order to derive the signing keys.
633+
fn sign_bolt12_message(
634+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
635+
) -> Result<schnorr::Signature, ()>;
636+
623637
/// Sign a gossip message.
624638
///
625639
/// Note that if this fails, LDK may panic and the message will not be broadcast to the network
@@ -1453,6 +1467,14 @@ impl NodeSigner for KeysManager {
14531467
Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
14541468
}
14551469

1470+
fn sign_bolt12_message(
1471+
&self, digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
1472+
) -> Result<schnorr::Signature, ()> {
1473+
let keys = KeyPair::from_secret_key(&self.secp_ctx, &self.node_secret);
1474+
let aux_rand = self.get_secure_random_bytes();
1475+
Ok(self.secp_ctx.sign_schnorr_with_aux_rand(digest, &keys, &aux_rand))
1476+
}
1477+
14561478
fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
14571479
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
14581480
Ok(self.secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
@@ -1561,6 +1583,12 @@ impl NodeSigner for PhantomKeysManager {
15611583
Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
15621584
}
15631585

1586+
fn sign_bolt12_message(
1587+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
1588+
) -> Result<schnorr::Signature, ()> {
1589+
self.inner.sign_bolt12_message(digest, tag, bytes, metadata)
1590+
}
1591+
15641592
fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
15651593
self.inner.sign_gossip_message(msg)
15661594
}

lightning/src/util/test_utils.rs

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

44-
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
44+
use bitcoin::secp256k1::{Message, PublicKey, Scalar, Secp256k1, SecretKey};
4545
use bitcoin::secp256k1::ecdh::SharedSecret;
4646
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
47+
use bitcoin::secp256k1::schnorr;
4748

4849
use regex;
4950

@@ -795,6 +796,12 @@ impl NodeSigner for TestNodeSigner {
795796
unreachable!()
796797
}
797798

799+
fn sign_bolt12_message(
800+
&self, _digest: &Message, _tag: &str, _bytes: &[u8], _metadata: &[u8]
801+
) -> Result<schnorr::Signature, ()> {
802+
unreachable!()
803+
}
804+
798805
fn sign_gossip_message(&self, _msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
799806
unreachable!()
800807
}
@@ -835,6 +842,12 @@ impl NodeSigner for TestKeysInterface {
835842
self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
836843
}
837844

845+
fn sign_bolt12_message(
846+
&self, digest: &Message, tag: &str, bytes: &[u8], metadata: &[u8]
847+
) -> Result<schnorr::Signature, ()> {
848+
self.backing.sign_bolt12_message(digest, tag, bytes, metadata)
849+
}
850+
838851
fn sign_gossip_message(&self, msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
839852
self.backing.sign_gossip_message(msg)
840853
}

0 commit comments

Comments
 (0)