Skip to content

Commit

Permalink
Support signing BOLT 12 messages in NodeSigner
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jkczyz committed Jul 27, 2023
1 parent bb4e7dc commit b7e1a0a
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 1 deletion.
8 changes: 8 additions & 0 deletions fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
use lightning::ln::msgs::{self, CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init};
use lightning::ln::script::ShutdownScript;
use lightning::ln::functional_test_utils::*;
use lightning::offers::merkle::TaggedHash;
use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
use lightning::util::errors::APIError;
use lightning::util::logger::Logger;
Expand All @@ -57,6 +58,7 @@ use crate::utils::test_persister::TestPersister;
use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use bitcoin::secp256k1::schnorr;

use std::mem;
use std::cmp::{self, Ordering};
Expand Down Expand Up @@ -211,6 +213,12 @@ impl NodeSigner for KeyProvider {
unreachable!()
}

fn sign_bolt12_message(
&self, _message: &TaggedHash, _metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
unreachable!()
}

fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
let secp_ctx = Secp256k1::signing_only();
Expand Down
8 changes: 8 additions & 0 deletions fuzz/src/full_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
use lightning::ln::msgs::{self, DecodeError};
use lightning::ln::script::ShutdownScript;
use lightning::ln::functional_test_utils::*;
use lightning::offers::merkle::TaggedHash;
use lightning::routing::gossip::{P2PGossipSync, NetworkGraph};
use lightning::routing::utxo::UtxoLookup;
use lightning::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router};
Expand All @@ -55,6 +56,7 @@ use crate::utils::test_persister::TestPersister;
use bitcoin::secp256k1::{Message, PublicKey, SecretKey, Scalar, Secp256k1};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use bitcoin::secp256k1::schnorr;

use std::cell::RefCell;
use hashbrown::{HashMap, hash_map};
Expand Down Expand Up @@ -316,6 +318,12 @@ impl NodeSigner for KeyProvider {
unreachable!()
}

fn sign_bolt12_message(
&self, _message: &TaggedHash, _metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
unreachable!()
}

fn sign_gossip_message(&self, msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
let msg_hash = Message::from_slice(&Sha256dHash::hash(&msg.encode()[..])[..]).map_err(|_| ())?;
let secp_ctx = Secp256k1::signing_only();
Expand Down
8 changes: 8 additions & 0 deletions fuzz/src/onion_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ use bitcoin::blockdata::script::Script;
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::RecoverableSignature;
use bitcoin::secp256k1::schnorr;

use lightning::sign::{Recipient, KeyMaterial, EntropySource, NodeSigner, SignerProvider};
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
use lightning::ln::script::ShutdownScript;
use lightning::offers::merkle::TaggedHash;
use lightning::util::enforcing_trait_impls::EnforcingSigner;
use lightning::util::logger::Logger;
use lightning::util::ser::{Readable, Writeable, Writer};
Expand Down Expand Up @@ -153,6 +155,12 @@ impl NodeSigner for KeyProvider {
unreachable!()
}

fn sign_bolt12_message(
&self, _message: &TaggedHash, _metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
unreachable!()
}

fn sign_gossip_message(&self, _msg: lightning::ln::msgs::UnsignedGossipMessage) -> Result<bitcoin::secp256k1::ecdsa::Signature, ()> {
unreachable!()
}
Expand Down
27 changes: 26 additions & 1 deletion lightning/src/sign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
use bitcoin::hash_types::WPubkeyHash;

use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, Signing};
use bitcoin::secp256k1::{KeyPair, PublicKey, Scalar, Secp256k1, SecretKey, Signing};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use bitcoin::secp256k1::schnorr;
use bitcoin::{PackedLockTime, secp256k1, Sequence, Witness};

use crate::util::transaction_utils;
Expand All @@ -42,6 +43,7 @@ use crate::ln::{chan_utils, PaymentPreimage};
use crate::ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction, ClosingTransaction};
use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
use crate::ln::script::ShutdownScript;
use crate::offers::merkle::TaggedHash;

use crate::prelude::*;
use core::convert::TryInto;
Expand Down Expand Up @@ -620,6 +622,15 @@ pub trait NodeSigner {
/// Errors if the [`Recipient`] variant is not supported by the implementation.
fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient) -> Result<RecoverableSignature, ()>;

/// Signs a BOLT 12 message.
///
/// See [`SignFunction`] for details.
///
/// [`SignFunction`]: crate::offers::merkle::SignFunction
fn sign_bolt12_message(
&self, message: &TaggedHash, metadata: &[u8]
) -> Result<schnorr::Signature, ()>;

/// Sign a gossip message.
///
/// Note that if this fails, LDK may panic and the message will not be broadcast to the network
Expand Down Expand Up @@ -1453,6 +1464,14 @@ impl NodeSigner for KeysManager {
Ok(self.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
}

fn sign_bolt12_message(
&self, message: &TaggedHash, _metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
let keys = KeyPair::from_secret_key(&self.secp_ctx, &self.node_secret);
let aux_rand = self.get_secure_random_bytes();
Ok(self.secp_ctx.sign_schnorr_with_aux_rand(&message.to_digest(), &keys, &aux_rand))
}

fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
Ok(self.secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret))
Expand Down Expand Up @@ -1561,6 +1580,12 @@ impl NodeSigner for PhantomKeysManager {
Ok(self.inner.secp_ctx.sign_ecdsa_recoverable(&hash_to_message!(&Sha256::hash(&preimage)), secret))
}

fn sign_bolt12_message(
&self, message: &TaggedHash, metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
self.inner.sign_bolt12_message(message, metadata)
}

fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
self.inner.sign_gossip_message(msg)
}
Expand Down
14 changes: 14 additions & 0 deletions lightning/src/util/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
use crate::ln::{msgs, wire};
use crate::ln::msgs::LightningError;
use crate::ln::script::ShutdownScript;
use crate::offers::merkle::TaggedHash;
use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId};
use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult};
use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParameters, Router, ScorerAccountingForInFlightHtlcs};
Expand All @@ -44,6 +45,7 @@ use bitcoin::hash_types::{BlockHash, Txid};
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey};
use bitcoin::secp256k1::ecdh::SharedSecret;
use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
use bitcoin::secp256k1::schnorr;

use regex;

Expand Down Expand Up @@ -795,6 +797,12 @@ impl NodeSigner for TestNodeSigner {
unreachable!()
}

fn sign_bolt12_message(
&self, _message: &TaggedHash, _metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
unreachable!()
}

fn sign_gossip_message(&self, _msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
unreachable!()
}
Expand Down Expand Up @@ -835,6 +843,12 @@ impl NodeSigner for TestKeysInterface {
self.backing.sign_invoice(hrp_bytes, invoice_data, recipient)
}

fn sign_bolt12_message(
&self, message: &TaggedHash, metadata: &[u8]
) -> Result<schnorr::Signature, ()> {
self.backing.sign_bolt12_message(message, metadata)
}

fn sign_gossip_message(&self, msg: msgs::UnsignedGossipMessage) -> Result<Signature, ()> {
self.backing.sign_gossip_message(msg)
}
Expand Down

0 comments on commit b7e1a0a

Please sign in to comment.