blob: d6478992c06096bfcaee1cfccc1a915c63126f1b (
plain) (
blame)
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
|
use bls12_381::{ G1Affine, G1Projective, Scalar };
pub const BLS_PUBKEY_SIZE: usize = 48;
pub type BLSPubkey = [u8; BLS_PUBKEY_SIZE];
// Originally implemented in https://github.com/metacraft-labs/dvt-circuits/blob/master/crates/bls_utils/src/bls.rs
#[guests_macro::proving_entrypoint]
pub fn main(
pks: Vec<String>,
target: String,
) -> bool {
let pks: Vec<G1Affine> = pks
.iter().map(|pk| -> BLSPubkey {
hex::decode(pk).unwrap().try_into().unwrap()
})
.map(|pk| G1Affine::from_compressed(&pk).into_option().unwrap()).collect();
let id = bls_id_from_u32(1);
let result = evaluate_polynomial(pks, id);
hex::encode(result.to_compressed()) == target
}
pub fn bls_id_from_u32(id: u32) -> Scalar {
let unwrapped_le: [u8; 4] = (id as u32).to_le_bytes();
let mut bytes = [0u8; 32];
bytes[..4].copy_from_slice(&unwrapped_le);
Scalar::from_bytes(&bytes).unwrap()
}
// https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
//
// In Shamir's secret sharing, a secret is encoded as a n-degree polynomial
// F where the secret value is equal to F(0). Here, F(0) is provided as mask[0].
//
// A key share is generated by evaluating the polynomial in the `id` point.
// Later we can use at least N of these points to recover the original secret.
//
// Furthermore, if we sign some message M with at least K of the secret key
// shares we can restore from them the signature of the same message signed
// with original secret key.
//
// For a more gentle introductiont to Shamir's secret sharing, see also:
//
// https://github.com/dashpay/dips/blob/master/dip-0006/bls_m-of-n_threshold_scheme_and_dkg.md
// https://medium.com/toruslabs/what-distributed-key-generation-is-866adc79620
pub fn evaluate_polynomial(cfs: Vec<G1Affine>, x: Scalar) -> G1Affine {
let cfst: Vec<G1Projective> = cfs.iter().map(|c| G1Projective::from(c)).collect();
let count = cfst.len();
if count == 0 {
return G1Affine::identity();
} else if count == 1 {
return cfs[0];
} else {
let mut y = cfst[count - 1];
for i in 2..(count + 1) {
y = y * x + cfs[count - i];
}
return G1Affine::from(y);
}
}
|