1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use crate::{
errors::{self, MuSigError},
MuSigContext, PublicKey, SchnorrError,
};
use bacteria::Transcript;
use mohan::dalek::{ristretto::RistrettoPoint, scalar::Scalar};
#[derive(Clone)]
pub struct MultiKey {
prf: Option<Transcript>,
aggregated_key: PublicKey,
public_keys: Vec<PublicKey>,
}
impl MultiKey {
pub fn new(pubkeys: Vec<PublicKey>) -> Result<Self, SchnorrError> {
match pubkeys.len() {
0 => {
return Err(errors::from_musig(MuSigError::BadArguments));
}
1 => {
return Ok(MultiKey {
prf: None,
aggregated_key: pubkeys[0],
public_keys: pubkeys,
});
}
_ => {}
}
let mut prf = Transcript::new(b"Musig.aggregated-key");
prf.append_u64(b"n", pubkeys.len() as u64);
for X in &pubkeys {
prf.commit_point(b"X", X.as_compressed());
}
let mut aggregated_key = RistrettoPoint::default();
for (i, X) in pubkeys.iter().enumerate() {
let a = MultiKey::compute_factor(&prf, i);
let X = X.into_point();
aggregated_key = aggregated_key + a * X;
}
Ok(MultiKey {
prf: Some(prf),
aggregated_key: PublicKey::from_point(aggregated_key),
public_keys: pubkeys,
})
}
fn compute_factor(prf: &Transcript, i: usize) -> Scalar {
let mut a_i_prf = prf.clone();
a_i_prf.append_u64(b"i", i as u64);
a_i_prf.challenge_scalar(b"a_i")
}
pub fn aggregated_key(&self) -> PublicKey {
self.aggregated_key
}
}
impl MuSigContext for MultiKey {
fn commit(&self, transcript: &mut Transcript) {
transcript.proto_name(b"organism_schnorr");
transcript.commit_point(b"public_key", self.aggregated_key.as_compressed());
}
fn challenge(&self, i: usize, transcript: &mut Transcript) -> Scalar {
let c = transcript.challenge_scalar(b"c");
let a_i = match &self.prf {
Some(t) => MultiKey::compute_factor(&t, i),
None => Scalar::one(),
};
c * a_i
}
fn len(&self) -> usize {
self.public_keys.len()
}
fn key(&self, index: usize) -> PublicKey {
self.public_keys[index]
}
}