bn254 module

This module exports the classes point, scalar, point2, and scalar2 for representing points and scalars. It also exports the two wrapper classes/namespaces python and mcl that encapsulate pure-Python and shared/dynamic library variants of the above (respectively) and also include low-level operations that correspond more directly to the functions found in the underlying libraries.

  • Under all conditions, the wrapper class python is defined and encapsulates a pure-Python variant of class exported by this module as a whole. It also includes pure-Python variants of low-level operations that correspond to functions found in the underlying libraries.

  • If the mclbn256 package is installed (which includes a bundled copy of the mcl dynamic/shared libray), then the wrapper class mcl is defined. Otherwise, the exported variable mcl is assigned None.

  • If the mclbn256 package is installed, all classes exported by this module correspond to the variants defined in mcl. Otherwise, they correspond to the variants defined in python.

For most users, the classes point, scalar, point2, and scalar2 should be sufficient.

When using the classes within python and/or mcl, users should be aware that objects corresponding to one implementation (e.g., instances of oblivious.bn254.mcl.point) are not compatible with instances corresponding to the other implementation (e.g., the methods of the oblivious.bn254.python.point class). When using the primitive operations that correspond to a specific implementation (e.g., oblivious.bn254.mcl.add), users are responsible for ensuring that inputs have the type and/or representation appropriate for that operation’s internal implementation.

class oblivious.bn254.point(bs: Optional[Union[bytes, bytearray]] = None)[source]

Bases: object

Wrapper class for a bytes-like object that corresponds to a point.

classmethod random() oblivious.bn254.point[source]

Return random point object.

>>> len(point.random())
96
classmethod bytes(bs: bytes) oblivious.bn254.point[source]

Return point object obtained by transforming supplied bytes-like object if it is possible to do so; otherwise, return None.

The bytes-like object need not be the binary representation of a point or its coordinate(s). For a strict deserialization from a bytes-like object, use point.from_bytes.

>>> p = point.bytes(hashlib.sha512('123'.encode()).digest())
>>> p.hex()[:64]
'6d68495eb4d539db4df70fd24d54fae37c9adf7dfd8dc705ccb8de8630e7cf22'
classmethod hash(bs: bytes) oblivious.bn254.point[source]

Return point object by hashing supplied bytes-like object.

>>> point.hash('123'.encode()).hex()[:64]
'825aa78af4c88d6de4abaebabf1a96f668956b92876cfb5d3a44829899cb480f'
classmethod base(s: oblivious.bn254.scalar) oblivious.bn254.point[source]

Return base point multiplied by supplied scalar if the scalar is valid.

>>> point.base(scalar.hash('123'.encode())).canonical().hex()[:64]
'2d66076815cda25556bab4a930244ac284412267e9345aceb98d71530308401a'
classmethod from_bytes(bs: bytes) oblivious.bn254.point[source]

Deserialize the supplied binary representation of an instance and return that instance.

>>> p = point.hash('123'.encode())
>>> bs = p.to_bytes()
>>> point.from_bytes(bs) == p
True
>>> type(bs) is bytes
True
classmethod fromhex(s: str) oblivious.bn254.point[source]

Construct an instance from its hexadecimal UTF-8 string representation.

>>> point.fromhex(
...     'b89ec91191915a72d4ec4434be7b438893975880b21720995c2b2458962c4e0a'
...     'd0efebb5c303e4d1f8461b44ec768c587eca8b0abc01d4cb0d878b076154940d'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
... ).canonical().hex()[:64]
'b89ec91191915a72d4ec4434be7b438893975880b21720995c2b2458962c4e0a'
classmethod from_base64(s: str) oblivious.bn254.point[source]

Construct an instance from its Base64 UTF-8 string representation.

>>> point.from_base64(
...     'hQIYpQRHupyyfPFoEm8rfmKV6i6VUP7vmngQWpxS3AEJD29fKVMW39l2oDLB+Ece'
...     '5PqBuRzCyiRb8xYIelEII47///////8Viv//////ObnN/////y7GovX//3/ypCsh'
... ).canonical().hex()[:64]
'850218a50447ba9cb27cf168126f2b7e6295ea2e9550feef9a78105a9c52dc01'
canonical() oblivious.bn254.point[source]

Normalize the representation of this point into its canonical form and return the result. This takes the z-coordinate, which may not always be equal to 1, and multiplies all coordinates x, y, and z by z’s multiplicative inverse. The resulting canonical representation is unique (i.e., two points are equal if and only if their canonical forms are equal) and in the form (x/z, y/z, 1).

>>> a = point.hash('123'.encode())
>>> p = a + a + a + a
>>> p == p
True
>>> p.to_bytes() == p.to_bytes()
True
>>> p.to_bytes() == p.canonical().to_bytes() and p.__class__ != python.point
False
>>> p.canonical().to_bytes() == p.canonical().to_bytes()
True
>>> p.canonical().to_bytes() == p.canonical().canonical().to_bytes()
True
>>> point.from_bytes(p.to_bytes()) == p
True
>>> point.from_bytes(p.canonical().to_bytes()) == p
True
>>> point.from_bytes(p.to_bytes()) == point.from_bytes(p.canonical().to_bytes())
True
>>> type(p.canonical()) is point
True
__mul__(other: Any) NoReturn[source]

Use of this method is not permitted. A point cannot be a left-hand argument.

>>> point() * scalar()
Traceback (most recent call last):
  ...
TypeError: point must be on right-hand side of multiplication operator
__rmul__(other: Any) NoReturn[source]

This functionality is implemented exclusively in the method scalar.__mul__, as that method pre-empts this method when the second argument has the correct type (i.e., it is a scalar instance). This method is included so that an exception can be raised if an incorrect argument is supplied.

>>> p = point.hash('123'.encode())
>>> 2 * p
Traceback (most recent call last):
  ...
TypeError: point can only be multiplied by a scalar
__add__(other: oblivious.bn254.point) oblivious.bn254.point[source]

Return sum of this point and another point.

>>> p = point.hash('123'.encode())
>>> q = point.hash('456'.encode())
>>> (p + q).canonical().hex()[:64]
'1ea48cab238fece46bd0c9fb562c859e318e17a8fb75517a4750d30ca79b911c'
__sub__(other: oblivious.bn254.point) oblivious.bn254.point[source]

Return the result of subtracting another point from this point.

>>> p = point.hash('123'.encode())
>>> q = point.hash('456'.encode())
>>> (p - q).canonical().hex()[:64]
'a43a5ce1931b1300b62e5d7e1b0c691203bfd85fafd9585dc5e47a7e2acfea22'
__neg__() oblivious.bn254.point[source]

Return the negation (additive inverse) of this point

>>> p = point.hash('123'.encode())
>>> q = point.hash('456'.encode())
>>> (p + q).canonical().hex()[:64]
'1ea48cab238fece46bd0c9fb562c859e318e17a8fb75517a4750d30ca79b911c'
__matmul__(other: oblivious.bn254.point2) oblivious.bn254.scalar2[source]

Return the result of pairing another second-level point with this instance.

This method is only defined for the classes oblivious.bn254.mcl.point and oblivious.bn254.mcl.point2 that are available when the mclbn256 package is installed. Otherwise, oblivious.bn254.point and oblivious.bn254.point2 correspond to the pure-Python implementations of these classes (for which this method is not defined).

>>> p = point.hash('123'.encode())
>>> q = point2.base(scalar.from_int(456))
>>> z = (p @ q).hex()[700:]
>>> z == 'd01f7e038b05acc5519eeda026c4aa111eb12f3483f274c60e34e6ec7571435df707'
True

The pairing function is bilinear.

>>> p = point.random()
>>> q = point2.random()
>>> s = scalar.random()
>>> t = scalar.random()
>>> -((~s) * (s * p)) - p == scalar.from_int(-2) * p
True
>>> (s * (t * p)) @ q == (s * p) @ (t * q)
True

Suppose there are two points: one multiplied by the scalar s and the other multiplied by the scalar t. Their equality can be determined by using a balancing point: g**(~s * t). If the pairing of t * x with g is the same as the pairing with s * y and g**(~s * t), then x equals y.

>>> x = y = p
>>> g = point2.base(scalar.from_int(1))
>>> b = point2.base(~s * t)
>>> (t * x) @ g == (s * y) @ b
True
__len__() int[source]

Return length (in bytes) of the binary representation of this instance.

>>> len(point())
96
__bytes__() bytes[source]

Serialize this instance and return its binary representation.

>>> p = point.hash('123'.encode())
>>> bs = bytes(p)
>>> point.from_bytes(bs) == p
True
>>> type(bs) is bytes
True
>>> len(bs)
96
to_bytes() bytes[source]

Serialize this instance and return its binary representation.

>>> p = point.hash('123'.encode())
>>> bs = p.to_bytes()
>>> point.from_bytes(bs) == p
True
>>> type(bs) is bytes
True
>>> len(bs)
96
hex() str[source]

Return a hexadecimal representation of this instance.

>>> p = point.hash('123'.encode())
>>> p.hex()[:64]
'825aa78af4c88d6de4abaebabf1a96f668956b92876cfb5d3a44829899cb480f'
to_base64() str[source]

Return the Base64 UTF-8 string representation of this instance.

>>> p = point.from_base64(
...     'hQIYpQRHupyyfPFoEm8rfmKV6i6VUP7vmngQWpxS3AEJD29fKVMW39l2oDLB+Ece'
...     '5PqBuRzCyiRb8xYIelEII47///////8Viv//////ObnN/////y7GovX//3/ypCsh'
... )
>>> p.to_base64()[-64:]
'5PqBuRzCyiRb8xYIelEII47///////8Viv//////ObnN/////y7GovX//3/ypCsh'
class oblivious.bn254.scalar(bs: Optional[Union[bytes, bytearray]] = None)[source]

Bases: object

Class for representing a scalar.

classmethod random() oblivious.bn254.scalar[source]

Return random non-zero scalar object.

>>> len(scalar.random())
32
classmethod bytes(bs: bytes) Optional[oblivious.bn254.scalar][source]

Return scalar object obtained by transforming supplied bytes-like object if it is possible to do so; otherwise, return None.

>>> s = scalar()
>>> t = scalar.bytes(bytes(s))
>>> s.hex() == t.hex()
True
classmethod hash(bs: bytes) oblivious.bn254.scalar[source]

Return scalar object by hashing supplied bytes-like object.

>>> scalar.hash('123'.encode()).hex()[:64]
'93d829354cb3592743174133104b5405ba6992b67bb219fbde3e394d70505913'
classmethod from_int(i: int) oblivious.bn254.scalar[source]

