Macro secp256kfun::g

source ·
macro_rules! g {
    ($($t:tt)*) => { ... };
}
Expand description

Group operation expression macro.

The g! macro lets you express scalar multiplications and group operations conveniently following standard order of operations. This compiles down to operations from the op module. Apart from being far more readable, the idea is that g! will (or may in the future) compile to more efficient operations than if you were to manually call the functions from op yourself.

Note you can but often don’t need to put a & in front of the terms in the expression.

§Syntax and operations

The expression supports the following operations:

  • <scalar> * <point> multiplies the point by scalar
  • <point> + <point> adds two points
  • <point> - <point> subtracts one point from another
  • <scalar_iter> .* <point_iter> does a dot product between a list of points and scalars. If one list is shorter than the other then the excess points or scalars will be multiplied by 0. See op::point_scalar_dot_product.

The terms of the expression can be any variable followed by simple method calls, attribute access etc. If your term involves more expressions (anything involving specifying types using ::) then you can use {..} to surround arbitrary expressions. You can also use (..) to group arithmetic expressions to override the usual operation order.

§Examples

Simple scalar multiplication by G but will work with any Point

use secp256kfun::{g, Scalar, G};
let x = Scalar::random(&mut rand::thread_rng());
let X = g!(x * G);

A more complicated set of expressions.

let x = Scalar::random(&mut rand::thread_rng());
let y = Scalar::random(&mut rand::thread_rng());
let H = Point::random(&mut rand::thread_rng());
let minus = g!(x * G - y * H);
let plus = g!(x * G + y * H);
assert_eq!(g!(plus + minus), g!(2 * x * G)); // this will do 2 * x first
assert_eq!(g!(42 * (G + H)), g!((42 * G + 42 * H)));

You may access attributes and call methods:

struct DoMul {
    scalar: Scalar,
    point: Point,
}

let mul = DoMul {
    scalar: Scalar::random(&mut rand::thread_rng()),
    point: Point::random(&mut rand::thread_rng()),
};

let result = g!(mul.scalar * mul.point);
assert_eq!(g!(mul.scalar.invert() * result), mul.point);

You can put an arbitrary expressions inside {...}

let random_point = g!({ Scalar::random(&mut rand::thread_rng()) } * G);