identity: eagerly precompute pubkey_full in PeerIdentity::from_pubkey

`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.
This commit is contained in:
Martti Malmi
2026-05-10 00:28:45 +03:00
committed by Dev
parent f0bb29ff6e
commit cd56fee7cf
+11 -1
View File
@@ -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,
}