2022-04-21 21:36:18 -04:00
|
|
|
use rand_core::{RngCore, CryptoRng};
|
|
|
|
|
|
|
|
|
|
use curve25519_dalek::edwards::EdwardsPoint;
|
|
|
|
|
use dalek_ff_group::Scalar;
|
|
|
|
|
use frost::{MultisigKeys, sign::lagrange};
|
|
|
|
|
|
2022-04-28 03:31:09 -04:00
|
|
|
use crate::{hash_to_point, frost::{MultisigError, Ed25519, DLEqProof}};
|
2022-04-21 21:36:18 -04:00
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
|
pub struct Package {
|
|
|
|
|
// Don't serialize
|
|
|
|
|
H: EdwardsPoint,
|
|
|
|
|
i: usize,
|
|
|
|
|
|
|
|
|
|
// Serialize
|
|
|
|
|
image: EdwardsPoint,
|
|
|
|
|
proof: DLEqProof
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
|
pub fn multisig<R: RngCore + CryptoRng>(
|
|
|
|
|
rng: &mut R,
|
|
|
|
|
keys: &MultisigKeys<Ed25519>,
|
|
|
|
|
included: &[usize]
|
|
|
|
|
) -> Package {
|
|
|
|
|
let i = keys.params().i();
|
|
|
|
|
let secret = (keys.secret_share() * lagrange::<Scalar>(i, included)).0;
|
|
|
|
|
|
|
|
|
|
let H = hash_to_point(&keys.group_key().0);
|
|
|
|
|
let image = secret * H;
|
|
|
|
|
// Includes a proof. Since:
|
|
|
|
|
// sum(lagranged_secrets) = group_private
|
|
|
|
|
// group_private * G = output_key
|
|
|
|
|
// group_private * H = key_image
|
|
|
|
|
// Then sum(lagranged_secrets * H) = key_image
|
|
|
|
|
// lagranged_secret * G is known. lagranged_secret * H is being sent
|
|
|
|
|
// Any discrete log equality proof confirms the same secret was used,
|
|
|
|
|
// forming a valid key_image share
|
|
|
|
|
Package { H, i, image, proof: DLEqProof::prove(rng, &secret, &H, &image) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(non_snake_case)]
|
|
|
|
|
impl Package {
|
|
|
|
|
pub fn resolve(
|
|
|
|
|
self,
|
|
|
|
|
shares: Vec<Option<(EdwardsPoint, Package)>>
|
2022-04-28 03:31:09 -04:00
|
|
|
) -> Result<EdwardsPoint, MultisigError> {
|
2022-04-21 21:36:18 -04:00
|
|
|
let mut included = vec![self.i];
|
|
|
|
|
for i in 1 .. shares.len() {
|
|
|
|
|
if shares[i].is_some() {
|
|
|
|
|
included.push(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut image = self.image;
|
|
|
|
|
for i in 0 .. shares.len() {
|
|
|
|
|
if shares[i].is_none() {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let (other, shares) = shares[i].as_ref().unwrap();
|
|
|
|
|
let other = other * lagrange::<Scalar>(i, &included).0;
|
|
|
|
|
|
|
|
|
|
// Verify their proof
|
|
|
|
|
let share = shares.image;
|
2022-04-28 03:31:09 -04:00
|
|
|
shares.proof.verify(&self.H, &other, &share).map_err(|_| MultisigError::InvalidKeyImage(i))?;
|
2022-04-21 21:36:18 -04:00
|
|
|
|
|
|
|
|
// Add their share to the image
|
|
|
|
|
image += share;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(image)
|
|
|
|
|
}
|
|
|
|
|
}
|