Skip to main content

Module 0x2::group_ops

Generic Move and native functions for group operations.

use 0x1::vector;
use 0x2::bcs;

Struct Element

struct Element<T> has copy, drop, store
Fields
bytes: vector<u8>

Constants

const EInvalidInput: u64 = 1;

const EInputTooLong: u64 = 2;

const EInvalidBufferLength: u64 = 3;

const ENotSupported: u64 = 0;

Function bytes

public fun bytes<G>(e: &group_ops::Element<G>): &vector<u8>
Implementation
public fun bytes<G>(e: &Element<G>): &vector<u8> {
    &e.bytes
}

Function equal

public fun equal<G>(e1: &group_ops::Element<G>, e2: &group_ops::Element<G>): bool
Implementation
public fun equal<G>(e1: &Element<G>, e2: &Element<G>): bool {
    &e1.bytes == &e2.bytes
}

Function from_bytes

public(friend) fun from_bytes<G>(type_: u8, bytes: &vector<u8>, is_trusted: bool): group_ops::Element<G>
Implementation
public(package) fun from_bytes<G>(type_: u8, bytes: &vector<u8>, is_trusted: bool): Element<G> {
    assert!(is_trusted || internal_validate(type_, bytes), EInvalidInput);
    Element<G> { bytes: *bytes }
}

Function add

public(friend) fun add<G>(type_: u8, e1: &group_ops::Element<G>, e2: &group_ops::Element<G>): group_ops::Element<G>
Implementation
public(package) fun add<G>(type_: u8, e1: &Element<G>, e2: &Element<G>): Element<G> {
    Element<G> { bytes: internal_add(type_, &e1.bytes, &e2.bytes) }
}

Function sub

public(friend) fun sub<G>(type_: u8, e1: &group_ops::Element<G>, e2: &group_ops::Element<G>): group_ops::Element<G>
Implementation
public(package) fun sub<G>(type_: u8, e1: &Element<G>, e2: &Element<G>): Element<G> {
    Element<G> { bytes: internal_sub(type_, &e1.bytes, &e2.bytes) }
}

Function mul

public(friend) fun mul<S, G>(type_: u8, scalar: &group_ops::Element<S>, e: &group_ops::Element<G>): group_ops::Element<G>
Implementation
public(package) fun mul<S, G>(type_: u8, scalar: &Element<S>, e: &Element<G>): Element<G> {
    Element<G> { bytes: internal_mul(type_, &scalar.bytes, &e.bytes) }
}

Function div

Fails if scalar = 0. Else returns 1/scalar * e.

public(friend) fun div<S, G>(type_: u8, scalar: &group_ops::Element<S>, e: &group_ops::Element<G>): group_ops::Element<G>
Implementation
public(package) fun div<S, G>(type_: u8, scalar: &Element<S>, e: &Element<G>): Element<G> {
    Element<G> { bytes: internal_div(type_, &scalar.bytes, &e.bytes) }
}

Function hash_to

public(friend) fun hash_to<G>(type_: u8, m: &vector<u8>): group_ops::Element<G>
Implementation
public(package) fun hash_to<G>(type_: u8, m: &vector<u8>): Element<G> {
    Element<G> { bytes: internal_hash_to(type_, m) }
}

Function multi_scalar_multiplication

Aborts with EInputTooLong if the vectors are too long.

public(friend) fun multi_scalar_multiplication<S, G>(type_: u8, scalars: &vector<group_ops::Element<S>>, elements: &vector<group_ops::Element<G>>): group_ops::Element<G>
Implementation
public(package) fun multi_scalar_multiplication<S, G>(
    type_: u8,
    scalars: &vector<Element<S>>,
    elements: &vector<Element<G>>,
): Element<G> {
    assert!(scalars.length() > 0, EInvalidInput);
    assert!(scalars.length() == elements.length(), EInvalidInput);

    let mut scalars_bytes: vector<u8> = vector[];
    let mut elements_bytes: vector<u8> = vector[];
    let mut i = 0;
    while (i < scalars.length()) {
        let scalar_vec = scalars[i];
        scalars_bytes.append(scalar_vec.bytes);
        let element_vec = elements[i];
        elements_bytes.append(element_vec.bytes);
        i = i + 1;
    };
    Element<G> { bytes: internal_multi_scalar_mul(type_, &scalars_bytes, &elements_bytes) }
}

Function pairing

public(friend) fun pairing<G1, G2, G3>(type_: u8, e1: &group_ops::Element<G1>, e2: &group_ops::Element<G2>): group_ops::Element<G3>
Implementation
public(package) fun pairing<G1, G2, G3>(
    type_: u8,
    e1: &Element<G1>,
    e2: &Element<G2>,
): Element<G3> {
    Element<G3> { bytes: internal_pairing(type_, &e1.bytes, &e2.bytes) }
}

Function internal_validate

fun internal_validate(type_: u8, bytes: &vector<u8>): bool
Implementation
native fun internal_validate(type_: u8, bytes: &vector<u8>): bool;

Function internal_add

fun internal_add(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>
Implementation
native fun internal_add(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>;

Function internal_sub

fun internal_sub(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>
Implementation
native fun internal_sub(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>;

Function internal_mul

fun internal_mul(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>
Implementation
native fun internal_mul(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>;

Function internal_div

fun internal_div(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>
Implementation
native fun internal_div(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>;

Function internal_hash_to

fun internal_hash_to(type_: u8, m: &vector<u8>): vector<u8>
Implementation
native fun internal_hash_to(type_: u8, m: &vector<u8>): vector<u8>;

Function internal_multi_scalar_mul

fun internal_multi_scalar_mul(type_: u8, scalars: &vector<u8>, elements: &vector<u8>): vector<u8>
Implementation
native fun internal_multi_scalar_mul(
    type_: u8,
    scalars: &vector<u8>,
    elements: &vector<u8>,
): vector<u8>;

Function internal_pairing

fun internal_pairing(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>
Implementation
native fun internal_pairing(type_: u8, e1: &vector<u8>, e2: &vector<u8>): vector<u8>;

Function set_as_prefix

public(friend) fun set_as_prefix(x: u64, big_endian: bool, buffer: &mut vector<u8>)
Implementation
public(package) fun set_as_prefix(x: u64, big_endian: bool, buffer: &mut vector<u8>) {
    let buffer_len = buffer.length();
    assert!(buffer_len > 7, EInvalidBufferLength);
    let x_as_bytes = bcs::to_bytes(&x); // little endian
    let mut i = 0;
    while (i < 8) {
        let position = if (big_endian) {
            buffer_len - i - 1
        } else {
            i
        };
        *(&mut buffer[position]) = x_as_bytes[i];
        i = i + 1;
    };
}