Skip to main content

multi_party_schnorr/common/
mod.rs

1// Copyright (c) Silence Laboratories Pte. Ltd. All Rights Reserved.
2// This software is licensed under the Silence Laboratories License Agreement.
3
4mod dlog_proof;
5mod math;
6
7/// Utility functions
8pub mod utils;
9
10pub use dlog_proof::*;
11
12pub use math::*;
13
14pub mod traits {
15    #[cfg(feature = "taproot")]
16    use crypto_bigint::U512;
17
18    #[cfg(any(feature = "eddsa", feature = "taproot"))]
19    use crypto_bigint::U256;
20
21    use crypto_bigint::subtle::{ConstantTimeEq, CtOption};
22
23    #[cfg(feature = "eddsa")]
24    use crypto_bigint::Encoding;
25
26    use elliptic_curve::{group::GroupEncoding, Group};
27
28    #[cfg(feature = "taproot")]
29    use elliptic_curve::ops::Reduce;
30
31    pub trait InitRound {
32        type OutputMessage;
33        type Next: Round;
34        type Error;
35
36        fn init(self) -> Result<(Self::Next, Self::OutputMessage), Self::Error>;
37    }
38
39    /// Trait that defines a state transition for any round based protocol.
40    pub trait Round {
41        /// Output of the state transition.
42        type Output;
43
44        /// Type of input messages
45        type InputMessage;
46
47        /// Input of the state transition, such as `Vec<InputMessage>`.
48        type Input;
49
50        type Error;
51
52        /// Transition to the next state.
53        fn process(self, messages: Self::Input) -> Result<Self::Output, Self::Error>;
54    }
55
56    pub trait RoundSize {
57        fn message_count(&self) -> usize;
58    }
59
60    pub trait GroupElem: Group + GroupEncoding + ConstantTimeEq {}
61
62    impl<G> GroupElem for G
63    where
64        G: Group + GroupEncoding + ConstantTimeEq,
65        G::Scalar: ScalarReduce<[u8; 32]>,
66    {
67    }
68
69    /// Reduce (little endian) bytes to a scalar.
70    pub trait ScalarReduce<T> {
71        fn reduce_from_bytes(bytes: &T) -> Self;
72    }
73
74    /// Trait that signifies that the Group supports BIP32 derivation and can parse the I_L bytes
75    /// into a valid scalar offset, while performing the less than group order check.
76    /// I_L bytes are the left most 32 bytes of the HMAC-SHA512 output.
77    pub trait BIP32Derive {
78        /// Given the I_L bytes perform the less than group order check and returns a valid scalar.
79        /// Arguments:
80        /// - `bytes`: I_L bytes (32 bytes)
81        ///
82        /// Returns a valid scalar after parsing the I_L bytes.
83        fn parse_offset(bytes: [u8; 32]) -> CtOption<Self>
84        where
85            Self: Sized;
86    }
87
88    #[cfg(feature = "eddsa")]
89    impl BIP32Derive for curve25519_dalek::Scalar {
90        fn parse_offset(bytes: [u8; 32]) -> CtOption<Self> {
91            let mut z_l = [0u8; 32];
92            // NOTE: Follwing BIP32-Ed25519 spec for parsing I_L bytes.
93            z_l[0..28].copy_from_slice(&bytes[..28]);
94            let mut z_l = U256::from_le_slice(&z_l);
95            z_l = z_l.shl(3);
96            Self::from_canonical_bytes(z_l.to_le_bytes())
97        }
98    }
99
100    #[cfg(feature = "taproot")]
101    impl BIP32Derive for k256::Scalar {
102        fn parse_offset(bytes: [u8; 32]) -> CtOption<k256::Scalar> {
103            use ff::PrimeField;
104            Self::from_repr(bytes.into())
105        }
106    }
107
108    #[cfg(feature = "eddsa")]
109    impl ScalarReduce<[u8; 32]> for curve25519_dalek::Scalar {
110        fn reduce_from_bytes(bytes: &[u8; 32]) -> Self {
111            Self::from_bytes_mod_order(*bytes)
112        }
113    }
114
115    #[cfg(feature = "eddsa")]
116    impl ScalarReduce<[u8; 64]> for curve25519_dalek::Scalar {
117        fn reduce_from_bytes(bytes: &[u8; 64]) -> Self {
118            Self::from_bytes_mod_order_wide(bytes)
119        }
120    }
121
122    #[cfg(feature = "taproot")]
123    impl ScalarReduce<[u8; 32]> for k256::Scalar {
124        fn reduce_from_bytes(bytes: &[u8; 32]) -> Self {
125            Reduce::<U256>::reduce(U256::from_be_slice(bytes))
126        }
127    }
128
129    #[cfg(feature = "taproot")]
130    impl ScalarReduce<[u8; 64]> for k256::Scalar {
131        fn reduce_from_bytes(bytes: &[u8; 64]) -> Self {
132            Reduce::<U512>::reduce(U512::from_be_slice(bytes))
133        }
134    }
135}
136
137#[cfg(not(feature = "serde"))]
138pub mod ser {
139    pub trait Serializable {}
140    impl<T> Serializable for T {}
141}
142
143#[cfg(feature = "serde")]
144pub mod ser {
145    pub trait Serializable: serde::Serialize + serde::de::DeserializeOwned {}
146    impl<T: serde::Serialize + serde::de::DeserializeOwned> Serializable for T {}
147}