use secp256k1::{PublicKey, Secp256k1, SecretKey, XOnlyPublicKey};
use std::collections::HashMap;
use crate::utils::common::calculate_t_n;
use crate::utils::sending::calculate_ecdh_shared_secret;
use crate::Result;
use crate::SilentPaymentAddress;
pub fn generate_recipient_pubkeys(
recipients: Vec<SilentPaymentAddress>,
partial_secret: SecretKey,
) -> Result<HashMap<SilentPaymentAddress, Vec<XOnlyPublicKey>>> {
let secp = Secp256k1::new();
let mut silent_payment_groups: HashMap<PublicKey, (PublicKey, Vec<SilentPaymentAddress>)> =
HashMap::new();
for address in recipients {
let B_scan = address.get_scan_key();
if let Some((_, payments)) = silent_payment_groups.get_mut(&B_scan) {
payments.push(address);
} else {
let ecdh_shared_secret = calculate_ecdh_shared_secret(&B_scan, &partial_secret);
silent_payment_groups.insert(B_scan, (ecdh_shared_secret, vec![address]));
}
}
let mut result: HashMap<SilentPaymentAddress, Vec<XOnlyPublicKey>> = HashMap::new();
for group in silent_payment_groups.into_values() {
let mut n = 0;
let (ecdh_shared_secret, recipients) = group;
for addr in recipients {
let t_n = calculate_t_n(&ecdh_shared_secret, n)?;
let res = t_n.public_key(&secp);
let reskey = res.combine(&addr.get_spend_key())?;
let (reskey_xonly, _) = reskey.x_only_public_key();
let entry = result.entry(addr.into()).or_default();
entry.push(reskey_xonly);
n += 1;
}
}
Ok(result)
}