Construct an instance from its corresponding integer (i.e., residue) representation.

The integer can be in the range from -16798108731015832284940804142231733909759579603404752749028378864165570215948 to 16798108731015832284940804142231733909759579603404752749028378864165570215948 (or a corresponding one in the range from -8399054365507916142470402071115866954879789801702376374514189432082785107974 to 8399054365507916142470402071115866954879789801702376374514189432082785107974). Any values outside of this range will not be reduced, may be truncated, or may raise a ValueError. Zero-valued scalars are technically allowed, but cannot be used for point-scalar multiplication.

>>> int(scalar.from_int(
...    16798108731015832284940804142231733909759579603404752749028378864165570215948
... ))
-1
>>> int(scalar.from_int(
...    -8399054365507916142470402071115866954879789801702376374514189432082785107974
... ))
-8399054365507916142470402071115866954879789801702376374514189432082785107974
>>> int(scalar.from_int(
...     12345678
... ))
12345678
classmethod from_bytes(bs: bytes) oblivious.bn254.scalar[source]

Deserialize the supplied binary representation of an instance and return that instance.

>>> s = scalar.hash('123'.encode())
>>> bs = s.to_bytes()
>>> scalar.from_bytes(bs) == s
True
>>> type(bs) is bytes
True
classmethod fromhex(s: str) oblivious.bn254.scalar[source]

Construct an instance from its hexadecimal UTF-8 string representation.

>>> scalar.fromhex(
...     '3ab45f5b1c9339f1d25b878cce1c053b5492b4dc1affe689cbe141769f655e1e'
... ).hex()[:64]
'3ab45f5b1c9339f1d25b878cce1c053b5492b4dc1affe689cbe141769f655e1e'
classmethod from_base64(s: str) oblivious.bn254.scalar[source]

Construct an instance from its Base64 UTF-8 string representation.

>>> scalar.from_base64('MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA=').hex()[:64]
'312d0c9130f69153bec9f5d0386a95135eb45eebf130af5f1fed1c6ed15f2500'
__invert__() oblivious.bn254.scalar[source]

Return the inverse of a scalar.

>>> s = scalar()
>>> p = point()
>>> ((~s) * (s * p)) == p
True
__mul__(other: Union[oblivious.bn254.scalar, oblivious.bn254.point, oblivious.bn254.point2]) Optional[Union[oblivious.bn254.scalar, oblivious.bn254.point, oblivious.bn254.point2]][source]

Multiply supplied scalar, point, or second-level point by this instance.

>>> s = scalar.from_base64('MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA=')
>>> (s * s).hex()[:64]
'0497a5b6a7992e7d77b59c07d4457e8bb3cf580603cfd19e05d1f31342141b00'
>>> isinstance(s * s, scalar)
True
>>> p = point.from_base64(
...     'hQIYpQRHupyyfPFoEm8rfmKV6i6VUP7vmngQWpxS3AEJD29fKVMW39l2oDLB+Ece'
...     '5PqBuRzCyiRb8xYIelEII47///////8Viv//////ObnN/////y7GovX//3/ypCsh'
... )
>>> (s * p).canonical().hex()[:64]
'eee31d1780ea41771357da19a81eaddf2e7fa560142067b433764cbf98be9002'
>>> isinstance(s * p, point)
True

If the second argument is a point2 object, this method pre-empts point2.__rmul__.

>>> p = point2.hash('123'.encode())
>>> (s * p).canonical().hex()[:128] == (
...     '451f144e06deecbfe5a1527f2b5cc6f12bbde91c1fdf0d5326ad79ffc53bb106'
...     '6d800275af625de83d72d815335832027cc60c34f22e8c5f89f953740a409702'
... )
True

Any attempt to multiply a value or object of an incompatible type by this instance raises an exception.

>>> s * 2
Traceback (most recent call last):
  ...
TypeError: multiplication by a scalar is defined only for scalars and points
__rmul__(other: Any) NoReturn[source]

A scalar cannot be on the right-hand side of a non-scalar.

>>> point() * scalar()
Traceback (most recent call last):
  ...
