arnaucube
arnaucube/babyjubjub-rsPublic Self-hosted repository
babyjubjub-rs/src/lib.rs
src/lib.rsRaw
  1extern crate num;
  2extern crate num_bigint;
  3extern crate num_traits;
  4
  5use num_bigint::BigInt;
  6use num_traits::{One, Zero};
  7
  8mod utils;
  9
 10#[derive(Clone, Debug)]
 11pub struct Point {
 12    pub x: BigInt,
 13    pub y: BigInt,
 14}
 15
 16pub struct Babyjubjub {
 17    d: BigInt,
 18    a: BigInt,
 19    q: BigInt,
 20}
 21
 22impl Babyjubjub {
 23    pub fn new() -> Babyjubjub {
 24        let d: BigInt = BigInt::parse_bytes(b"168696", 10).unwrap();
 25        let a: BigInt = BigInt::parse_bytes(b"168700", 10).unwrap();
 26        let q: BigInt = BigInt::parse_bytes(
 27            b"21888242871839275222246405745257275088548364400416034343698204186575808495617",
 28            10,
 29        )
 30        .unwrap();
 31        Babyjubjub { d: d, a: a, q: q }
 32    }
 33
 34    pub fn add(&self, p: &Point, q: &Point) -> Point {
 35        // x = (x1*y2+y1*x2)/(c*(1+d*x1*x2*y1*y2))
 36        // y = (y1*y2-x1*x2)/(c*(1-d*x1*x2*y1*y2))
 37
 38        // x = (x1 * y2 + y1 * x2) / (1 + d * x1 * y1 * y2)
 39        let one: BigInt = One::one();
 40        let x_num: BigInt = &p.x * &q.y + &p.y * &q.x;
 41        let x_den: BigInt = &one + &self.d * &p.x * &q.x * &p.y * &q.y;
 42        let x_den_inv = utils::mod_inverse0(&x_den, &self.q);
 43        // let x_den_inv = utils::mod_inverse1(x_den, self.q.clone());
 44        // let x_den_inv = utils::mod_inverse2(x_den, self.q.clone());
 45        let x: BigInt = utils::modulus(&(&x_num * &x_den_inv), &self.q);
 46
 47        // y = (y1 * y2 - a * x1 * x2) / (1 - d * x1 * x2 * y1 * y2)
 48        let y_num = &p.y * &q.y - &self.a * &p.x * &q.x;
 49        let y_den = utils::modulus(&(&one - &self.d * &p.x * &q.x * &p.y * &q.y), &self.q);
 50        let y_den_inv = utils::mod_inverse0(&y_den, &self.q);
 51        // let y_den_inv = utils::mod_inverse1(y_den, self.q.clone());
 52        // let y_den_inv = utils::mod_inverse2(y_den, self.q.clone());
 53        let y: BigInt = utils::modulus(&(&y_num * &y_den_inv), &self.q);
 54
 55        Point { x: x, y: y }
 56    }
 57}
 58
 59#[cfg(test)]
 60mod tests {
 61    use super::*;
 62    use num_bigint::ToBigInt;
 63
 64    #[test]
 65    fn test_add_same_point() {
 66        let p: Point = Point {
 67            x: BigInt::parse_bytes(
 68                b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
 69                10,
 70            )
 71            .unwrap(),
 72            y: BigInt::parse_bytes(
 73                b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
 74                10,
 75            )
 76            .unwrap(),
 77        };
 78        let q: Point = Point {
 79            x: BigInt::parse_bytes(
 80                b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
 81                10,
 82            )
 83            .unwrap(),
 84            y: BigInt::parse_bytes(
 85                b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
 86                10,
 87            )
 88            .unwrap(),
 89        };
 90        let bbjj = Babyjubjub::new();
 91        let res = bbjj.add(&p, &q);
 92        assert_eq!(
 93            res.x.to_string(),
 94            "6890855772600357754907169075114257697580319025794532037257385534741338397365"
 95        );
 96        assert_eq!(
 97            res.y.to_string(),
 98            "4338620300185947561074059802482547481416142213883829469920100239455078257889"
 99        );
100    }
101    #[test]
102    fn test_add_different_points() {
103        let p: Point = Point {
104            x: BigInt::parse_bytes(
105                b"17777552123799933955779906779655732241715742912184938656739573121738514868268",
106                10,
107            )
108            .unwrap(),
109            y: BigInt::parse_bytes(
110                b"2626589144620713026669568689430873010625803728049924121243784502389097019475",
111                10,
112            )
113            .unwrap(),
114        };
115        let q: Point = Point {
116            x: BigInt::parse_bytes(
117                b"16540640123574156134436876038791482806971768689494387082833631921987005038935",
118                10,
119            )
120            .unwrap(),
121            y: BigInt::parse_bytes(
122                b"20819045374670962167435360035096875258406992893633759881276124905556507972311",
123                10,
124            )
125            .unwrap(),
126        };
127        let bbjj = Babyjubjub::new();
128        let res = bbjj.add(&p, &q);
129        assert_eq!(
130            res.x.to_string(),
131            "7916061937171219682591368294088513039687205273691143098332585753343424131937"
132        );
133        assert_eq!(
134            res.y.to_string(),
135            "14035240266687799601661095864649209771790948434046947201833777492504781204499"
136        );
137    }
138}