From cd56fee7cf291e8c6c82a5a45f8c99094e780377 Mon Sep 17 00:00:00 2001 From: Martti Malmi Date: Sat, 9 May 2026 18:14:00 +0300 Subject: [PATCH] identity: eagerly precompute pubkey_full in PeerIdentity::from_pubkey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PeerIdentity::pubkey_full()` falls through to `self.pubkey.public_key(Parity::Even)` whenever the parity-aware full key wasn't passed at construction (i.e. for every peer constructed from an npub or x-only key). Underneath, that runs a secp256k1 EC point parse — `fe_sqrt` + `fe_mul` + `ge_set_xo_var` — which is ~6% of per-packet CPU on the bulk-data send path for a value that never changes after construction. Compute it eagerly. The same EC point parse already runs at construction inside `NodeAddr::from_pubkey`, so the cost is paid once where it would be paid anyway. --- src/identity/peer.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/identity/peer.rs b/src/identity/peer.rs index b6a7fce..06f65f7 100644 --- a/src/identity/peer.rs +++ b/src/identity/peer.rs @@ -24,12 +24,22 @@ impl PeerIdentity { /// /// Note: When only the x-only key is available, the full public key /// will be derived assuming even parity for ECDH operations. + /// + /// Precomputes the even-parity full pubkey eagerly so `pubkey_full()` + /// is a constant-time field load. Without this, every send-side + /// hot-path caller (per-packet) re-derived the full key, spending + /// ~6% of CPU on a secp256k1 EC point parse (`fe_sqrt` + `fe_mul` + + /// `ge_set_xo_var`) for what should be a memoized lookup. The same + /// EC point parse already runs at construction inside + /// `NodeAddr::from_pubkey`, so the cost is paid where it would be + /// paid anyway. pub fn from_pubkey(pubkey: XOnlyPublicKey) -> Self { let node_addr = NodeAddr::from_pubkey(&pubkey); let address = FipsAddress::from_node_addr(&node_addr); + let pubkey_full = pubkey.public_key(Parity::Even); Self { pubkey, - pubkey_full: None, + pubkey_full: Some(pubkey_full), node_addr, address, }