TypeError: point must be on right-hand side of multiplication operator
__add__(other: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Add another scalar to this instance.

>>> s = scalar.from_base64('MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA=')
>>> (s + s).hex()[:64]
'625a182261ec23a77c93eba171d42a27bc68bdd6e3615ebf3eda39dca2bf4a00'
>>> isinstance(s + s, scalar)
True
>>> z = scalar2.from_base64(
...     'GNDgZXmP+k7MoKfMbiuNbTJp9+tBNSXlm3MTMrAuqAVLkMic6T5EUlV/U6rl+PEy'
...     'IYWN3i6mpQNz8YWPEShwIQmz2veiF6IKPYcmMvjO1kPTJkmyQaZ2Ab7IVb1D8HcQ'
...     'iN9yK8rMj9F08WrX7xsdXmItk7fP7GOFw1PBN5Ok4Bw3HvVM2DaojhsfHhmNVm07'
...     'vlqiJXNDBfFMrJr5yCE1HIazZRkBBdG35xAR0TYu1q2RM6LCxCiY6evD0WBKYI8Q'
...     'hGHTeyRjtPiPDMtCe17qhxTuiPjDPa9+5KP0XKi8qRGHlWq7TSfeG0nl4Fn5BPu0'
...     'dYBHFasloXMG+g4ZbzBSFTpg36BzynjeSe3qrJxUyrPQE4dQwjwLaN55JKadG6AC'
...     'okrFkmIqRcWcHe1xM3lCkqCWAr1Xo2YB01Q4hG/LNw85wPp6FbNNFKtvle5b9bJr'
...     '1d7x5+0HNQki1EXaB9k2Ii21uqnewVLCsrz8Rs3m/SLnAnGvihZOd+WAjOYCCVof'
... )
>>> (z + z).hex()[700:]
'4a1f476a7553bd83a5dd5179f98d9acddae4c505e25e95df6734c901198d83ad9019'
>>> isinstance(z + z, scalar2)
True
__sub__(other: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Subtract this instance from another scalar.

>>> s = scalar.from_base64('MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA=')
>>> (s - s).hex() == '00' * len(s)
True
>>> isinstance(s - s, scalar)
True
__neg__() oblivious.bn254.scalar[source]

Negate this instance.

>>> s = scalar.from_base64('MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA=')
>>> (-s).hex()
'dcd2f36ecf096e4d52360a2fc7150aeca94ba1148e1c855ae212e3d1b004fe24'
>>> isinstance(-s, scalar)
True
__len__() int[source]

Return length (in bytes) of the binary representation of this instance.

>>> len(scalar())
32
__bytes__() bytes[source]

Serialize this instance and return its binary representation.

>>> s = scalar.hash('123'.encode())
>>> bs = bytes(s)
>>> scalar.from_bytes(bs) == s
True
>>> type(bs) is bytes
True
to_bytes() bytes[source]

Serialize this instance and return its binary representation.

>>> s = scalar.hash('123'.encode())
>>> bs = s.to_bytes()
>>> scalar.from_bytes(bs) == s
True
>>> type(bs) is bytes
True
__int__() bytes[source]

Compute and return the numerical representation of this instance.

>>> s = scalar.from_int(123)
>>> n = int(s)
>>> scalar.from_int(n) == s
True
>>> type(n) is int
True
to_int() bytes[source]

Compute and return the numerical representation of this instance.

>>> s = scalar.from_int(123)
>>> n = s.to_int()
>>> scalar.from_int(n) == s
True
>>> type(n) is int
True
hex() str[source]

Return a hexadecimal representation of this instance.

>>> s = scalar.hash('123'.encode())
>>> s.hex()
'93d829354cb3592743174133104b5405ba6992b67bb219fbde3e394d70505913'
to_base64() str[source]

Return the Base64 UTF-8 string representation of this instance.

>>> s = scalar.from_base64('MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA=')
>>> s.to_base64()
'MS0MkTD2kVO+yfXQOGqVE160XuvxMK9fH+0cbtFfJQA='
class oblivious.bn254.point2(bs: Optional[Union[bytes, bytearray]] = None)[source]

Bases: object

Wrapper class for a bytes-like object that corresponds to a point.

classmethod random() oblivious.bn254.point2[source]

Return random instance.

>>> len(point2.random())
192
classmethod bytes(bs: Union[bytes, bytearray]) oblivious.bn254.point2[source]

Construct an instance that corresponds to the supplied binary representation.

>>> p = point2.bytes(hashlib.sha512('123'.encode()).digest())
>>> p.canonical().hex()[:128] == (
...     '4c595542640a69c4a70bda55c27ef96c133cd1f4a5f83b3371e571960c018e19'
...     'c54aaec2069f8f10a00f12bcbb3511cdb7356201f5277ec5e47da91405be2809'
... )
True
classmethod hash(bs: Union[bytes, bytearray]) oblivious.bn254.point2[source]

Construct an instance by hashing the supplied bytes-like object.

>>> point2.hash('123'.encode()).canonical().hex()[:128] == (
...     '30326199f303fce7a77cff6d2fb0b3de8cd409d1d562f3543f7d064cdc58d309'
...     '7e88038ad76e85e5df26e4a9486a657b0431c8e7e09b0a1abf90fc874c515207'
... )
True
classmethod base(s: oblivious.bn254.scalar) oblivious.bn254.point2[source]

Return base second-level point multiplied by the supplied scalar if the scalar is valid; otherwise, return None.

>>> point2.base(scalar.hash('123'.encode())).canonical().hex()[:128] == (
...     'e7000fb12d206112c73fe1054e9d77b35c77881eba6598b7e035171d90b13e0c'
...     '33c8ad2c92acb446fa958f3001b6c15aaf0f00092534a9d567541f9fadc64e09'
... )
True
classmethod from_bytes(bs: bytes) oblivious.bn254.point2[source]

Deserialize the supplied binary representation of an instance and return that instance.

>>> p = point2.hash('123'.encode())
>>> bs = p.to_bytes()
>>> point2.from_bytes(bs) == p
True
>>> type(bs) is bytes
True
classmethod fromhex(s: str) oblivious.bn254.point2[source]

Construct an instance from its hexadecimal UTF-8 string representation.

>>> p = point2.fromhex(
...     'ab4efa2bcdeb825a67b12a10132ae1addca840ed248f83ae7dd987370dd47a05'
...     '31c10b08ada0e24c0327d85b108e826a55bf3dc3286488327fac75e05e293b20'
...     '01cbf919b53884d02b85aab9b0091eeda114fa65ca5d75620da26c4d164aa509'
...     '2a2d55b6f311bfe52d24adf7b4b0b6ce12ed486a37c474d35a2b373be8a3f71c'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
>>> p.canonical().hex()[:64]
'ab4efa2bcdeb825a67b12a10132ae1addca840ed248f83ae7dd987370dd47a05'
classmethod from_base64(s: str) oblivious.bn254.point2[source]

Construct an instance from its Base64 UTF-8 string representation.

>>> p = point2.from_base64(
...     'xRuTJv/OWkIPMxRoCQIqNYoSixnWfMxeYwSJnjdJwxlp9E9f6oKefvbfYlJeygmK'
...     'YDQniir3r/EYExFuClZ7H5X00GEqz7TcoqDl5EpwLDAvrTW3GNA2lOpHvc1F/eQc'
...     'obJoTn35OzzK7qd/87Y3pOKNQaNENKO19DMzw9Lt+hiO////////FYr//////zm5'
...     'zf////8uxqL1//9/8qQrIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
... )
>>> p.to_base64()[-64:]
'zf////8uxqL1//9/8qQrIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
canonical() oblivious.bn254.point2[source]

Normalize the representation of this point into its canonical form and return the result. This takes the z-coordinate, which may not always be equal to 1, and multiplies all coordinates x, y, and z by z’s multiplicative inverse. The resulting canonical representation is unique (i.e., two second-level points are equal if and only if their canonical forms are equal) and in the form (x1/z1, y1/z1, x2/z2, y2/z2, 1, 0).

>>> a = point2.hash('123'.encode())
>>> q = a + a + a + a
>>> q == q
True
>>> q.to_bytes() == q.to_bytes()
True
>>> q.to_bytes() == q.canonical().to_bytes() and q.__class__ != python.point2
False
>>> q.canonical().to_bytes() == q.canonical().to_bytes()
True
>>> q.canonical().to_bytes() == q.canonical().canonical().to_bytes()
True
>>> point2.from_bytes(q.to_bytes()) == q
True
>>> point2.from_bytes(q.canonical().to_bytes()) == q
True
>>> point2.from_bytes(q.to_bytes()) == point2.from_bytes(bytes(q.canonical()))
True
>>> type(q.canonical()) is point2
True
__mul__(other: Any) NoReturn[source]

Use of this method is not permitted. A point cannot be a left-hand argument.

>>> point2() * scalar()
Traceback (most recent call last):
  ...
TypeError: second-level point must be on right-hand side of multiplication operator
__rmul__(other: Any) NoReturn[source]

This functionality is implemented exclusively in the method scalar.__mul__, as that method pre-empts this method when the second argument has the correct type (i.e., it is a scalar instance). This method is included so that an exception can be raised if an incorrect argument is supplied.

>>> p = point2.hash('123'.encode())
>>> 2 * p
Traceback (most recent call last):
  ...
TypeError: second-level point can only be multiplied by a scalar
__add__(other: oblivious.bn254.point2) Optional[oblivious.bn254.point2][source]

Return sum of this instance and another second-level point.

>>> p = point2.hash('123'.encode())
>>> q = point2.hash('456'.encode())
>>> (p + q).canonical().hex()[:128] == (
...     'cb0fc423c1bac2ac2df47bf5f5548a42b0d0a0da325bc77243d15dc587a7b221'
...     '9808a1649991ddf770f0060333aab4d499580b123f109b5cb180f1f8a75a090e'
... )
True
__sub__(other: oblivious.bn254.point2) Optional[oblivious.bn254.point2][source]

Return the result of subtracting another second-level point from this instance.

>>> p = point2.hash('123'.encode())
>>> q = point2.hash('456'.encode())
>>> (p - q).canonical().hex()[:128] == (
...     'e97a70c4e3a5369ebbb1dcf0cc1135c8c8e04a4ec7cffdf875ac429d66846d0b'
...     '191b090909c40a723027b07ac44435a6ade3813d04b3632a17c92c5c98718902'
... )
True
__neg__() oblivious.bn254.point2[source]

Return the negation (additive inverse) of this instance.

>>> p = point2.hash('123'.encode())
>>> (-p).canonical().hex()[:128] == (
...     '30326199f303fce7a77cff6d2fb0b3de8cd409d1d562f3543f7d064cdc58d309'
...     '7e88038ad76e85e5df26e4a9486a657b0431c8e7e09b0a1abf90fc874c515207'
... )
True
__matmul__(other: oblivious.bn254.point) oblivious.bn254.scalar2[source]

Return the result of pairing another point with this instance.

Input-swapped alias of point.__matmul__.

__len__() int[source]

Return length (in bytes) of the binary representation of this instance.

>>> len(point2())
192
__bytes__() bytes[source]

Serialize this instance and return its binary representation.

>>> len(bytes(point2()))
192
to_bytes() bytes[source]

Serialize this instance and return its binary representation.

>>> p = point2.hash('123'.encode())
>>> bs = p.to_bytes()
>>> point2.from_bytes(bs) == p
True
>>> type(bs) is bytes
True
hex() str[source]

Return a hexadecimal representation of this instance.

>>> p = point2.hash('123'.encode())
>>> p.canonical().hex() == (
...     '30326199f303fce7a77cff6d2fb0b3de8cd409d1d562f3543f7d064cdc58d309'
...     '7e88038ad76e85e5df26e4a9486a657b0431c8e7e09b0a1abf90fc874c515207'
...     '2c6a88bb448065eb748df632b1d872e02f54b6f56fdb84a7b1cb388fe551fb08'
...     '04464efa186bd4b1371e53d6f31f0e2f50ff553b6264a43331b42c976a0c541f'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
to_base64() str[source]

Return the Base64 UTF-8 string representation of this instance.

>>> p = point2.from_base64(
...     'zn07zy59PMhe396h9AQ+FY3LqfzmaRmbVmfwKaQqTxStH2ZPqGwBjv99STlWrenq'
...     'Mkfc3PCxRgM1xVaJGN+WExXhuDn4V40nkdpxtU85VFgE4aj0CMUoD99bqTEqBSYD'
...     '50haF1C7mDxMRxmMXZinYDEMynRY69C1vTQ5IgcCdh+O////////FYr//////zm5'
...     'zf////8uxqL1//9/8qQrIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
... )
>>> p.to_base64()[-64:]
'zf////8uxqL1//9/8qQrIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
class oblivious.bn254.scalar2(bs: Optional[Union[bytes, bytearray]] = None)[source]

Bases: object

Class for representing second-level scalars.

classmethod random() oblivious.bn254.scalar2[source]

Return random non-zero second-level scalar.

>>> isinstance(scalar2.random(), scalar2)
True
>>> len(scalar2.random())
384
classmethod bytes(bs: bytes) Optional[oblivious.bn254.scalar2][source]

Return second-level scalar object obtained by transforming the supplied bytes-like object if it is possible to do so; otherwise, return None.

>>> s = scalar2()
>>> t = scalar2.bytes(bytes(s))
>>> s.hex() == t.hex()
True
classmethod hash(bs: Union[bytes, bytearray]) oblivious.bn254.scalar2[source]

Return an instance derived by hashing the supplied bytes-like object.

>>> s = python.scalar2.hash(bytes([123]))
>>> s.hex()[700:]
'e91ed56ea67d29047d588ffaf78f9ed317ff13e7f63e53276ff32988c49184e17b22'
>>> s0 = python.scalar2.hash(secrets.token_bytes(64))
>>> s1 = python.scalar2.hash(secrets.token_bytes(64))
>>> python.sse(python.smu2(python.smu2(s0, python.inv2(s0)), s1)) == python.sse(s1)
True
classmethod from_bytes(bs: bytes) oblivious.bn254.scalar2[source]

Deserialize the supplied binary representation of an instance and return that instance.

>>> s = scalar2.hash('123'.encode())
>>> bs = s.to_bytes()
>>> scalar2.from_bytes(bs) == s
True
>>> type(bs) is bytes
True
classmethod fromhex(s: str) oblivious.bn254.scalar2[source]

Construct an instance from its hexadecimal UTF-8 string representation.

>>> s_hex = (
...     '18d0e065798ffa4ecca0a7cc6e2b8d6d3269f7eb413525e59b731332b02ea805'
...     '4b90c89ce93e4452557f53aae5f8f13221858dde2ea6a50373f1858f11287021'
...     '09b3daf7a217a20a3d872632f8ced643d32649b241a67601bec855bd43f07710'
...     '88df722bcacc8fd174f16ad7ef1b1d5e622d93b7cfec6385c353c13793a4e01c'
...     '371ef54cd836a88e1b1f1e198d566d3bbe5aa225734305f14cac9af9c821351c'
...     '86b365190105d1b7e71011d1362ed6ad9133a2c2c42898e9ebc3d1604a608f10'
...     '8461d37b2463b4f88f0ccb427b5eea8714ee88f8c33daf7ee4a3f45ca8bca911'
...     '87956abb4d27de1b49e5e059f904fbb475804715ab25a17306fa0e196f305215'
...     '3a60dfa073ca78de49edeaac9c54cab3d0138750c23c0b68de7924a69d1ba002'
...     'a24ac592622a45c59c1ded7133794292a09602bd57a36601d35438846fcb370f'
...     '39c0fa7a15b34d14ab6f95ee5bf5b26bd5def1e7ed07350922d445da07d93622'
...     '2db5baa9dec152c2b2bcfc46cde6fd22e70271af8a164e77e5808ce602095a1f'
... )
>>> s = scalar2.fromhex(s_hex)
>>> s.hex() == s_hex
True
classmethod from_base64(s: str) oblivious.bn254.scalar2[source]

Construct an instance from its Base64 UTF-8 string representation.

>>> b64s = (
...     'GNDgZXmP+k7MoKfMbiuNbTJp9+tBNSXlm3MTMrAuqAVLkMic6T5EUlV/U6rl+PEy'
...     'IYWN3i6mpQNz8YWPEShwIQmz2veiF6IKPYcmMvjO1kPTJkmyQaZ2Ab7IVb1D8HcQ'
...     'iN9yK8rMj9F08WrX7xsdXmItk7fP7GOFw1PBN5Ok4Bw3HvVM2DaojhsfHhmNVm07'
...     'vlqiJXNDBfFMrJr5yCE1HIazZRkBBdG35xAR0TYu1q2RM6LCxCiY6evD0WBKYI8Q'
...     'hGHTeyRjtPiPDMtCe17qhxTuiPjDPa9+5KP0XKi8qRGHlWq7TSfeG0nl4Fn5BPu0'
...     'dYBHFasloXMG+g4ZbzBSFTpg36BzynjeSe3qrJxUyrPQE4dQwjwLaN55JKadG6AC'
...     'okrFkmIqRcWcHe1xM3lCkqCWAr1Xo2YB01Q4hG/LNw85wPp6FbNNFKtvle5b9bJr'
...     '1d7x5+0HNQki1EXaB9k2Ii21uqnewVLCsrz8Rs3m/SLnAnGvihZOd+WAjOYCCVof'
... )
>>> s = scalar2.from_base64(b64s)
>>> s.to_base64() == b64s
True
__invert__() oblivious.bn254.scalar2[source]

Return the inverse of this instance.

>>> s = scalar2.hash('123'.encode())
>>> ~(~s) == s
True
>>> ~s == s
False
>>> bytes(~s).hex()[700:] == (
...     'ff13804852ea3ad35e8316d90a6d5dde854517e74cfc27ba676f429eb4fd52cd9b0c'
... )
True
__mul__(other: oblivious.bn254.scalar2) oblivious.bn254.scalar2[source]

Multiply this instance by another second-level scalar.

>>> s = scalar2.from_base64(
...     'GNDgZXmP+k7MoKfMbiuNbTJp9+tBNSXlm3MTMrAuqAVLkMic6T5EUlV/U6rl+PEy'
...     'IYWN3i6mpQNz8YWPEShwIQmz2veiF6IKPYcmMvjO1kPTJkmyQaZ2Ab7IVb1D8HcQ'
...     'iN9yK8rMj9F08WrX7xsdXmItk7fP7GOFw1PBN5Ok4Bw3HvVM2DaojhsfHhmNVm07'
...     'vlqiJXNDBfFMrJr5yCE1HIazZRkBBdG35xAR0TYu1q2RM6LCxCiY6evD0WBKYI8Q'
...     'hGHTeyRjtPiPDMtCe17qhxTuiPjDPa9+5KP0XKi8qRGHlWq7TSfeG0nl4Fn5BPu0'
...     'dYBHFasloXMG+g4ZbzBSFTpg36BzynjeSe3qrJxUyrPQE4dQwjwLaN55JKadG6AC'
...     'okrFkmIqRcWcHe1xM3lCkqCWAr1Xo2YB01Q4hG/LNw85wPp6FbNNFKtvle5b9bJr'
...     '1d7x5+0HNQki1EXaB9k2Ii21uqnewVLCsrz8Rs3m/SLnAnGvihZOd+WAjOYCCVof'
... )
>>> bytes(s * s).hex()[700:]
'6f11685b89b03431dac6dc9d129c6a31cc5e3036f7f781d7460ab9f532a06845bd15'
>>> scalar2() * point()
Traceback (most recent call last):
  ...
TypeError: second-level scalar can only be multiplied by another second-level scalar
__rmul__(other: Any) NoReturn[source]

A second-level scalar cannot be on the right-hand side of a non-scalar.

>>> 2 * scalar2()
Traceback (most recent call last):
  ...
TypeError: second-level scalar must be on left-hand side of multiplication operator
__add__(other: oblivious.bn254.scalar2) oblivious.bn254.scalar2[source]

Add another second-level scalar to this instance.

>>> z = scalar2.from_base64(
...     'GNDgZXmP+k7MoKfMbiuNbTJp9+tBNSXlm3MTMrAuqAVLkMic6T5EUlV/U6rl+PEy'
...     'IYWN3i6mpQNz8YWPEShwIQmz2veiF6IKPYcmMvjO1kPTJkmyQaZ2Ab7IVb1D8HcQ'
...     'iN9yK8rMj9F08WrX7xsdXmItk7fP7GOFw1PBN5Ok4Bw3HvVM2DaojhsfHhmNVm07'
...     'vlqiJXNDBfFMrJr5yCE1HIazZRkBBdG35xAR0TYu1q2RM6LCxCiY6evD0WBKYI8Q'
...     'hGHTeyRjtPiPDMtCe17qhxTuiPjDPa9+5KP0XKi8qRGHlWq7TSfeG0nl4Fn5BPu0'
...     'dYBHFasloXMG+g4ZbzBSFTpg36BzynjeSe3qrJxUyrPQE4dQwjwLaN55JKadG6AC'
...     'okrFkmIqRcWcHe1xM3lCkqCWAr1Xo2YB01Q4hG/LNw85wPp6FbNNFKtvle5b9bJr'
...     '1d7x5+0HNQki1EXaB9k2Ii21uqnewVLCsrz8Rs3m/SLnAnGvihZOd+WAjOYCCVof'
... )
>>> (z + z).hex()[700:]
'4a1f476a7553bd83a5dd5179f98d9acddae4c505e25e95df6734c901198d83ad9019'
>>> isinstance(z + z, scalar2)
True
__len__() int[source]

Return length (in bytes) of the binary representation of this instance.

>>> len(scalar2.random())
384
__bytes__() bytes[source]

Serialize this instance and return its binary representation.

>>> s = scalar2.hash('123'.encode())
>>> bs = bytes(s)
>>> scalar2.from_bytes(bs) == s
True
>>> type(bs) is bytes
True
>>> len(bs)
384
to_bytes() bytes[source]

Serialize this instance and return its binary representation.

>>> s = scalar2.hash('123'.encode())
>>> bs = s.to_bytes()
>>> scalar2.from_bytes(bs) == s
True
>>> type(bs) is bytes
True
>>> len(bs)
384
hex() str[source]

Return a hexadecimal representation of this instance.

>>> s = scalar2.from_base64(
...     'GNDgZXmP+k7MoKfMbiuNbTJp9+tBNSXlm3MTMrAuqAVLkMic6T5EUlV/U6rl+PEy'
...     'IYWN3i6mpQNz8YWPEShwIQmz2veiF6IKPYcmMvjO1kPTJkmyQaZ2Ab7IVb1D8HcQ'
...     'iN9yK8rMj9F08WrX7xsdXmItk7fP7GOFw1PBN5Ok4Bw3HvVM2DaojhsfHhmNVm07'
...     'vlqiJXNDBfFMrJr5yCE1HIazZRkBBdG35xAR0TYu1q2RM6LCxCiY6evD0WBKYI8Q'
...     'hGHTeyRjtPiPDMtCe17qhxTuiPjDPa9+5KP0XKi8qRGHlWq7TSfeG0nl4Fn5BPu0'
...     'dYBHFasloXMG+g4ZbzBSFTpg36BzynjeSe3qrJxUyrPQE4dQwjwLaN55JKadG6AC'
...     'okrFkmIqRcWcHe1xM3lCkqCWAr1Xo2YB01Q4hG/LNw85wPp6FbNNFKtvle5b9bJr'
...     '1d7x5+0HNQki1EXaB9k2Ii21uqnewVLCsrz8Rs3m/SLnAnGvihZOd+WAjOYCCVof'
... )
>>> s.hex() == (
...     '18d0e065798ffa4ecca0a7cc6e2b8d6d3269f7eb413525e59b731332b02ea805'
...     '4b90c89ce93e4452557f53aae5f8f13221858dde2ea6a50373f1858f11287021'
...     '09b3daf7a217a20a3d872632f8ced643d32649b241a67601bec855bd43f07710'
...     '88df722bcacc8fd174f16ad7ef1b1d5e622d93b7cfec6385c353c13793a4e01c'
...     '371ef54cd836a88e1b1f1e198d566d3bbe5aa225734305f14cac9af9c821351c'
...     '86b365190105d1b7e71011d1362ed6ad9133a2c2c42898e9ebc3d1604a608f10'
...     '8461d37b2463b4f88f0ccb427b5eea8714ee88f8c33daf7ee4a3f45ca8bca911'
...     '87956abb4d27de1b49e5e059f904fbb475804715ab25a17306fa0e196f305215'
...     '3a60dfa073ca78de49edeaac9c54cab3d0138750c23c0b68de7924a69d1ba002'
...     'a24ac592622a45c59c1ded7133794292a09602bd57a36601d35438846fcb370f'
...     '39c0fa7a15b34d14ab6f95ee5bf5b26bd5def1e7ed07350922d445da07d93622'
...     '2db5baa9dec152c2b2bcfc46cde6fd22e70271af8a164e77e5808ce602095a1f'
... )
True
to_base64() str[source]

Return the Base64 UTF-8 string representation of this instance.

>>> b64s = (
...     'GNDgZXmP+k7MoKfMbiuNbTJp9+tBNSXlm3MTMrAuqAVLkMic6T5EUlV/U6rl+PEy'
...     'IYWN3i6mpQNz8YWPEShwIQmz2veiF6IKPYcmMvjO1kPTJkmyQaZ2Ab7IVb1D8HcQ'
...     'iN9yK8rMj9F08WrX7xsdXmItk7fP7GOFw1PBN5Ok4Bw3HvVM2DaojhsfHhmNVm07'
...     'vlqiJXNDBfFMrJr5yCE1HIazZRkBBdG35xAR0TYu1q2RM6LCxCiY6evD0WBKYI8Q'
...     'hGHTeyRjtPiPDMtCe17qhxTuiPjDPa9+5KP0XKi8qRGHlWq7TSfeG0nl4Fn5BPu0'
...     'dYBHFasloXMG+g4ZbzBSFTpg36BzynjeSe3qrJxUyrPQE4dQwjwLaN55JKadG6AC'
...     'okrFkmIqRcWcHe1xM3lCkqCWAr1Xo2YB01Q4hG/LNw85wPp6FbNNFKtvle5b9bJr'
...     '1d7x5+0HNQki1EXaB9k2Ii21uqnewVLCsrz8Rs3m/SLnAnGvihZOd+WAjOYCCVof'
... )
>>> s = scalar2.from_base64(b64s)
>>> s.to_base64() == b64s
True
class oblivious.bn254.python[source]

Bases: object

Wrapper class for pure-Python implementations of primitive operations.

This class encapsulates pure-Python variants of all classes exported by this module and of all the underlying low-level operations: python.pnt, python.bas, python.can, python.ser, python.des, python.mul, python.add, python.sub, python.neg, python.par, python.rnd, python.scl, python.sse, python.sde, python.inv, python.smu, python.sad, python.ssu, python.sne, python.pnt2, python.bas2, python.can2, python.ser2, python.des2, python.mul2, python.add2, python.sub2, python.neg2, python.rnd2, python.scl2, python.sse2, python.sde2, python.inv2, python.smu2, python.sad2, python.point, python.scalar, python.point2, and python.scalar2. For example, you can perform multiplication of scalars using the pure-Python scalar multiplication implementation.

>>> s = python.scl()
>>> t = python.scl()
>>> python.smu(s, t) == python.smu(t, s)
True

Pure-Python variants of the python.point and python.scalar classes always employ pure Python implementations of operations when their methods are invoked.

>>> p = python.scalar()
>>> q = python.scalar()
>>> p * q == q * p
True
static pnt(h: Optional[bytes] = None) oblivious.bn254.point[source]

Construct a point from its 64-byte vector representation (normally obtained via hashing).

>>> p = python.pnt(hashlib.sha512('123'.encode()).digest())
>>> p.hex()[:64]
'6d68495eb4d539db4df70fd24d54fae37c9adf7dfd8dc705ccb8de8630e7cf22'
static bas(s: oblivious.bn254.scalar) oblivious.bn254.point[source]

Return the base point multiplied by the supplied scalar.

>>> bytes(python.bas(python.scalar.hash('123'.encode()))).hex()[:64]
'2d66076815cda25556bab4a930244ac284412267e9345aceb98d71530308401a'
static can(p: oblivious.bn254.point) oblivious.bn254.point[source]

Normalize the representation of a point into its canonical form and return the result.

>>> a = python.point.hash('123'.encode())
>>> p = python.add(a, a)
>>> p_can = python.can(python.add(a, a))

It may be the case that ser(p_can) != ser(p), depending on the implementation. It is the responsibility of the user to ensure that only canonical forms are serialized if those serialized forms must be compared.

>>> mclbn256 = p.__class__ != python.point
>>> (python.ser(p_can) != python.ser(p)) or not mclbn256
True

Normalization is idempotent.

>>> python.can(p) == python.can(p_can)
True
static ser(p: oblivious.bn254.point) bytes[source]

Return the binary representation of a point.

>>> q = python.point2.hash('123'.encode())
>>> python.des(python.ser(q)) == q
True
static des(bs: bytes) oblivious.bn254.point[source]

Construct a point corresponding to the supplied binary representation.

>>> p = python.point.hash('123'.encode())
>>> python.ser_p = bytes.fromhex(
...     '825aa78af4c88d6de4abaebabf1a96f668956b92876cfb5d3a44829899cb480f'
...     'b03c992ec97868be765b98048118a96f42bdc466a963c243c223b95196304209'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
... )
>>> python.des(python.ser_p) == p
True
>>> python.ser(python.des(python.ser_p)) == python.ser_p
True
static mul(s: oblivious.bn254.scalar, p: oblivious.bn254.point) oblivious.bn254.point[source]

Multiply a point by a scalar and return the result.

>>> p = python.pnt(hashlib.sha512('123'.encode()).digest())
>>> s = python.scl(bytes.fromhex(
...     '35c141f1c2c43543de9d188805a210abca3cd39a1e986304991ceded42b11709'
... ))
>>> python.mul(s, p).hex()[:64]
'68b5dd61adaa83f1511efe7b4749481cc9f86e11bf82d82960b6c56373de0d24'
static add(p: oblivious.bn254.point, q: oblivious.bn254.point) oblivious.bn254.point[source]

Return the sum of the supplied points.

>>> p = python.point.hash('123'.encode())
>>> q = python.point.hash('456'.encode())
>>> python.point.to_bytes(python.add(p, q)).hex()[:64]
'1ea48cab238fece46bd0c9fb562c859e318e17a8fb75517a4750d30ca79b911c'
>>> python.add(python.sub(p, q), q) == p
True
static sub(p: oblivious.bn254.point, q: oblivious.bn254.point) oblivious.bn254.point[source]

Return the result of subtracting the right-hand point from the left-hand point.

>>> p = python.point.hash('123'.encode())
>>> q = python.point.hash('456'.encode())
>>> python.sub(p, q).hex()[:64]
'a43a5ce1931b1300b62e5d7e1b0c691203bfd85fafd9585dc5e47a7e2acfea22'
>>> python.sub(python.add(p, q), q) == p
True
static neg(p: oblivious.bn254.point) oblivious.bn254.point[source]

Return the additive inverse of a point.

>>> p = python.point.hash('123'.encode())
>>> python.point.to_bytes(python.neg(p)).hex()[:64]
'825aa78af4c88d6de4abaebabf1a96f668956b92876cfb5d3a44829899cb480f'
static rnd() oblivious.bn254.scalar[source]

Return random non-zero scalar.

>>> isinstance(python.rnd(), python.scalar)
True
classmethod scl(s: Optional[Union[bytes, bytearray]] = None) Optional[oblivious.bn254.scalar][source]

Construct a scalar if the supplied bytes-like object represents a valid scalar; otherwise, return None. If no byte vector is supplied, return a random scalar.

>>> s = python.scl()
>>> t = python.scl(s)
>>> s == t
True
>>> python.scl(bytes([255] * 32)) is None
True
static sse(s: oblivious.bn254.scalar) bytes[source]

Return the binary representation of a scalar.

>>> s = python.scalar.hash('123'.encode())
>>> python.sde(python.sse(s)) == s
True
static sde(bs: bytes) oblivious.bn254.scalar[source]

Construct a scalar from its binary representation.

>>> s = python.scalar.hash('123'.encode())
>>> bs = bytes.fromhex(
...     '93d829354cb3592743174133104b5405ba6992b67bb219fbde3e394d70505913'
... )
>>> python.sde(bs) == s
True
>>> python.sse(python.sde(bs)) == bs
True
static inv(s: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Return the inverse of a scalar (modulo r = 16798108731015832284940804142231733909759579603404752749028378864165570215949 in the prime field F*_r).

>>> s = python.scl()
>>> p = python.pnt()
>>> python.mul(python.inv(s), python.mul(s, p)) == p
True
static smu(s: oblivious.bn254.scalar, t: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Return the product of two scalars.

>>> s = python.scl()
>>> t = python.scl()
>>> python.smu(s, t) == python.smu(t, s)
True
static sad(s: oblivious.bn254.scalar, t: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Return the sum of two scalars.

>>> s = python.scl()  # Could be `python.scl()`.
>>> t = python.scl()
>>> python.sad(s, t) == python.sad(t, s)
True
static ssu(s: oblivious.bn254.scalar, t: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Return the result of subtracting the right-hand scalar from the left-hand scalar.

>>> s = python.scl()
>>> t = python.scl()
>>> python.ssu(s, t) == python.sad(s, python.sne(t))
True
>>> python.ssu(s, t) == python.sne(python.ssu(t, s))
True
static sne(s: oblivious.bn254.scalar) oblivious.bn254.scalar[source]

Return the additive inverse of a scalar.

>>> s = python.scl()
>>> t = python.scl()
>>> python.sne(python.sne(s)) == s
True
static pnt2(h: Optional[bytes] = None) oblivious.bn254.point2[source]

Construct a second-level point if the supplied bytes-like object represents a valid second-level point; otherwise, return None. If no byte vector is supplied, return a random second-level point.

>>> p = python.pnt2(hashlib.sha512('123'.encode()).digest())
>>> python.point2.to_bytes(p).hex()[:128] == (
...     '4c595542640a69c4a70bda55c27ef96c133cd1f4a5f83b3371e571960c018e19'
...     'c54aaec2069f8f10a00f12bcbb3511cdb7356201f5277ec5e47da91405be2809'
... )
True
static bas2(s: oblivious.bn254.scalar) oblivious.bn254.point2[source]

Return the base second-level point multiplied by the supplied scalar.

>>> bytes(python.bas2(python.scalar.hash('123'.encode()))).hex()[:64]
'e7000fb12d206112c73fe1054e9d77b35c77881eba6598b7e035171d90b13e0c'
static can2(p: oblivious.bn254.point2) oblivious.bn254.point2[source]

Normalize the representation of a second-level point into its canonical form and return the result.

>>> p = python.bas2(scalar.from_int(1))
>>> python.ser(python.can2(p)).hex()[:64]
'669e6563afaa45af7cbc013d23f092bb3763d4dc41b97aef555bdf61de713f17'
static ser2(p: oblivious.bn254.point2) bytes[source]

Return the binary representation of a second-level point.

>>> p = python.point2.hash('123'.encode())
>>> python.des2(python.ser2(p)) == p
True

It is the responsibility of the user to ensure that only canonical representations of points are serialized.

static des2(bs: bytes) oblivious.bn254.point2[source]

Return the second-level point corresponding to the supplied binary representation thereof.

>>> p = python.point2.hash('123'.encode())
>>> ser_p = bytes.fromhex(
...     '30326199f303fce7a77cff6d2fb0b3de8cd409d1d562f3543f7d064cdc58d309'
...     '7e88038ad76e85e5df26e4a9486a657b0431c8e7e09b0a1abf90fc874c515207'
...     '2c6a88bb448065eb748df632b1d872e02f54b6f56fdb84a7b1cb388fe551fb08'
...     '04464efa186bd4b1371e53d6f31f0e2f50ff553b6264a43331b42c976a0c541f'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
>>> python.des2(ser_p) == p
True
>>> python.ser(python.des2(ser_p)) == ser_p
True
static mul2(s: oblivious.bn254.scalar, p: oblivious.bn254.point2) oblivious.bn254.point2[source]

Multiply a second-level point by a scalar.

>>> p = python.point2.hash('123'.encode())
>>> s = python.scl(bytes.fromhex(
...     '35c141f1c2c43543de9d188805a210abca3cd39a1e986304991ceded42b11709'
... ))
>>> python.point2.to_bytes(python.mul2(s, p)).hex() == (
...     '5f6f2ace8566ca47354fbe244ae3e6a854c37011fb6d6ac56571c94169e4ab18'
...     '650bea4cfed5c9603e5949fe3d7509b17e20db4ff1f05129aad0d0a3bffb0008'
...     '3043c5a14b986882836b1c929952ea3881d04ca44d487d1ab2d4c0b171b87d14'
...     '5dca6dabb4f0ea7be5c95a861ed319d146b15d70542d3952af995a8bb35b8314'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static add2(p: oblivious.bn254.point2, q: oblivious.bn254.point2) oblivious.bn254.point2[source]

Return sum of the supplied second-level points.

>>> p = python.point2.hash('123'.encode())
>>> q = python.point2.hash('456'.encode())
>>> python.point2.to_bytes(python.add2(p, q)).hex() == (
...     'cb0fc423c1bac2ac2df47bf5f5548a42b0d0a0da325bc77243d15dc587a7b221'
...     '9808a1649991ddf770f0060333aab4d499580b123f109b5cb180f1f8a75a090e'
...     '83dd34d9ecdd6fd639230f7f0cf44b218fae4d879111de6c6c037e6ffdcdc823'
...     'f5a48318143873ca90ad512a2ea1854200eea5537cd0ac93691d5b94ff36b212'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static sub2(p: oblivious.bn254.point2, q: oblivious.bn254.point2) oblivious.bn254.point2[source]

Return the result of subtracting right-hand second-level point from the left-hand second-level point.

>>> p = python.point2.hash('123'.encode())
>>> q = python.point2.hash('456'.encode())
>>> python.point2.to_bytes(python.sub2(p, q)).hex() == (
...     'e97a70c4e3a5369ebbb1dcf0cc1135c8c8e04a4ec7cffdf875ac429d66846d0b'
...     '191b090909c40a723027b07ac44435a6ade3813d04b3632a17c92c5c98718902'
...     '407c58ed13cc0c0aaa43d0eafd44080080c8199401fe4f8ed7dd0eb5fba86817'
...     '141f74341ce3c4884f86a97f51f7c0b208fe52be336b7651252fa9881c93d203'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static neg2(p: oblivious.bn254.point2) oblivious.bn254.point2[source]

Return the negation of a second-level point.

>>> p = python.point2.hash('123'.encode())
>>> python.point2.to_bytes(python.neg2(p)).hex() == (
...     '30326199f303fce7a77cff6d2fb0b3de8cd409d1d562f3543f7d064cdc58d309'
...     '7e88038ad76e85e5df26e4a9486a657b0431c8e7e09b0a1abf90fc874c515207'
...     'e7957744bb7f9abb9e7209cd4e27ae80d8ab490a1072af125034c7b09c12281c'
...     '0fbab105e7942bf5dbe1ac290ce01232b800aac41de98f86d04bd3a81758cf05'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static rnd2() oblivious.bn254.scalar2[source]

Return random non-zero second-level scalar.

>>> isinstance(python.rnd2(), python.scalar2)
True
static scl2(s: Optional[Union[bytes, bytearray]] = None) Optional[oblivious.bn254.scalar2][source]

Construct a second-level scalar if the supplied bytes-like object represents a valid second-level scalar; otherwise, return None. If no byte vector is supplied, return a random second-level scalar.

>>> bs = bytes.fromhex(
...     '18d0e065798ffa4ecca0a7cc6e2b8d6d3269f7eb413525e59b731332b02ea805'
...     '4b90c89ce93e4452557f53aae5f8f13221858dde2ea6a50373f1858f11287021'
...     '09b3daf7a217a20a3d872632f8ced643d32649b241a67601bec855bd43f07710'
...     '88df722bcacc8fd174f16ad7ef1b1d5e622d93b7cfec6385c353c13793a4e01c'
...     '371ef54cd836a88e1b1f1e198d566d3bbe5aa225734305f14cac9af9c821351c'
...     '86b365190105d1b7e71011d1362ed6ad9133a2c2c42898e9ebc3d1604a608f10'
...     '8461d37b2463b4f88f0ccb427b5eea8714ee88f8c33daf7ee4a3f45ca8bca911'
...     '87956abb4d27de1b49e5e059f904fbb475804715ab25a17306fa0e196f305215'
...     '3a60dfa073ca78de49edeaac9c54cab3d0138750c23c0b68de7924a69d1ba002'
...     'a24ac592622a45c59c1ded7133794292a09602bd57a36601d35438846fcb370f'
...     '39c0fa7a15b34d14ab6f95ee5bf5b26bd5def1e7ed07350922d445da07d93622'
...     '2db5baa9dec152c2b2bcfc46cde6fd22e70271af8a164e77e5808ce602095a1f'
... )
>>> python.scalar2.to_bytes(python.scl2(bs)).hex()[700:]
'36222db5baa9dec152c2b2bcfc46cde6fd22e70271af8a164e77e5808ce602095a1f'
static sse2(s: oblivious.bn254.scalar2) bytes[source]

Return the binary representation of a second-level scalar.

>>> s = python.scalar2.hash('123'.encode())
>>> python.sde2(python.sse2(s)) == s
True
static sde2(bs: bytes) oblivious.bn254.scalar2[source]

Construct a second-level scalar from its binary representation.

>>> s = python.scalar2.hash('123'.encode())
>>> bs = bytes.fromhex(
...     '36980a8359d40e106075488e80cf1479f2e6ba95d6a99a67832d21b7b94d8c1d'
...     '5eb4d655f23e1d5d499d51d1c552b5e7df6943091427cd080f582e120613a021'
...     '85898ef7d016e47a74a8df62316cc4ad975cb64bb63867ed9b5221f77bb9a121'
...     '7bd89cd213eee0c3fdf2e0e13ef9e30383ea5607c8d13fc10e04448a6c964a00'
...     '04a098a55beab09732220966319333608b2187ee2196eb5b4253bc2b1aea5303'
...     '654260dd687a2eb176a494258ff7ef753f93105a6f0e9f46c926afdbe31ff124'
...     '6bdd87c32537abcdb46ad542792edd74a229c9ba61abcd993f074237a91f5215'
...     '8f6b07886895733edde15cb22129459162d89d3662826b74e4fcbe4e9e8c2420'
...     'bd53586a09f91ff8f67f92cba72c5b64a9c3965c01e93710200ab4e084955316'
...     'fb18950835b79fb4c2930efcc5fcaa9d82ee0faff036b80657daee233a445901'
...     '7df3e57cb535ed26162b3ee0f8961131a93fe3198dc5393d277ed8bac5532411'
...     '93b7ad15c52ca123fd26f592a2219b1bf118b3035893cc4abf614b422f978718'
... )
>>> python.sde2(bs) == s
True
>>> python.sse(python.sde2(bs)) == bs
True
static inv2(s: oblivious.bn254.scalar2) oblivious.bn254.scalar2[source]

Return the inverse of a second-level scalar.

>>> s = python.scl2()
>>> python.smu2(s, python.smu2(s, python.inv2(s))) == s
True
>>> python.smu2(python.smu2(s, s), python.inv2(s)) == s
True
static smu2(s: oblivious.bn254.scalar2, t: oblivious.bn254.scalar2) oblivious.bn254.scalar2[source]

Return second-level scalar multiplied by another scalar.

>>> s = python.scalar2.random()
>>> t = python.scalar2.random()
>>> python.smu2(s, t) == python.smu2(t, s)
True
static sad2(s: oblivious.bn254.scalar2, t: oblivious.bn254.scalar2) oblivious.bn254.scalar2[source]

Return scalar2 added to another scalar2.

>>> s = python.scl2()
>>> t = python.scl2()
>>> python.sad2(s, t) == python.sad2(t, s)
True
class point(bs: Optional[Union[bytes, bytearray]] = None)

Bases: bytes

class point2(bs: Optional[Union[bytes, bytearray]] = None)

Bases: bytes

class scalar(bs: Optional[Union[bytes, bytearray]] = None)

Bases: bytes

class scalar2(bs: Optional[Union[bytes, bytearray]] = None)

Bases: bytes

class oblivious.bn254.mcl[source]

Bases: object

Wrapper class for binary implementations of primitive operations.

When this module is imported, it makes a number of attempts to locate an instance of the shared/dynamic library file of the mclbn256 library on the host system. The sequence of attempts is listed below, in order.

  1. It uses ctypes.util.find_library to look for 'mcl' or 'mclbn256'.

  2. It attempts to find a file mclbn256.so or mclbn256.dll in the paths specified by the PATH and LD_LIBRARY_PATH environment variables.

  3. If the mclbn256 package is installed, it reverts to the compiled subset of mclbn256 included in that package.

If all of the above fail, then mcl is assigned the value None and all classes exported by this module default to their pure-Python variants (i.e., those encapsulated within python). One way to confirm that a dynamic/shared library has been found when this module is imported is to evaluate the expression mcl is not None.

If a shared/dynamic library file has been loaded successfully, this class encapsulates shared/dynamic library variants of all classes exported by this module and of all the underlying low-level operations: mcl.pnt, mcl.bas, mcl.can, mcl.ser, mcl.des, mcl.mul, mcl.add, mcl.sub, mcl.neg, mcl.par, mcl.rnd, mcl.scl, mcl.sse, mcl.sde, mcl.inv, mcl.smu, mcl.sad, mcl.ssu, mcl.sne, mcl.pnt2, mcl.bas2, mcl.can2, mcl.ser2, mcl.des2, mcl.mul2, mcl.add2, mcl.sub2, mcl.neg2, mcl.rnd2, mcl.scl2, mcl.sse2, mcl.sde2, mcl.inv2, mcl.smu2, mcl.sad2, mcl.point, mcl.scalar, mcl.point2, and mcl.scalar2. For example, you can perform addition of points using the point addition implementation found in the shared/dynamic library bundled with the instance of the package mclbn256 that is found on the host system.

>>> p = mcl.pnt()
>>> q = mcl.pnt()
>>> mcl.add(p, q) == mcl.add(q, p)
True

Methods found in the shared/dynamic library variants of the point, scalar, point2, and scalar2 classes are wrappers for the shared/dynamic library implementations of the underlying operations.

>>> p = mcl.point()
>>> q = mcl.point()
>>> p + q == q + p
True
static pnt(h: Optional[Union[bytes, bytearray]] = None) mclbn256.mclbn256.G1[source]

Construct a point if the supplied bytes-like object represents a valid point; otherwise, return None. If no byte vector is supplied, return a random point.

>>> p = mcl.pnt(hashlib.sha512('123'.encode()).digest())
>>> p.__class__ = point
>>> mcl.point.to_bytes(p).hex()[:64]
'6d68495eb4d539db4df70fd24d54fae37c9adf7dfd8dc705ccb8de8630e7cf22'
static bas(s: mclbn256.mclbn256.Fr) mclbn256.mclbn256.G1[source]

Return the base point multiplied by the supplied scalar.

>>> p = mcl.bas(mcl.scalar.hash('123'.encode())).normalize().normalize()
>>> p.__class__ = point
>>> mcl.point.to_bytes(p).hex()[:64]
'2d66076815cda25556bab4a930244ac284412267e9345aceb98d71530308401a'
static can(p: mclbn256.mclbn256.G1) mclbn256.mclbn256.G1[source]

Normalize the representation of a point into its canonical form and return the result.

>>> a = mcl.point.hash('123'.encode())
>>> p = mcl.add(a, a)
>>> p_can = mcl.can(mcl.add(a, a))

We may have ser(p_can) != ser(p) here, depending on the backend implementation. Either normalization matters, or MCl is not the backend.

>>> (mcl.ser(p_can) != mcl.ser(p)) or not mclbn256
True

Normalization is idempotent.

>>> mcl.can(p) == mcl.can(p_can)
True
static ser(p: mclbn256.mclbn256.G1) bytes[source]

Return the binary representation of a point.

>>> p = mcl.point.hash('123'.encode())
>>> mcl.des(mcl.ser(p)) == p
True
static des(bs: bytes) mclbn256.mclbn256.G1[source]

Construct a point corresponding to the supplied binary representation.

>>> p = mcl.point.hash('123'.encode())
>>> ser_p = bytes.fromhex(
...     '825aa78af4c88d6de4abaebabf1a96f668956b92876cfb5d3a44829899cb480f'
...     'b03c992ec97868be765b98048118a96f42bdc466a963c243c223b95196304209'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
... )
>>> mcl.des(ser_p) == p
True
>>> mcl.ser(mcl.des(ser_p)) == ser_p
True
static mul(s: mclbn256.mclbn256.Fr, p: mclbn256.mclbn256.G1) mclbn256.mclbn256.G1[source]

Multiply a point by a scalar and return the result.

>>> p = mcl.pnt(hashlib.sha512('123'.encode()).digest())
>>> s = mcl.scl(bytes.fromhex(
...     '35c141f1c2c43543de9d188805a210abca3cd39a1e986304991ceded42b11709'
... ))
>>> q = mcl.mul(s, p).normalize().normalize()
>>> q.__class__ = point
>>> mcl.point.to_bytes(q).hex()[:64]
'68b5dd61adaa83f1511efe7b4749481cc9f86e11bf82d82960b6c56373de0d24'
static add(p: mclbn256.mclbn256.G1, q: mclbn256.mclbn256.G1) mclbn256.mclbn256.G1[source]

Return the sum of the supplied points.

>>> p = mcl.point.hash('123'.encode())
>>> q = mcl.point.hash('456'.encode())
>>> r = mcl.add(p, q).normalize().normalize()
>>> r.__class__ = point
>>> mcl.point.to_bytes(r).hex()[:64]
'1ea48cab238fece46bd0c9fb562c859e318e17a8fb75517a4750d30ca79b911c'
static sub(p: mclbn256.mclbn256.G1, q: mclbn256.mclbn256.G1) mclbn256.mclbn256.G1[source]

Return the result of subtracting the right-hand point from the left-hand point.

>>> p = mcl.point.hash('123'.encode())
>>> q = mcl.point.hash('456'.encode())
>>> r = mcl.sub(p, q).normalize().normalize()
>>> r.__class__ = point
>>> mcl.point.to_bytes(r).hex()[:64]
'a43a5ce1931b1300b62e5d7e1b0c691203bfd85fafd9585dc5e47a7e2acfea22'
static neg(p: mclbn256.mclbn256.G1) mclbn256.mclbn256.G1[source]

Return the additive inverse of a point.

>>> p = mcl.point.hash('123'.encode())
>>> q = mcl.neg(p)
>>> q.__class__ = point
>>> mcl.point.to_bytes(q).hex()[:64]
'825aa78af4c88d6de4abaebabf1a96f668956b92876cfb5d3a44829899cb480f'
static par(p: Union[mclbn256.mclbn256.G1, mclbn256.mclbn256.G2], q: Union[mclbn256.mclbn256.G1, mclbn256.mclbn256.G2]) mclbn256.mclbn256.GT[source]

Compute the pairing function on two points.

>>> p = mcl.point.hash('123'.encode())
>>> q = mcl.point2.base(mcl.scalar.from_int(456))
>>> r = mcl.par(p, q)
>>> r.__class__ = mcl.scalar2
>>> mcl.scalar2.to_bytes(r).hex()[700:]
'd01f7e038b05acc5519eeda026c4aa111eb12f3483f274c60e34e6ec7571435df707'

The order of the two arguments is not important (as long as exactly one argument is an instance of point and the other is an instance of point2).

>>> r = mcl.par(q, p)
>>> r.__class__ = mcl.scalar2
>>> mcl.scalar2.to_bytes(r).hex()[700:]
'd01f7e038b05acc5519eeda026c4aa111eb12f3483f274c60e34e6ec7571435df707'

The pairing function is bilinear.

>>> p = mcl.point.random()
>>> s = mcl.scalar.random()
>>> t = mcl.scalar.random()
>>> q = mcl.point2.random()
>>> -((~s) * (s * p)) - p == mcl.scalar.from_int(-2) * p
True
>>> s * t * p @ q == s * p @ (t * q)
True

Suppose there are two points: one multiplied by the scalar s and the other multiplied by the scalar t. Their equality can be determined by using a balancing point: g**(~s * t). If the pairing of t * x with g is the same as the pairing with s * y and g**(~s * t), then x equals y.

>>> x = y = p
>>> g = mcl.point2.base(mcl.scalar.from_int(1))
>>> b = mcl.point2.base(~s * t)
>>> (t * x) @ g == (s * y) @ b
True

This operation is defined only for a point and a second-level point. Any attempt to invoke the operation on values or objects of other types raises an exception.

>>> p @ (p + p)
Traceback (most recent call last):
  ...
TypeError: pairing is defined only for a point and a second-level point
>>> g @ b
Traceback (most recent call last):
  ...
TypeError: pairing is defined only for a point and a second-level point

Pairing is intended to be nonsingular.

>>> p @ q.clear()
Traceback (most recent call last):
  ...
TypeError: cannot meaningfully pair the infinity point
>>> p.clear() @ g
Traceback (most recent call last):
  ...
TypeError: cannot meaningfully pair the infinity point
static rnd() mclbn256.mclbn256.Fr[source]

Return random non-zero scalar.

>>> s = mcl.rnd()
>>> isinstance(s, Fr)
True
>>> s.__class__ = scalar
>>> len(mcl.scalar.to_bytes(s))
32
classmethod scl(bs: Optional[Union[bytes, bytearray]] = None) Optional[mclbn256.mclbn256.Fr][source]

Construct a scalar if the supplied bytes-like object represents a valid scalar; otherwise, return None. If no byte vector is supplied, return a random scalar.

>>> s = mcl.scl()
>>> s.__class__ = scalar
>>> t = mcl.scl(mcl.scalar.to_bytes(s))
>>> s == t
True
>>> mcl.scl(bytes([255] * 32)) is None
True
static sse(s: mclbn256.mclbn256.Fr) bytes[source]

Return the binary representation of a scalar.

>>> s = mcl.scalar.hash('123'.encode())
>>> mcl.sde(mcl.sse(s)) == s
True
static sde(bs: bytes) mclbn256.mclbn256.Fr[source]

Return a scalar from its binary representation.

>>> s = mcl.scalar.hash('123'.encode())
>>> bs = bytes.fromhex(
...     '93d829354cb3592743174133104b5405ba6992b67bb219fbde3e394d70505913'
... )
>>> mcl.sde(bs) == s
True
>>> mcl.sse(mcl.sde(bs)) == bs
True
static inv(s: mclbn256.mclbn256.Fr) mclbn256.mclbn256.Fr[source]

Return inverse of a scalar (modulo r = 16798108731015832284940804142231733909759579603404752749028378864165570215949 in the prime field F_*r*).

>>> (s, p) = (mcl.scl(), mcl.pnt())
>>> mcl.mul(mcl.inv(s), mcl.mul(s, p)) == p
True
static smu(s: mclbn256.mclbn256.Fr, t: mclbn256.mclbn256.Fr) mclbn256.mclbn256.Fr[source]

Return scalar multiplied by another scalar.

>>> (s, t) = (mcl.scl(), mcl.scl())
>>> mcl.smu(s, t) == mcl.smu(t, s)
True
static sad(s: mclbn256.mclbn256.Fr, t: mclbn256.mclbn256.Fr) mclbn256.mclbn256.Fr[source]

Return scalar added to another scalar.

>>> (s, t) = (mcl.scl(), mcl.scl())
>>> mcl.sad(s, t) == mcl.sad(t, s)
True
static ssu(s: mclbn256.mclbn256.Fr, t: mclbn256.mclbn256.Fr) mclbn256.mclbn256.Fr[source]

Return the result of one scalar subtracted from another scalar.

>>> (s, t) = (mcl.scl(), mcl.scl())
>>> mcl.ssu(s, t) == mcl.sad(s, mcl.sne(t))
True
>>> mcl.ssu(s, t) == mcl.sne(mcl.ssu(t, s))
True
static sne(s: mclbn256.mclbn256.Fr) mclbn256.mclbn256.Fr[source]

Return the additive inverse of a scalar.

>>> (s, t) = (mcl.scl(), mcl.scl())
>>> mcl.sne(mcl.sne(s)) == s
True
static pnt2(h: Optional[bytes] = None) mclbn256.mclbn256.G2[source]

Construct a second-level point if the supplied bytes-like object represents a valid second-level point; otherwise, return None. If no byte vector is supplied, return a random second-level point.

>>> p = mcl.pnt2(hashlib.sha512('123'.encode()).digest())
>>> p.__class__ = point2
>>> mcl.point2.to_bytes(p.canonical().canonical()).hex()[:128] == (
...     '4c595542640a69c4a70bda55c27ef96c133cd1f4a5f83b3371e571960c018e19'
...     'c54aaec2069f8f10a00f12bcbb3511cdb7356201f5277ec5e47da91405be2809'
... )
True
static bas2(s) mclbn256.mclbn256.G2[source]

Return the base second-level point multiplied by the supplied scalar.

>>> r = mcl.bas2(mcl.scalar.hash('123'.encode())).normalize().normalize()
>>> r.__class__ = point2
>>> mcl.point2.to_bytes(r).hex()[:64]
'e7000fb12d206112c73fe1054e9d77b35c77881eba6598b7e035171d90b13e0c'
static can2(p: mclbn256.mclbn256.G2) mclbn256.mclbn256.G2[source]

Normalize the representation of a second-level point into its canonical form and return the result.

>>> p = mcl.bas2(scalar.from_int(1))
>>> mcl.ser(mcl.can2(p)).hex()[:64]
'669e6563afaa45af7cbc013d23f092bb3763d4dc41b97aef555bdf61de713f17'
static ser2(p: mclbn256.mclbn256.G2) bytes[source]

Return the binary representation of a second-level point.

>>> p = mcl.point2.hash('123'.encode())
>>> mcl.des2(mcl.ser2(p)) == p
True

It is the responsibility of the user to ensure that only canonical representations of points are serialized.

static des2(bs: bytes) mclbn256.mclbn256.G2[source]

Return the second-level point corresponding to the supplied binary representation thereof.

>>> p = mcl.point2.hash('123'.encode())
>>> mcl.ser_p = bytes.fromhex(
...     'b5b0a52e43ba71ae03317333da4ba9452dbdbbec353ade0c732348e0bea4ba1b'
...     '8860718e5ba784d55799ab292459a638f6399738a6de348742e6a789674f300d'
...     '7e59c60a595253ebf69bf0794b7a032e59b6b5037adba410d680b53ffac08517'
...     'cf5bc3be9d850ec64ea6939904cf66b66b6b4b82be03ee4f10661fedaf83841f'
...     'ba7e678442a658340a5b3c51eb5076d738cf88387ada6cbd1fe7f8d8a2268417'
...     'bc8aedbc99808b0450025d0c75b5f1ccb34bc69934cc620d9ea51038a1d98721'
... )
>>> mcl.des2(mcl.ser_p) == p
True
>>> mcl.ser(mcl.des2(mcl.ser_p)) == mcl.ser_p
True
static mul2(s: mclbn256.mclbn256.Fr, p: mclbn256.mclbn256.G2) mclbn256.mclbn256.G2[source]

Multiply a second-level point by a scalar.

>>> p = mcl.point2.hash('123'.encode())
>>> s = mcl.scl(bytes.fromhex(
...     '35c141f1c2c43543de9d188805a210abca3cd39a1e986304991ceded42b11709'
... ))
>>> r = mcl.mul2(s, p).normalize().normalize()
>>> r.__class__ = point2
>>> mcl.point2.to_bytes(r).hex() == (
...     '5f6f2ace8566ca47354fbe244ae3e6a854c37011fb6d6ac56571c94169e4ab18'
...     '650bea4cfed5c9603e5949fe3d7509b17e20db4ff1f05129aad0d0a3bffb0008'
...     '3043c5a14b986882836b1c929952ea3881d04ca44d487d1ab2d4c0b171b87d14'
...     '5dca6dabb4f0ea7be5c95a861ed319d146b15d70542d3952af995a8bb35b8314'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static add2(p: mclbn256.mclbn256.G2, q: mclbn256.mclbn256.G2) mclbn256.mclbn256.G2[source]

Return sum of the supplied second-level points.

>>> p = mcl.point2.hash('123'.encode())
>>> q = mcl.point2.hash('456'.encode())
>>> r = mcl.add2(p, q).normalize().normalize()
>>> r.__class__ = point2
>>> mcl.point2.to_bytes(r).hex() == (
...     'cb0fc423c1bac2ac2df47bf5f5548a42b0d0a0da325bc77243d15dc587a7b221'
...     '9808a1649991ddf770f0060333aab4d499580b123f109b5cb180f1f8a75a090e'
...     '83dd34d9ecdd6fd639230f7f0cf44b218fae4d879111de6c6c037e6ffdcdc823'
...     'f5a48318143873ca90ad512a2ea1854200eea5537cd0ac93691d5b94ff36b212'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static sub2(p: mclbn256.mclbn256.G2, q: mclbn256.mclbn256.G2) mclbn256.mclbn256.G2[source]

Return the result of subtracting the right-hand second-level point from the left-hand second-level point.

>>> p = mcl.point2.hash('123'.encode())
>>> q = mcl.point2.hash('456'.encode())
>>> r = mcl.sub2(p, q).normalize().normalize()
>>> r.__class__ = point2
>>> mcl.point2.to_bytes(r).hex() == (
...     'e97a70c4e3a5369ebbb1dcf0cc1135c8c8e04a4ec7cffdf875ac429d66846d0b'
...     '191b090909c40a723027b07ac44435a6ade3813d04b3632a17c92c5c98718902'
...     '407c58ed13cc0c0aaa43d0eafd44080080c8199401fe4f8ed7dd0eb5fba86817'
...     '141f74341ce3c4884f86a97f51f7c0b208fe52be336b7651252fa9881c93d203'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static neg2(p: mclbn256.mclbn256.G2) mclbn256.mclbn256.G2[source]

Return the negation of a second-level point.

>>> p = mcl.point2.hash('123'.encode())
>>> r = mcl.neg2(p).normalize().normalize()
>>> r.__class__ = point2
>>> mcl.point2.to_bytes(r).hex() == (
...     '30326199f303fce7a77cff6d2fb0b3de8cd409d1d562f3543f7d064cdc58d309'
...     '7e88038ad76e85e5df26e4a9486a657b0431c8e7e09b0a1abf90fc874c515207'
...     'e7957744bb7f9abb9e7209cd4e27ae80d8ab490a1072af125034c7b09c12281c'
...     '0fbab105e7942bf5dbe1ac290ce01232b800aac41de98f86d04bd3a81758cf05'
...     '8effffffffffff158affffffffff39b9cdffffffff2ec6a2f5ffff7ff2a42b21'
...     '0000000000000000000000000000000000000000000000000000000000000000'
... )
True
static rnd2() mclbn256.mclbn256.GT[source]

Return random non-zero second-level scalar.

>>> isinstance(mcl.rnd2(), GT)
True
static scl2(s: Optional[Union[bytes, bytearray]] = None) Optional[mclbn256.mclbn256.GT][source]

Construct a second-level scalar if the supplied bytes-like object represents a valid second-level scalar; otherwise, return None. If no byte vector is supplied, return a random second-level scalar.

>>> bs = bytes.fromhex(
...     '18d0e065798ffa4ecca0a7cc6e2b8d6d3269f7eb413525e59b731332b02ea805'
...     '4b90c89ce93e4452557f53aae5f8f13221858dde2ea6a50373f1858f11287021'
...     '09b3daf7a217a20a3d872632f8ced643d32649b241a67601bec855bd43f07710'
...     '88df722bcacc8fd174f16ad7ef1b1d5e622d93b7cfec6385c353c13793a4e01c'
...     '371ef54cd836a88e1b1f1e198d566d3bbe5aa225734305f14cac9af9c821351c'
...     '86b365190105d1b7e71011d1362ed6ad9133a2c2c42898e9ebc3d1604a608f10'
...     '8461d37b2463b4f88f0ccb427b5eea8714ee88f8c33daf7ee4a3f45ca8bca911'
...     '87956abb4d27de1b49e5e059f904fbb475804715ab25a17306fa0e196f305215'
...     '3a60dfa073ca78de49edeaac9c54cab3d0138750c23c0b68de7924a69d1ba002'
...     'a24ac592622a45c59c1ded7133794292a09602bd57a36601d35438846fcb370f'
...     '39c0fa7a15b34d14ab6f95ee5bf5b26bd5def1e7ed07350922d445da07d93622'
...     '2db5baa9dec152c2b2bcfc46cde6fd22e70271af8a164e77e5808ce602095a1f'
... )
>>> s = mcl.scl2(bs)
>>> s.__class__ = mcl.scalar2
>>> mcl.scalar2.to_bytes(s).hex()[700:]
'36222db5baa9dec152c2b2bcfc46cde6fd22e70271af8a164e77e5808ce602095a1f'
static sse2(s: oblivious.bn254.scalar2) bytes[source]

Return the binary representation of a second-level scalar.

>>> s = scalar2.hash('123'.encode())
>>> mcl.sde2(mcl.sse2(s)) == s
True
static sde2(bs: bytes) mclbn256.mclbn256.GT[source]

Return the second-level scalar corresponding to the supplied binary representation thereof.

>>> s = mcl.scalar2.hash('123'.encode())
>>> bs = bytes.fromhex(
...     '36980a8359d40e106075488e80cf1479f2e6ba95d6a99a67832d21b7b94d8c1d'
...     '5eb4d655f23e1d5d499d51d1c552b5e7df6943091427cd080f582e120613a021'
...     '85898ef7d016e47a74a8df62316cc4ad975cb64bb63867ed9b5221f77bb9a121'
...     '7bd89cd213eee0c3fdf2e0e13ef9e30383ea5607c8d13fc10e04448a6c964a00'
...     '04a098a55beab09732220966319333608b2187ee2196eb5b4253bc2b1aea5303'
...     '654260dd687a2eb176a494258ff7ef753f93105a6f0e9f46c926afdbe31ff124'
...     '6bdd87c32537abcdb46ad542792edd74a229c9ba61abcd993f074237a91f5215'
...     '8f6b07886895733edde15cb22129459162d89d3662826b74e4fcbe4e9e8c2420'
...     'bd53586a09f91ff8f67f92cba72c5b64a9c3965c01e93710200ab4e084955316'
...     'fb18950835b79fb4c2930efcc5fcaa9d82ee0faff036b80657daee233a445901'
...     '7df3e57cb535ed26162b3ee0f8961131a93fe3198dc5393d277ed8bac5532411'
...     '93b7ad15c52ca123fd26f592a2219b1bf118b3035893cc4abf614b422f978718'
... )
>>> mcl.sde2(bs) == s
True
>>> mcl.sse(mcl.sde2(bs)) == bs
True
static inv2(s: mclbn256.mclbn256.GT) mclbn256.mclbn256.GT[source]

Return the inverse of a second-level scalar.

>>> s = mcl.scl2()
>>> mcl.smu2(s, mcl.smu2(s, mcl.inv2(s))) == s
True
>>> mcl.smu2(mcl.smu2(s, s), mcl.inv2(s)) == s
True
static smu2(s: mclbn256.mclbn256.GT, t: mclbn256.mclbn256.GT) mclbn256.mclbn256.GT[source]

Return the product of two second-level scalars.

>>> p1 = mcl.point.hash('123'.encode())
>>> p2 = mcl.point.hash('456'.encode())
>>> q1 = mcl.point2.base(mcl.scalar.hash('123'.encode()))
>>> q2 = mcl.point2.base(mcl.scalar.hash('456'.encode()))
>>> s = p1 @ q1
>>> t = p2 @ q2
>>> mcl.smu2(s, t) == mcl.smu2(t, s)
True
static sad2(s: mclbn256.mclbn256.GT, t: mclbn256.mclbn256.GT) mclbn256.mclbn256.GT[source]

Return the sum of two second-level scalars.

>>> s = mcl.scl2()
>>> t = mcl.scl2()
>>> mcl.sad2(s, t) == mcl.sad2(t, s)
True
class point(bs: Optional[Union[bytes, bytearray]] = None)

Bases: object

class point2(bs: Optional[Union[bytes, bytearray]] = None)

Bases: object

class scalar(bs: Optional[Union[bytes, bytearray]] = None)

Bases: object

class scalar2(bs: Optional[Union[bytes, bytearray]] = None)

Bases: object