Skip to content

Add KeysInterface::get_node_id method #1779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion lightning/src/chain/keysinterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,28 @@ pub trait KeysInterface {
///
/// This method must return the same value each time it is called with a given `Recipient`
/// parameter.
///
/// Errors if the `Recipient` variant is not supported by the implementation.
fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()>;
/// Get node id based on the provided [`Recipient`]. This public key corresponds to the secret in
/// [`get_node_secret`].
///
/// This method must return the same value each time it is called with a given `Recipient`
/// parameter.
///
/// Errors if the `Recipient` variant is not supported by the implementation.
///
/// [`get_node_secret`]: KeysInterface::get_node_secret
fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
let secp_ctx = Secp256k1::signing_only();
Ok(PublicKey::from_secret_key(&secp_ctx, &self.get_node_secret(recipient)?))
}
/// Gets the ECDH shared secret of our [`node secret`] and `other_key`, multiplying by `tweak` if
/// one is provided. Note that this tweak can be applied to `other_key` instead of our node
/// secret, though this is less efficient.
///
/// Errors if the `Recipient` variant is not supported by the implementation.
///
/// [`node secret`]: Self::get_node_secret
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>;
/// Get a script pubkey which we send funds to when claiming on-chain contestable outputs.
Expand Down Expand Up @@ -455,6 +472,8 @@ pub trait KeysInterface {
/// The hrp is ascii bytes, while the invoice data is base32.
///
/// The secret key used to sign the invoice is dependent on the [`Recipient`].
///
/// Errors if the `Recipient` variant is not supported by the implementation.
fn sign_invoice(&self, hrp_bytes: &[u8], invoice_data: &[u5], receipient: Recipient) -> Result<RecoverableSignature, ()>;

/// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
Expand Down Expand Up @@ -871,6 +890,7 @@ impl ReadableArgs<SecretKey> for InMemorySigner {
pub struct KeysManager {
secp_ctx: Secp256k1<secp256k1::All>,
node_secret: SecretKey,
node_id: PublicKey,
inbound_payment_key: KeyMaterial,
destination_script: Script,
shutdown_pubkey: PublicKey,
Expand Down Expand Up @@ -912,6 +932,7 @@ impl KeysManager {
match ExtendedPrivKey::new_master(Network::Testnet, seed) {
Ok(master_key) => {
let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0).unwrap()).expect("Your RNG is busted").private_key;
let node_id = PublicKey::from_secret_key(&secp_ctx, &node_secret);
let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1).unwrap()) {
Ok(destination_key) => {
let wpubkey_hash = WPubkeyHash::hash(&ExtendedPubKey::from_priv(&secp_ctx, &destination_key).to_pub().to_bytes());
Expand Down Expand Up @@ -939,6 +960,7 @@ impl KeysManager {
let mut res = KeysManager {
secp_ctx,
node_secret,
node_id,
inbound_payment_key: KeyMaterial(inbound_pmt_key_bytes),

destination_script,
Expand Down Expand Up @@ -1158,6 +1180,13 @@ impl KeysInterface for KeysManager {
}
}

fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
match recipient {
Recipient::Node => Ok(self.node_id.clone()),
Recipient::PhantomNode => Err(())
}
}

fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
let mut node_secret = self.get_node_secret(recipient)?;
if let Some(tweak) = tweak {
Expand Down Expand Up @@ -1238,6 +1267,7 @@ pub struct PhantomKeysManager {
inner: KeysManager,
inbound_payment_key: KeyMaterial,
phantom_secret: SecretKey,
phantom_node_id: PublicKey,
}

impl KeysInterface for PhantomKeysManager {
Expand All @@ -1250,6 +1280,13 @@ impl KeysInterface for PhantomKeysManager {
}
}

fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
match recipient {
Recipient::Node => self.inner.get_node_id(Recipient::Node),
Recipient::PhantomNode => Ok(self.phantom_node_id.clone()),
}
}

fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
let mut node_secret = self.get_node_secret(recipient)?;
if let Some(tweak) = tweak {
Expand Down Expand Up @@ -1303,10 +1340,13 @@ impl PhantomKeysManager {
pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32, cross_node_seed: &[u8; 32]) -> Self {
let inner = KeysManager::new(seed, starting_time_secs, starting_time_nanos);
let (inbound_key, phantom_key) = hkdf_extract_expand_twice(b"LDK Inbound and Phantom Payment Key Expansion", cross_node_seed);
let phantom_secret = SecretKey::from_slice(&phantom_key).unwrap();
let phantom_node_id = PublicKey::from_secret_key(&inner.secp_ctx, &phantom_secret);
Self {
inner,
inbound_payment_key: KeyMaterial(inbound_key),
phantom_secret: SecretKey::from_slice(&phantom_key).unwrap(),
phantom_secret,
phantom_node_id,
}
}

Expand Down
3 changes: 3 additions & 0 deletions lightning/src/util/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,9 @@ impl keysinterface::KeysInterface for TestKeysInterface {
fn get_node_secret(&self, recipient: Recipient) -> Result<SecretKey, ()> {
self.backing.get_node_secret(recipient)
}
fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
self.backing.get_node_id(recipient)
}
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
self.backing.ecdh(recipient, other_key, tweak)
}
Expand Down