1use super::{Error, Public, Secret};
18use cfx_types::{BigEndianHash as _, H256, U256};
19use secp256k1::{
20 constants::{CURVE_ORDER, GENERATOR_X, GENERATOR_Y},
21 PublicKey, Scalar, SECP256K1,
22};
23
24pub fn public_is_valid(public: &Public) -> bool {
26 public_to_pubkey(public).is_ok()
27}
28
29pub fn public_mul_secret(
31 public: &mut Public, secret: &Secret,
32) -> Result<(), Error> {
33 let key_secret = secret.to_secp256k1_secret()?;
34 let key_public = public_to_pubkey(public)?;
35 let res = key_public.mul_tweak(SECP256K1, &Scalar::from(key_secret))?;
36 *public = pubkey_to_public(&res);
37 Ok(())
38}
39
40pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> {
42 let key_public = public_to_pubkey(public)?;
43 let other_public = public_to_pubkey(other)?;
44 let res = key_public.combine(&other_public)?;
45 *public = pubkey_to_public(&res);
46 Ok(())
47}
48
49pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> {
51 let key_other = public_to_pubkey(other)?;
52 let key_public = public_to_pubkey(public)?;
53 let res = key_public.combine(&key_other.negate(SECP256K1))?;
54 *public = pubkey_to_public(&res);
55 Ok(())
56}
57
58pub fn public_negate(public: &mut Public) -> Result<(), Error> {
60 let key_public = public_to_pubkey(public)?;
61 *public = pubkey_to_public(&key_public.negate(SECP256K1));
62 Ok(())
63}
64
65pub fn generation_point() -> Public {
67 let mut public_sec_raw = [0u8; 65];
68 public_sec_raw[0] = 4;
69 public_sec_raw[1..33].copy_from_slice(&GENERATOR_X);
70 public_sec_raw[33..65].copy_from_slice(&GENERATOR_Y);
71
72 let public_key = PublicKey::from_slice(&public_sec_raw)
73 .expect("constructing using predefined constants; qed");
74 pubkey_to_public(&public_key)
75}
76
77pub fn curve_order() -> U256 { H256::from_slice(&CURVE_ORDER).into_uint() }
79
80pub(crate) fn public_to_pubkey(public: &Public) -> Result<PublicKey, Error> {
83 let mut buf = [4u8; 65];
84 buf[1..65].copy_from_slice(&public[0..64]);
85 Ok(PublicKey::from_slice(&buf)?)
86}
87
88pub(crate) fn pubkey_to_public(pk: &PublicKey) -> Public {
91 let serialized = pk.serialize_uncompressed();
92 let mut public = Public::default();
93 public.as_bytes_mut().copy_from_slice(&serialized[1..65]);
94 public
95}
96
97#[cfg(test)]
98mod tests {
99 use super::{
100 super::{KeyPairGenerator, Public, Random},
101 public_add, public_is_valid, public_sub,
102 };
103
104 #[test]
105 fn zero_public_is_rejected() {
106 assert!(!public_is_valid(&Public::zero()));
112 }
113
114 #[test]
115 fn public_addition_is_commutative() {
116 let public1 = Random.generate().unwrap().public().clone();
117 let public2 = Random.generate().unwrap().public().clone();
118
119 let mut left = public1.clone();
120 public_add(&mut left, &public2).unwrap();
121
122 let mut right = public2.clone();
123 public_add(&mut right, &public1).unwrap();
124
125 assert_eq!(left, right);
126 }
127
128 #[test]
129 fn public_addition_is_reversible_with_subtraction() {
130 let public1 = Random.generate().unwrap().public().clone();
131 let public2 = Random.generate().unwrap().public().clone();
132
133 let mut sum = public1.clone();
134 public_add(&mut sum, &public2).unwrap();
135 public_sub(&mut sum, &public2).unwrap();
136
137 assert_eq!(sum, public1);
138 }
139}