Giter VIP home page Giter VIP logo

supranational / blst Goto Github PK

View Code? Open in Web Editor NEW
438.0 21.0 158.0 1.88 MB

Multilingual BLS12-381 signature library

License: Apache License 2.0

C 13.75% Assembly 70.62% Go 5.21% Python 2.68% Rust 4.13% Batchfile 0.03% Shell 0.32% C++ 1.61% Java 0.06% JavaScript 0.07% TypeScript 0.17% Makefile 0.04% C# 1.28% HTML 0.04%
blst-library signatures blst eth2 filecoin bls12-381 hash-to-curve bls-signature

blst's Introduction

Build Status Actions status CodeQL status

blst

blst (pronounced 'blast') is a BLS12-381 signature library focused on performance and security. It is written in C and assembly.

Table of Contents

Status

This library is under active development

An initial audit of this library was conducted by NCC Group in January 2021 and can be found here.

Formal verification of this library by Galois is on-going and can be found here.

This library is compliant with the following IETF draft specifications:

The serialization formatting is implemented according to the ZCash definition.

General notes on implementation

The goal of the blst library is to provide a foundational component for applications and other libraries that require high performance and formally verified BLS12-381 operations. With that in mind some decisions are made to maximize the public good beyond BLS12-381. For example, the field operations are optimized for general 384-bit usage, as opposed to tuned specifically for the 381-bit BLS12-381 curve parameters. With the formal verification of these foundational components, we believe they can provide a reliable building block for other curves that would like high performance and an extra element of security.

The library deliberately abstains from dealing with memory management and multi-threading, with the rationale that these ultimately belong in language-specific bindings. Another responsibility that is left to application is random number generation. All this in the name of run-time neutrality, which makes integration into more stringent environments like Intel SGX or ARM TrustZone trivial.

Platform and Language Compatibility

This library primarily supports x86_64 and ARM64 hardware platforms, and Linux, Mac, and Windows operating systems. But it does have a portable replacement for the assembly modules, which can be compiled for a plethora of other platforms. Problem reports for these will be considered and are likely to be addressed.

This repository includes explicit bindings for:

Unless deemed appropriate to implement, bindings for other languages will be provided using SWIG. Proof-of-concept scripts are available for:

API

The blst API is defined in the C header bindings/blst.h. The API can be categorized as follows, with some example operations:

  • Field Operations (add, sub, mul, neg, inv, to/from Montgomery)
  • Curve Operations (add, double, mul, to/from affine, group check)
  • Intermediate (hash to curve, pairing, serdes)
  • BLS12-381 signature (sign, verify, aggregate)

Note: there is also an auxiliary header file, bindings/blst_aux.h, that is used as a staging area for experimental interfaces that may or may not get promoted to blst.h.

Introductory Tutorial

Programming is understanding, and understanding implies mastering the lingo. So we have a pair of additive groups being mapped to multiplicative one... What does it mean? Well, this tutorial is not about explaining that, but rather about making the connection between what you're supposed to know about pairing-based cryptography and the interface provided by the library.

Public Keys and Signatures

We have two elliptic curves, E1 and E2, points on which are contained in blst_p1 and blst_p2, or blst_p1_affine and blst_p2_affine structures. Elements in the multiplicative group are held in a blst_fp12 structure. One of the curves, or more specifically, a subset of points that form a cyclic group, is chosen for public keys, and another, for signatures. The choice is denoted by the subroutines' suffixes, _pk_in_g1 or _pk_in_g2. The most common choice appears to be the former, that is, blst_p1 for public keys, and blst_p2 for signatures. But it all starts with a secret key...

The secret key is held in a 256-bit blst_scalar structure which can be instantiated with either blst_keygen, or deserialized with blst_scalar_from_bendian or blst_scalar_from_lendian from a previously serialized byte sequence. It shouldn't come as surprise that there are two uses for a secret key:

  • generating the associated public key, either with blst_sk_to_pk_in_g1 or blst_sk_to_pk_in_g2;
  • performing a sign operation, either with blst_sign_pk_in_g1 or blst_sign_pk_in_g2;

As for signing, unlike what your intuition might suggest, blst_sign_* doesn't sign a message, but rather a point on the corresponding elliptic curve. You can obtain this point from a message by calling blst_hash_to_g2 or blst_encode_to_g2 (see the IETF hash-to-curve draft for distinction). Another counter-intuitive aspect is the apparent g1 vs. g2 naming mismatch, in the sense that blst_sign_pk_in_g1 accepts output from blst_hash_to_g2, and blst_sign_pk_in_g2 accepts output from blst_hash_to_g1. This is because, as you should recall, public keys and signatures come from complementary groups.

Now that you have a public key and signature, as points on corresponding elliptic curves, you can serialize them with blst_p1_serialize/blst_p1_compress and blst_p2_serialize/blst_p2_compress and send the resulting byte sequences over the network for deserialization/uncompression and verification.

Signature Verification

Even though there are "single-shot" blst_core_verify_pk_in_g1 and blst_core_verify_pk_in_g2, you should really familiarize yourself with the more generalized pairing interface. blst_pairing is an opaque structure, and the only thing you know about it is blst_pairing_sizeof, which is how much memory you're supposed to allocate for it. In order to verify an aggregated signature for a set of public keys and messages, or just one[!], you would:

blst_pairing_init(ctx, hash_or_encode, domain_separation_tag);
blst_pairing_aggregate_pk_in_g1(ctx, PK[0], aggregated_signature, message[0]);
blst_pairing_aggregate_pk_in_g1(ctx, PK[1], NULL, message[1]);
...
blst_pairing_commit(ctx);
result = blst_pairing_finalverify(ctx, NULL);

The essential point to note is that it's the caller's responsibility to ensure that public keys are group-checked with blst_p1_affine_in_g1. This is because it's a relatively expensive operation and it's naturally assumed that the application would cache the check's outcome. Signatures are group-checked internally. Not shown in the pseudo-code snippet above, but aggregate and commit calls return BLST_ERROR denoting success or failure in performing the operation. Call to finalverify, on the other hand, returns boolean.

Another, potentially more useful usage pattern is:

blst_p2_affine_in_g2(signature);
blst_aggregated_in_g2(gtsig, signature);
blst_pairing_init(ctx, hash_or_encode, domain_separation_tag);
blst_pairing_aggregate_pk_in_g1(ctx, PK[0], NULL, message[0]);
blst_pairing_aggregate_pk_in_g1(ctx, PK[1], NULL, message[1]);
...
blst_pairing_commit(ctx);
result = blst_pairing_finalverify(ctx, gtsig);

What is useful about it is that aggregated_signature can be handled in a separate thread. And while we are at it, aggregate calls can also be executed in different threads. This naturally implies that each thread will operate on its own blst_pairing context, which will have to be combined with blst_pairing_merge as threads join.

Signature Aggregation

Aggregation is a trivial operation of performing point additions, with blst_p2_add_or_double_affine or blst_p1_add_or_double_affine. Note that the accumulator is a non-affine point.


That's about what you need to know to get started with nitty-gritty of actual function declarations.

Serialization Format

From the ZCash BLS12-381 specification

  • Fq elements are encoded in big-endian form. They occupy 48 bytes in this form.
  • Fq2 elements are encoded in big-endian form, meaning that the Fq2 element c0 + c1 * u is represented by the Fq element c1 followed by the Fq element c0. This means Fq2 elements occupy 96 bytes in this form.
  • The group G1 uses Fq elements for coordinates. The group G2 uses Fq2 elements for coordinates.
  • G1 and G2 elements can be encoded in uncompressed form (the x-coordinate followed by the y-coordinate) or in compressed form (just the x-coordinate). G1 elements occupy 96 bytes in uncompressed form, and 48 bytes in compressed form. G2 elements occupy 192 bytes in uncompressed form, and 96 bytes in compressed form.

The most-significant three bits of a G1 or G2 encoding should be masked away before the coordinate(s) are interpreted. These bits are used to unambiguously represent the underlying element:

  • The most significant bit, when set, indicates that the point is in compressed form. Otherwise, the point is in uncompressed form.
  • The second-most significant bit indicates that the point is at infinity. If this bit is set, the remaining bits of the group element's encoding should be set to zero.
  • The third-most significant bit is set if (and only if) this point is in compressed form and it is not the point at infinity and its y-coordinate is the lexicographically largest of the two associated with the encoded x-coordinate.

Build

The build process is very simple and only requires a C compiler. It's integrated into the Go and Rust ecosystems, so that respective users would go about as they would with any other external module. Otherwise, a binary library would have to be compiled.

C static library

A static library called libblst.a can be built in the current working directory of the user's choice:

Linux, Mac, and Windows (in MinGW or Cygwin environments)

/some/where/build.sh

Windows (Visual C)

\some\where\build.bat

If final application crashes with an "illegal instruction" exception [after copying to another system], pass -D__BLST_PORTABLE__ on build.sh command line. If you don't use build.sh, complement the CFLAGS environment variable with the said command line option. If you compile a Go application, you will need to modify the CGO_CFLAGS variable instead. And if you compile a Rust application, you can pass --features portable to cargo build. Alternatively, if you compile on an older Intel system, but will execute application on a newer one, consider instead passing --features force-adx for better performance.

Language-specific notes

There are two primary modes of operation that can be chosen based on type definitions in the application.

For minimal-pubkey-size operations:

type PublicKey = blst.P1Affine
type Signature = blst.P2Affine
type AggregateSignature = blst.P2Aggregate
type AggregatePublicKey = blst.P1Aggregate

For minimal-signature-size operations:

type PublicKey = blst.P2Affine
type Signature = blst.P1Affine
type AggregateSignature = blst.P1Aggregate
type AggregatePublicKey = blst.P2Aggregate

For more details see the Go binding readme.

blst is the Rust binding crate.

To use min-pk version:

use blst::min_pk::*;

To use min-sig version:

use blst::min_sig::*;

For more details see the Rust binding readme.

Repository Structure

Root - Contains various configuration files, documentation, licensing, and a build script

  • Bindings - Contains the files that define the blst interface
    • blst.h - provides C API to blst library
    • blst_aux.h - contains experimental functions not yet committed for long-term maintenance
    • blst.hpp - provides foundational class-oriented C++ interface to blst library
    • blst.swg - provides SWIG definitions for creating blst bindings for other languages, such as Java and Python
    • C# - folder containing C# bindings and an example of how to use them
    • Emscripten - folder containing an example of how to use Emscripten WebAssembly bindings from Javascript
    • Go - folder containing Go bindings for blst, including tests and benchmarks
    • Java - folder containing an example of how to use SWIG Java bindings for blst
    • Node.js - folder containing an example of how to use SWIG Javascript bindings for blst
    • Python - folder containing an example of how to use SWIG Python bindings for blst
    • Rust - folder containing Rust bindings for blst, including tests and benchmarks
    • Vectors
      • Hash_to_curve: folder containing test for hash_to_curve from IETF specification
  • Src - folder containing C code for lower level blst functions such as field operations, extension field operations, hash-to-field, and more
    • Asm - folder containing Perl scripts that are used to generate assembly code for different hardware platforms including x86 with ADX instructions, x86 without ADX instructions, and ARMv8, and ABI[1]
  • Build - this folder containing a set of pre-generated assembly files for a variety of operating systems and maintenance scripts.
    • Cheri - assembly code for use on CHERI platforms
    • Coff - assembly code for use on Window systems with GNU toolchain
    • Elf - assembly code for use on Unix systems
    • Mach-o - assembly code for use on Apple operating systems
    • Win64 - assembly code for use on Windows systems with Microsoft toolchain

[1]: See refresh.sh for usage. This method allows for simple reuse of optimized assembly across various platforms with minimal effort.

Performance

Currently both the Go and Rust bindings provide benchmarks for a variety of signature related operations.

License

The blst library is licensed under the Apache License Version 2.0 software license.

blst's People

Contributors

ajsutton avatar alinush avatar cemozerr avatar dannywillems avatar dapplion avatar dot-asm avatar gyuho avatar hellosupranational avatar huitseeker avatar jtraglia avatar kirk-baird avatar kwantam avatar michaelsproul avatar mratsim avatar nano-o avatar patrick-ogrady avatar paulhauner avatar sean-sn avatar simonatsn avatar stephenbuttolph avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blst's Issues

SWIG Java uint64_t binding on Windows

That issue is not directly related to blst code, but rather a general SWIG question.

I've simplified the code for experiments:
test.h:

typedef struct { uint64_t arr[4]; } scalar;

void fun1(scalar *ret);
void fun2(scalar s);

test.swg:

%module "test"
%include "test.h";

The SWIG 4.0 Windows was used for experiments.

If I generate the wrapper in this simple case with swig.exe test.swg (result) or swig.exe -DSWIGWORDSIZE64 test.swg (result) I've got opaque SWIGTYPE_p_uint64_t.java which is unusable

Some SO article led me to the following solution:
test.swg:

%module "test"

%include "stdint.i";
%include "arrays_java.i";

%include "test.h";

with swig.exe test.swg I've got the same result as earlier.
However with swig.exe -DSWIGWORDSIZE64 test.swg I've finally got ability to pass the uint64_t with java long[] :
void setArr(long[] value)

But! As we run with -DSWIGWORDSIZE64 option the SWIG generated C wrapper code which uses unsigned long to refer uint64_t when copying Java arrays :
https://github.com/Nashatyrev/swig.test/blob/master/case.4/build/test_wrap.c#L810

  if (!SWIG_JavaArrayInUlong(jenv, &jarr2, (unsigned long **)&arg2, jarg2)) return ; 

On Windows unsigned long is 32-bit so the code works incorrectly.
(btw on Linux the same generated code should work)

If you have some SWIG experience may be you can give me a hint how to handle this situation?

Python example question

I noticed that in Python example (run.me) different affine used for the signature construction from binary data:

########################################################################
# at this point 'pk_for_wire', 'sig_for_wire' and 'msg' are
# "sent over network," so now on "receiver" side

sig = blst.P1_Affine(sig_for_wire)
pk  = blst.P2_Affine(pk_for_wire)

########################################################################
# from https://github.com/supranational/blst/issues/5

pk_for_wire = bytes.fromhex("ab10fc693d038b73d67279127501a05f0072cbb7147c68650ef6ac4e0a413e5cabd1f35c8711e1f7d9d885bbc3b8eddc")
sig_for_wire = bytes.fromhex("a44158c08c8c584477770feec2afa24d5a0b0bab2800414cb9efbb37c40339b6318c9349dad8de27ae644376d71232580ff5102c7a8579a6d2627c6e40b0ced737a60c66c7ebd377c04bf5ac957bf05bc8b6b09fbd7bdd2a7fa1090b5a0760bb")
msg = bytes.fromhex("0000000000000000000000000000000000000000000000000000000000000000")
DST = bytes.fromhex("424c535f5349475f424c53313233383147325f584d443a5348412d3235365f535357555f524f5f504f505f")

sig = blst.P2_Affine(sig_for_wire)
pk  = blst.P1_Affine(pk_for_wire)

In first case P1_Affine was used and for the second case P2_Affine. Is it correct?

Rust Subgroup Checks

Thought I'd open the issue to get the current status of subgroup checks for signatures and public keys in the rust bindings and hopefully reach a conclusion.

A quick summary of previous discussions (sorry if I've forgotten any):

  1. Check subgroups on deserialisation
    Note: I believe this is currently what the go bindings do?
    Pros - simple, secure, if points are cached in BLST format the subgroup check is done once per point.
    Cons - if the same signature / public key is deserialised/not cached in BLST format, there are unnecessary subgroup checks

  2. Always check signatures, skip public keys only on PoPVerified public keys (e.g. when calling fast_aggregate_verify() public keys are always PoPVerified).
    Pros - Faster deserialisation times, public keys will only be checked once
    Cons - Wasteful if we verify signatures then aggregate them, slower if we use public keys multiple times for non-PoPVerified methods.

  3. Always check signatures and publickeys
    Pros - this matches the BLS Spec
    Cons - wasteful as points will have the subgroup checked during every use and public keys are likely used numerous times.

Personally I'm leaning towards option 1 to match the go bindings and for it's simplicity. Option 2 has a few edge cases to be weary of such as if we do fast_aggregate_verify_multiple() which multiplies a signature by random integer so we'd have to do subgroup checks before multiplication and aggregating signatures into an which individually aren't in the correct subgroup but aggregated are.

[doc] Aggregate - pairing_mul_n

Looking into aggregate.c it's clear what blst_pairing_aggregate_pk_in_g1 is for but blst_pairing_mul_n_aggregate_pk_in_g1 is not documented.

blst/src/aggregate.c

Lines 7 to 34 in 6d6dec3

/*
* Usage pattern on single-processor system is
*
* blst_pairing_init(ctx);
* blst_pairing_aggregate_pk_in_g1(ctx, PK1, aggregated_signature, message1);
* blst_pairing_aggregate_pk_in_g1(ctx, PK2, NULL, message2);
* ...
* blst_pairing_commit(ctx);
* blst_pairing_finalverify(ctx, NULL);
*
***********************************************************************
* Usage pattern on multi-processor system is
*
* blst_pairing_init(pk0);
* blst_pairing_init(pk1);
* ...
* start threads each processing a slice of PKs and messages:
* blst_pairing_aggregate_pk_in_g1(pkx, PK[], NULL, message[]);
* blst_pairing_commit(pkx);
* ...
* blst_fp12 gtsig;
* blst_aggregated_in_g2(&gtsig, aggregated_signature);
* join threads and merge their contexts:
* blst_pairing_merge(pk0, pk1);
* blst_pairing_merge(pk0, pk2);
* ...
* blst_pairing_finalverify(pk0, gtsig);
*/

It seems like it's computing ฮป0 e(PK0, H(msg0)) ฮป1 e(PK1, H(msg1)) ... with ฮปi != 1

Point Decompression does not enforce field points are less than field modulus.

What is the issue?

When decompression a point each specific field point should be strictly less than the field modulus.
For example a min PublicKey should have the x coordinate strictly less than the field modulus. PublicKey.X < P

If this is not enforced, signature malleability may occur by taking Signature.X[0] from a valid signature and doing Signature.X[0] + P which will equate to the same point thus providing signature malleability.

What needs to be done?

I think this check out be easiest to do on the limbs just after converting bytes to words. That is in src/vect.h::limbs_from_be_bytes(). That way a simple loop can be made checking each word from the most significant word is less than, equal to or greater than the equivalent word in the field modulus.
This could break the loop if a word is less than, error/exit if a word is greater than and continue if a word is equal to the field modulus word.

AggregateVerify Verifies for Infinite Pubkeys

As of aae0c7d ,

AggegateVerify will verify a message signed by a zero key as valid. This will only be triggered if there are
multiple messages/pubkeys to verify. In the event the message and pubkey are singluar verification fails correctly.

https://github.com/supranational/blst/blob/master/bindings/go/blst.go#L282

To illustrate here is a test case for it:

func TestSignVerifyAggregateValidatesInfinitePubkey(t *testing.T) {
	size := 20
	sks, msgs, _, pubks, _, err :=
		generateBatchTestDataUncompressedMinPk(size)
	if err {
		t.Errorf("Error generating test data")
		return
	}

	// All signers sign the same message
	sigs := make([]*SignatureMinPk, 0)
	for i := 0; i < size; i++ {
		sigs = append(sigs, new(SignatureMinPk).Sign(sks[i], msgs[i],
			dstMinPk))
	}

	// Infinite pubkeys and signature
	zeroKey := new(PublicKeyMinPk)
	zeroSig := new(SignatureMinPk)
	agProj := new(AggregateSignatureMinPk).Aggregate([]*SignatureMinPk{zeroSig})
	if agProj == nil {
		t.Errorf("Aggregate unexpectedly returned nil")
		return
	}
	agSig := agProj.ToAffine()

	if !agSig.AggregateVerify([]*PublicKeyMinPk{zeroKey}, [][]byte{msgs[0]}, dstMinPk) {
		t.Errorf("failed to verify signature")
	}

	// Replace firstkey with infinite pubkey.
	pubks[0] = zeroKey
	sigs[0] = zeroSig
	agProj = new(AggregateSignatureMinPk).Aggregate(sigs)
	if agProj == nil {
		t.Errorf("Aggregate unexpectedly returned nil")
		return
	}
	agSig = agProj.ToAffine()

	if !agSig.AggregateVerify(pubks, msgs, dstMinPk) {
		t.Errorf("failed to verify signature")
	}
}

The first test case correctly fails, while the second test case actually passes.

node.js v12+

This is a placeholder issue to track swig/swig#1746, which adds node.js v12+ support to swig. And to provide a download point for pre-generated wrapper, blst_wrap.cpp, for those who don't want to experiment with swig compilation.

NodeJS multi-thread support

Current NodeJS bindings are not able to run in a multi-threaded setup with worker_threads reliably. Most of the times the parent process crashes with a segmentation fault. I'm working on creating a minimal reproducible POC that always crashes, but it's proving very difficult.

First of all, could you say if current SWIG NodeJS bindings are safe to multi-thread? There's some directions about to load the same bindings in multiple threads in the NodeJS docs. I wonder if the current SWIG setup achieves any of this directions. https://nodejs.org/api/addons.html#addons_worker_support

In our particular case I would be happy with a threaded setup where threads don't share any resources and only communicate with the main thread through messages.

Rust bindings: add typical impls

Thanks again for this great library!

When implementing blst in Lighthouse (Eth2 impl) I noticed that the core structs (e.g., PublicKey, Signature, etc) are missing some typical and useful impls. In particular:

  • Clone
  • PartialEq
  • Eq (if it adheres to the definition here)

As you can see in our code, I've added some wrapper structs to Lighthouse and made my own custom implementations. It would be great if these were included in the library by default.

If the implementations I've used (see previous link) are good, I'm happy to make a PR to this repository. However I suspect that you might know faster or more elegant ways to achieve these things.

Fp2 Sqrt missmatch

I have tried to integrate blst_fp2_sqrt into blstrs, but have run into an issue with this test case:

https://github.com/filecoin-project/blstrs/blob/master/src/fp2.rs#L935-L978

It fails with

left: `Fp2 {
  c0: Fp(0x090a7bae7eacfad4c30069b48d39ec66d6f82c12b68250ebfa02f6bba490b7a1afb4216bc88d749c794c664d8fbd51e6),
  c1: Fp(0x112941eaa55e8369a6526cae32ee3b2df8f2209a00d547a43e8ec2f2249f063ca83ba6b84bec9bb7f965acb03df5c359)
  }`,
right: `Fp2 {
  c0: Fp(0x10f6963bbad2ebc5881b3e01b611c0708d7f1f723d02c1d36d2ddbe552203e826ef7de92e8c68b6340b299b2704258c5),
  c1: Fp(0x08d7cfff94216330a4c93b08105d71a96b852aeaf2afcb1b28a20faed211efe77670594665676447c099534fc209e752)
  }`', src/fp2.rs:946:9

all other test cases pass strangely enough.

Point Decompression does not handle invalid byte lengths

What is the issue?

The rust bindings uncompress() and deserialize() for each point object do not ensure the correct number of bytes are supplied before calling.

This is an issue if someone calls uncompress(&[]) with an empty array. The c code assumes it was passed a 48 byte array and will read the next sections of memory.

What needs to be done?

I think this will have to be checked in the rust uncompress() / deserialize() functions.

For uncompress() maybe something along the lines of pk_comp.len() == $pk_comp_size.
It's generally safe to do a strict check on length to prevent signature malleability by appending bytes.

A little more challenging for deserialize() as we have to handle the compressed and uncompressed byte lengths. But a check of the compression bit should do the trick.

wasm32 support

As of time of writing, polkadot's substrate does not use any impl of BLS, since a part of runtime is compiled to wasm and current bls crates are to slow for it.

Do you have some plans to add support for wasm target in clang?

[Optim] Square root on Fp2

Is the addition chain to exponentiate by a^((p^2-9)/16) faster than the method mentioned in

Adj, G. and F. Rodriguez-Henriquez, "Square Root Computation over Even Extension Fields",
DOI 10.1109/TC.2013.145, pages 2829-2841, In IEEE
Transactions on Computers. vol 63 issue 11, November 2014,
https://doi.org/10.1109/TC.2013.145.
https://eprint.iacr.org/2012/685.pdf

image

In Nim, assuming we have sqrt_invsqrt which returns both the sqrt and inverse sqrt on Fp

func sqrt_if_square*(a: var QuadraticExt): SecretBool =
  ## If ``a`` is a square, compute the square root of ``a``
  ## if not, ``a`` is unmodified.
  ##
  ## The square root, if it exist is multivalued,
  ## i.e. both xยฒ == (-x)ยฒ
  ## This procedure returns a deterministic result
  #
  # Implementation via the complex method (which confusingly does not require a complex field)
  # We make it constant-time via conditional copies

  mixin fromComplexExtension # TODO: relax this
  static: doAssert a.fromComplexExtension()

  var t1{.noInit.}, t2{.noInit.}, t3{.noInit.}: typeof(a.c0)

  t1.square(a.c0) #     a0ยฒ
  t2.square(a.c1) # - ฮฒ a1ยฒ with ฮฒ = ๐‘–ยฒ in a complex extension field

  t1 += t2        # a0 - (-1) a1ยฒ
  result = t1.sqrt_if_square()

  t2.sum(a.c0, t1)
  t2.div2()

  t3.diff(a.c0, t1)
  t3.div2()

  let quadResidTest = t2.isSquare()
  t2.ccopy(t3, not quadResidTest)

  sqrt_invsqrt(sqrt = t1, invsqrt = t3, t2)
  a.c0.ccopy(t1, result)

  t3.div2()
  t3 *= a.c1
  a.c1.ccopy(t3, result)

Running in ARM64 Fails with SIGILL: illegal instruction

This has been reported by a few of our users prysmaticlabs/prysm#7312 . We just released a new release of our client with support for blst. However a few users running on ARM64 have failed with the above error and also a user running on debian 10 (x86_64) have also reported getting the above error.

Below is an example snapshot of the stack trace.

SIGILL: illegal instruction
PC=0x146f2a1 m=3 sigcode=2

goroutine 0 [idle]:
runtime: unknown pc 0x146f2a1
stack: frame={sp:0x7f8db214ecf0, fp:0x0} stack=[0x7f8db194f288,0x7f8db214ee88)
00007f8db214ebf0:  000000000044d420 <runtime.(*pageAlloc).update+1296>  00007f8db2963e00 
00007f8db214ec00:  000000000000000d  00007f8db214ed38 
00007f8db214ec10:  000000000048c991 <runtime.goexit+1>  00000000000eaf57 
00007f8db214ec20:  00000000013df594 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).Start+5236>  000008f800aec26f 
00007f8db214ec30:  00000000013db920 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).processFetchedData+1088>  ffffffff00aeae53 
00007f8db214ec40:  00000000013da864 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).roundRobinSync+1124>  ffffffff00aeab55 
00007f8db214ec50:  00000000013df593 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).Start+5235>  ffffffff00aeca1a 
00007f8db214ec60:  0000000000000000  0000000000000000 
00007f8db214ec70:  00000000013da865 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).roundRobinSync+1125>  0000070000aea68a 
00007f8db214ec80:  00000000013dda36 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).processBatchedBlocks+1942>  ffffffff00aebd4e 
00007f8db214ec90:  0000000001013f0a <github.com/prysmaticlabs/prysm/beacon-chain/core/state.ExecuteStateTransitionNoVerifyAnySig+458>  ffffffff008776b6 
00007f8db214eca0:  0000000000b9460d <github.com/prysmaticlabs/prysm/beacon-chain/state.NewFieldTrie+877>  000000c00055156f 
00007f8db214ecb0:  0000000001015139 <github.com/prysmaticlabs/prysm/beacon-chain/core/state.ProcessSlots+937>  ffffffff008780e7 
00007f8db214ecc0:  0000000000000000  0000000000000000 
00007f8db214ecd0:  000000000101486d <github.com/prysmaticlabs/prysm/beacon-chain/core/state.ProcessSlot+461>  ffffffff00877beb 
00007f8db214ece0:  0000000000431b59 <runtime.profilealloc+89>  00000018000ab8b0 
00007f8db214ecf0: <89f3fffcfffcfffd  000000000146ccd7 
00007f8db214ed00:  0000000000b9460c <github.com/prysmaticlabs/prysm/beacon-chain/state.NewFieldTrie+876>  00007f8db214eda0 
00007f8db214ed10:  00007f8db214ed70  0000000001d4f400 
00007f8db214ed20:  0000000000000080  000000c00c29ba40 
00007f8db214ed30:  00007f8db214ee00  0000000001441333 
00007f8db214ed40:  07d369807fd6a51e  5ce681b849ad9b70 
00007f8db214ed50:  350427e9f5d63260  ddf4455750c7b9ff 
00007f8db214ed60:  9c7e600381e7002a  00bdb40b883e391c 
00007f8db214ed70:  07d369807fd6a51e  5ce681b849ad9b70 
00007f8db214ed80:  350427e9f5d63260  ddf4455750c7b9ff 
00007f8db214ed90:  9c7e600381e7002a  00bdb40b883e391c 
00007f8db214eda0:  0000000002a6b408  00007f8da84751a8 
00007f8db214edb0:  0000000000000001  00007f8da84751a8 
00007f8db214edc0:  0000000000000000  000000c016f7c000 
00007f8db214edd0:  00007f8db214ee18  000000c0116f3fb8 
00007f8db214ede0:  ffffffffffffffff  000000c0116f6000 
runtime: unknown pc 0x146f2a1
stack: frame={sp:0x7f8db214ecf0, fp:0x0} stack=[0x7f8db194f288,0x7f8db214ee88)
00007f8db214ebf0:  000000000044d420 <runtime.(*pageAlloc).update+1296>  00007f8db2963e00 
00007f8db214ec00:  000000000000000d  00007f8db214ed38 
00007f8db214ec10:  000000000048c991 <runtime.goexit+1>  00000000000eaf57 
00007f8db214ec20:  00000000013df594 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).Start+5236>  000008f800aec26f 
00007f8db214ec30:  00000000013db920 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).processFetchedData+1088>  ffffffff00aeae53 
00007f8db214ec40:  00000000013da864 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).roundRobinSync+1124>  ffffffff00aeab55 
00007f8db214ec50:  00000000013df593 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).Start+5235>  ffffffff00aeca1a 
00007f8db214ec60:  0000000000000000  0000000000000000 
00007f8db214ec70:  00000000013da865 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).roundRobinSync+1125>  0000070000aea68a 
00007f8db214ec80:  00000000013dda36 <github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync.(*Service).processBatchedBlocks+1942>  ffffffff00aebd4e 
00007f8db214ec90:  0000000001013f0a <github.com/prysmaticlabs/prysm/beacon-chain/core/state.ExecuteStateTransitionNoVerifyAnySig+458>  ffffffff008776b6 
00007f8db214eca0:  0000000000b9460d <github.com/prysmaticlabs/prysm/beacon-chain/state.NewFieldTrie+877>  000000c00055156f 
00007f8db214ecb0:  0000000001015139 <github.com/prysmaticlabs/prysm/beacon-chain/core/state.ProcessSlots+937>  ffffffff008780e7 
00007f8db214ecc0:  0000000000000000  0000000000000000 
00007f8db214ecd0:  000000000101486d <github.com/prysmaticlabs/prysm/beacon-chain/core/state.ProcessSlot+461>  ffffffff00877beb 
00007f8db214ece0:  0000000000431b59 <runtime.profilealloc+89>  00000018000ab8b0 
00007f8db214ecf0: <89f3fffcfffcfffd  000000000146ccd7 
00007f8db214ed00:  0000000000b9460c <github.com/prysmaticlabs/prysm/beacon-chain/state.NewFieldTrie+876>  00007f8db214eda0 
00007f8db214ed10:  00007f8db214ed70  0000000001d4f400 
00007f8db214ed20:  0000000000000080  000000c00c29ba40 
00007f8db214ed30:  00007f8db214ee00  0000000001441333 
00007f8db214ed40:  07d369807fd6a51e  5ce681b849ad9b70 
00007f8db214ed50:  350427e9f5d63260  ddf4455750c7b9ff 
00007f8db214ed60:  9c7e600381e7002a  00bdb40b883e391c 
00007f8db214ed70:  07d369807fd6a51e  5ce681b849ad9b70 
00007f8db214ed80:  350427e9f5d63260  ddf4455750c7b9ff 
00007f8db214ed90:  9c7e600381e7002a  00bdb40b883e391c 
00007f8db214eda0:  0000000002a6b408  00007f8da84751a8 
00007f8db214edb0:  0000000000000001  00007f8da84751a8 
00007f8db214edc0:  0000000000000000  000000c016f7c000 
00007f8db214edd0:  00007f8db214ee18  000000c0116f3fb8 
00007f8db214ede0:  ffffffffffffffff  000000c0116f6000 

goroutine 248 [syscall]:
runtime.cgocall(0x143df10, 0xc0116f3fb8, 0x4b65ab3d1e582b89)
	GOROOT/src/runtime/cgocall.go:133 +0x5b fp=0xc0116f3f88 sp=0xc0116f3f50 pc=0x427acb
github.com/supranational/blst/bindings/go._Cfunc_blst_p1_uncompress(0xc00c29ba40, 0xc0164d0750, 0xc000000000)
	_cgo_gotypes.go:520 +0x4d fp=0xc0116f3fb8 sp=0xc0116f3f88 pc=0xbadbbd
github.com/supranational/blst/bindings/go.(*_Ctype_struct___4).Uncompress(0xc00c29ba40, 0xc0164d0750, 0x30, 0x30, 0x0)
	blst.go:1392 +0x48 fp=0xc0116f3fe0 sp=0xc0116f3fb8 pc=0xbb3cd8
github.com/prysmaticlabs/prysm/shared/bls/blst.PublicKeyFromBytes(0xc0164d0750, 0x30, 0x30, 0xc00c0dce00, 0x1c, 0x8, 0xc000074700)
	shared/bls/blst/public_key.go:39 +0x1d2 fp=0xc0116f40d0 sp=0xc0116f3fe0 pc=0xbb8882
github.com/prysmaticlabs/prysm/shared/bls.PublicKeyFromBytes(0xc0164d0750, 0x30, 0x30, 0xc00c0dce00, 0x20, 0xc018cef140, 0xc0116f41f4)
	shared/bls/bls.go:24 +0x70 fp=0xc0116f4168 sp=0xc0116f40d0 pc=0xbcc010
github.com/prysmaticlabs/prysm/beacon-chain/core/helpers.RetrieveBlockSignatureSet(0xc0089259d0, 0xc0164d0750, 0x30, 0x30, 0xc009ca64e0, 0x60, 0x60, 0xc018cef100, 0x20, 0x20, ...)

This fails the moment we decompress a pubkey in the cgo call.

The provided ARM64 binary is compiled on a host linux x86_64 system using these instructions:
https://github.com/prysmaticlabs/prysm/blob/master/third_party/blst/blst.BUILD#L12

In line with what was used over here:
https://github.com/supranational/blst/blob/master/bindings/go/blst.go#L13

Are there any other flags we might be missing here ?

They were all running the commit from here:

d75dab4

This commit is about a month back, so was wondering if it might already be fixed in master

Type mismatches in exports and headers

The header file that describes the function uses a different type than the actual implementation - this may lead to miscompiles / optimization errors as there may be subtle differences between bool and limb_t.

bool blst_fp12_is_equal(const blst_fp12 *a, const blst_fp12 *b);

limb_t blst_p1_affine_is_equal(const POINTonE1_affine *a,

blst/bindings/blst_aux.h:17:6: warning: type of โ€˜blst_p1_affine_is_equalโ€™ does not match original declaration [-Wlto-type-mismatch]
   17 | bool blst_p1_affine_is_equal(const blst_p1_affine *a, const blst_p1_affine *b);
      |      ^
blst/src/exports.c:241:8: note: return value type mismatch
  241 | limb_t blst_p1_affine_is_equal(const POINTonE1_affine *a,
      |        ^
blst/src/exports.c:241:8: note: type โ€˜limb_tโ€™ should match type โ€˜_Boolโ€™
blst/src/exports.c:241:8: note: โ€˜blst_p1_affine_is_equalโ€™ was previously declared here
blst/src/exports.c:241:8: note: code may be misoptimized unless โ€˜-fno-strict-aliasingโ€™ is used

missing methods proposed by the README.md when used in hello-word app with go 1.16

I tried to import this as a go module, but it could not find some methods.

For example blst.P1Affine is missing the "From" method and blst.P2Affine is missing the "Sign" method.

So then I decided to see if the blst.go file was outdated, therefore I cloned this repo,
run go get golang.org/x/tools/cmd/goimports
run .generate.py

And there I noticed that blst.go is also failing with many missing methods for the types declared, for example:
sk.Zeroize undefined (type *_Ctype_struct___6 has no field or method Zeroize)compilerMissingFieldOrMethod

Is there something else I'm missing to use the example from the README.md ?

EIP-2333

This is just a question.

The KeyGen function directly derive a secretKey from a seed and optional parameters. I guess this might be compliant with EIP-2333, but not very sure.

Would anyone please confirm it does, or how we derive masterKey and child keys with the provided functions? Thanks.

[Optim] Accelerated scalar multiplication

Following our exchanges, you can accelerate the scalar multiplication via:

  • GLV endomorphism on G1, which divides the number of doubling by 2.
  • GLV endomorphism + GLS endomorphism on G2 which divides the number of doublings by 4.

Method 1 has a patent that expires on September 2020.

References

Implementation follow closely Algorithm 1 and 2 from paper

  • Efficient and Secure Algorithms for GLV-Based Scalar
    Multiplication and their Implementation on GLV-GLS
    Curves (Extended Version)
    Armando Faz-Hernaฬndez, Patrick Longa, Ana H. Saฬnchez, 2013
    https://eprint.iacr.org/2013/158.pdf

The Lattice decompositions for BN and BLS curve families follow chapter 6 from

  • Guide to Pairing-based Cryptography
    Chapter 6: Scalar Multiplication and Exponentiation in Pairing Groups
    Joppe Bos, Craig Costello, Michael Naehrig

Extra

The FourQ draft also mentions this: https://tools.ietf.org/html/draft-ladd-cfrg-4q-00#section-4.3

Implementation

Variable point

For variable point, on G1, we can accelerate via an efficient endomorphism, field multiplication by a cube root of unity:

For variable point, on G2 you can combine the cube root of unity endomorphism with the Frobenius endomorphism to divide by 4 the number of doubling.
I think only MCL and MIRACL are using those at the moment.

The decomposition lattice is available in the guide to pairing based cryptography. I also have sage scripts for G1 decomposition for vectors (incomplete, the last assert fails even though in my production code it's working so I probably have bit issues with Python):

Fixed points like generators

The paper mentions LSB Set decomposition has being more efficient if the point is known at compile-time. CIRCL and Snowshoe also implement this technique.

core_verify_pk_in_g1 fails to verify valid signature

Didn't found any tests on core_verify_pk_in_g1 function and thought it probably could be a library bug.

PrivateKey (bigendian serialized) = 0x2793e28525ec30c29f3ff05f9ebd5449c79f180c442496ccef9294bd9850662c

Public key (compressed p1_affine) = 0xab10fc693d038b73d67279127501a05f0072cbb7147c68650ef6ac4e0a413e5cabd1f35c8711e1f7d9d885bbc3b8eddc

Message = 0x0000000000000000000000000000000000000000000000000000000000000000

Message hash (compressed p2_affine, DST=0x424c535f5349475f424c53313233383147325f584d443a5348412d3235365f535357555f524f5f504f505f , aug =[]): 
0x97502412bcfc3f1d88b71f1ad9b60fa37c332d19466fba1dc991d42bcd09bcd9f1c22a562646ffce0922793b6c69938b076e5cd6cfb3c361fc767e5f40ce05486e1668825ffeecab89d7daa455a179736a387ae93b9b15d283d45ffa14cd4af7

Signature (compressed p2_affine) = 0xa44158c08c8c584477770feec2afa24d5a0b0bab2800414cb9efbb37c40339b6318c9349dad8de27ae644376d71232580ff5102c7a8579a6d2627c6e40b0ced737a60c66c7ebd377c04bf5ac957bf05bc8b6b09fbd7bdd2a7fa1090b5a0760bb

Just compare all the values to the current Java Milagro library and all of them are the same, but Milagro verifies the signature while core_verify_pk_in_g1 doesn't. The signature has the same value when signing by both our current Milagro implementation and by Blst based code.

Would be super if you could check this case. Any other help in finding the root cause is also much appreciated!

[$] Enable and optimize for Linux on Z (s390x)

Blst currently supports x86_64 and ARMv8 through the asm routines. This is a feature request to add asm routines to enable Blst for the IBMz aka s390x architecture and demonstrate appropriate, good performance.
A financial bounty from IBM is open for discussion.

Unable to compile with instrumentation since recent commit

export CC="clang"
export CFLAGS="-fsanitize=fuzzer-no-link"
git clone --depth 1 https://github.com/supranational/blst
cd blst/
./build.sh
echo -e "#include \"bindings/blst.h\"\n int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) { blst_fp12_one(); return 0; }" >f.c
$CC $CFLAGS -fsanitize=fuzzer f.c libblst.a

This used to work but since commit 54e2be4 this now produces many errors such as:

libblst.a(blst.o):(.data._ZN11__sanitizer15IOCTL_KDGKBSENTE+0x0): multiple definition of `__sanitizer::IOCTL_KDGKBSENT'
/usr/lib/llvm-11/lib/clang/11.1.0/lib/linux/libclang_rt.ubsan_standalone-x86_64.a(sanitizer_platform_limits_posix.cpp.o):(.data._ZN11__sanitizer15IOCTL_KDGKBSENTE+0x0): first defined here
libblst.a(blst.o): In function `__sanitizer::StartReportDeadlySignal()':
(.text._ZN11__sanitizer23StartReportDeadlySignalEv+0x0): multiple definition of `__sanitizer::StartReportDeadlySignal()'
/usr/lib/llvm-11/lib/clang/11.1.0/lib/linux/libclang_rt.ubsan_standalone-x86_64.a(sanitizer_symbolizer_report.cpp.o):(.text._ZN11__sanitizer23StartReportDeadlySignalEv+0x0): first defined here
libblst.a(blst.o): In function `__sanitizer::SetAlternateSignalStack()':
(.text._ZN11__sanitizer23SetAlternateSignalStackEv+0x0): multiple definition of `__sanitizer::SetAlternateSignalStack()'
/usr/lib/llvm-11/lib/clang/11.1.0/lib/linux/libclang_rt.ubsan_standalone-x86_64.a(sanitizer_posix_libcdep.cpp.o):(.text._ZN11__sanitizer23SetAlternateSignalStackEv+0x0): first defined here
libblst.a(blst.o): In function `__sanitizer::ThreadRegistry::JoinThread(unsigned int, void*)':
(.text._ZN11__sanitizer14ThreadRegistry10JoinThreadEjPv+0x0): multiple definition of `__sanitizer::ThreadRegistry::JoinThread(unsigned int, void*)'
/usr/lib/llvm-11/lib/clang/11.1.0/lib/linux/libclang_rt.ubsan_standalone-x86_64.a(sanitizer_thread_registry.cpp.o):(.text._ZN11__sanitizer14ThreadRegistry10JoinThreadEjPv+0x0): first defined here

Is there anything we can do about this?

GCC optimization flag incompatibility

FYI, BLST is incompatible with the following GCC flag: -ftree-loop-vectorize

This causes the scalar multiplication to miscompile and easily noticeable on blst_sk_to_pk_in_g1 function.

Unfortunately it is automatically activated with -O3. You might want to have a note about not compiling with -O3 or using -fno-tree-loop-vectorize to deactivate the offending flag.

Tested with GCC v10.1.0

Clang works fine (v10.0.1)

Sagnificant performance degradation for aggregate method in jblst

Sagnificant performance degradation for aggregate method in jblst.

This was noticed while benchmark tests for BLS aggregation method in jblst. The library from v0.1.0-RELEASE showed ~150MB/sec performance on my 6 core Rysen 5. I decided to upgrade to the latest jblst v 0.3.3-1. After this the same test showed ~3.5MB/sec. The benchmark test is published in github repo here: https://github.com/RiV-chain/riv-benchmark/blob/main/src/main/java/org/riv/SigningTest.java#L29

I could find the part of Java code and compare what difference in the native methods invokation:

v0.1.0-RELEASE

  public static BlstSignature aggregate(List<BlstSignature> signatures) {
    List<BlstSignature> finiteSignatures =
        signatures.stream().filter(sig -> !sig.isInfinity()).collect(Collectors.toList());

    Optional<BlstSignature> invalidSignature =
        finiteSignatures.stream().filter(s -> !s.isValid).findFirst();
    if (invalidSignature.isPresent()) {
      throw new IllegalArgumentException(
          "Can't aggregate invalid signature: " + invalidSignature.get());
    }

    p2 sum = new p2();
    try {
      blst.p2_from_affine(sum, finiteSignatures.get(0).ec2Point);
      for (int i = 1; i < finiteSignatures.size(); i++) {
        blst.p2_add_affine(sum, sum, finiteSignatures.get(i).ec2Point);
      }
      p2_affine res = new p2_affine();
      blst.p2_to_affine(res, sum);

      return new BlstSignature(res, true);
    } finally {
      sum.delete();
    }
  }

v0.3.3-1

  public static BlstSignature aggregate(List<BlstSignature> signatures) {

    Optional<BlstSignature> invalidSignature =
        signatures.stream().filter(s -> !s.isValid).findFirst();
    if (invalidSignature.isPresent()) {
      throw new IllegalArgumentException(
          "Can't aggregate invalid signature: " + invalidSignature.get());
    }

    P2 sum = new P2();
    for (BlstSignature finiteSignature : signatures) {
      sum.aggregate(finiteSignature.ec2Point);
    }

    return new BlstSignature(sum.to_affine(), true);
  }

[Optim] Runtime detection of MULX and ADX support

Given the significant speed increase (~20% for high level signing/verifying) provided by BMI2 and ADX support (for MULX, ADCX, ADOX instructions) (bench: status-im/nim-blst#1)
It would probably worthwhile to autodetect CPU support for those instructions at runtime.
This is especially interesting because the CPUs are now widespread (Broadwell, 2015 for Intel and Ryzen 2017 for AMD).

Cloudflare BN256 does that for example https://github.com/cloudflare/bn256/blob/3cac37b6/gfp_amd64.s#L108-L129

DTS as std::string in CPP binding

Throughout CPP API the DST is defined as const std::string
Was it done intentionally?
Cause C API defines it as const byte* and the spec also defines it as octet string:

   Domain separation is enforced with a domain separation tag (DST),
   which is an octet string.

Linking errors on aarch64

When cross-compiling for aarch64 from x86_64, I'm receiving a linking error about missing functions (below).

I'm using a commit descended from 5c41509, specifically the head of #26

Compiling in portable mode resolves the issue (as the polyfills are used instead).

note: /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_affine_Serialize_BE':
          server.c:(.text.POINTonE1_affine_Serialize_BE+0x50): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE1_affine_Serialize_BE+0xa0): undefined reference to `fromx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `reciprocal_fp':
          server.c:(.text.reciprocal_fp+0x98): undefined reference to `sqrx_mont_384'
          server.c:(.text.reciprocal_fp+0xc4): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0xe4): undefined reference to `sqrx_mont_384'
          server.c:(.text.reciprocal_fp+0x108): undefined re```ference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x130): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x154): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x184): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x1a8): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.reciprocal_fp+0x1d4): more undefined references to `mulx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `reciprocal_fp':
          server.c:(.text.reciprocal_fp+0x2ac): undefined reference to `sqrx_mont_384'
          server.c:(.text.rec<details><summary>Backtrace</summary>
<p>
<code>iprocal_fp+0x2d0): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x2f4): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x318): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp+0x340): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.reciprocal_fp+0x368): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.reciprocal_fp+0x390): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.reciprocal_fp+0x3b8): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.reciprocal_fp+0x3e0): undefined reference to `sqrx_n_mul_mont_383'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.reciprocal_fp+0x408): more undefined references to `sqrx_n_mul_mont_383' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `recip_sqrt_fp_3mod4':
          server.c:(.text.recip_sqrt_fp_3mod4+0x98): undefined reference to `sqrx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0xc8): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0xe8): undefined reference to `sqrx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x10c): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x134): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x158): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x188): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x1ac): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.recip_sqrt_fp_3mod4+0x1d8): more undefined references to `mulx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `recip_sqrt_fp_3mod4':
          server.c:(.text.recip_sqrt_fp_3mod4+0x2b0): undefined reference to `sqrx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x2d4): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x2f8): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x31c): undefined reference to `mulx_mont_384'
          server.c:(.text.recip_sqrt_fp_3mod4+0x344): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.recip_sqrt_fp_3mod4+0x36c): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.recip_sqrt_fp_3mod4+0x394): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.recip_sqrt_fp_3mod4+0x3bc): undefined reference to `sqrx_n_mul_mont_383'
          server.c:(.text.recip_sqrt_fp_3mod4+0x3e4): undefined reference to `sqrx_n_mul_mont_383'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.recip_sqrt_fp_3mod4+0x40c): more undefined references to `sqrx_n_mul_mont_383' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `recip_sqrt_fp_3mod4':
          server.c:(.text.recip_sqrt_fp_3mod4+0xda0): undefined reference to `sqrx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sqrt_fp':
          server.c:(.text.sqrt_fp+0x68): undefined reference to `mulx_mont_384'
          server.c:(.text.sqrt_fp+0x88): undefined reference to `sqrx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_fp_times_Zz':
          server.c:(.text.map_fp_times_Zz+0x70): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sigma':
          server.c:(.text.sigma+0x34): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `line_by_Px2':
          server.c:(.text.line_by_Px2+0x44): undefined reference to `mulx_mont_384'
          server.c:(.text.line_by_Px2+0x60): undefined reference to `mulx_mont_384'
          server.c:(.text.line_by_Px2+0x78): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.line_by_Px2+0x9c): more undefined references to `mulx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_affine_Compress_BE':
          server.c:(.text.POINTonE1_affine_Compress_BE+0x48): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE1_affine_Compress_BE+0x90): undefined reference to `sgn0x_pty_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_fp':
          server.c:(.text.map_fp+0x64): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `isogeny_map_to_E1':
          server.c:(.text.isogeny_map_to_E1+0x7c): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0xa4): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0xc8): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0xe8): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x110): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x130): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x158): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x180): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x1a8): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x1c8): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x1f0): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x210): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x238): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x258): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x288): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x2d0): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x378): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x3b4): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x404): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.isogeny_map_to_E1+0x474): more undefined references to `mulx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `isogeny_map_to_E1':
          server.c:(.text.isogeny_map_to_E1+0x528): undefined reference to `sqrx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x54c): undefined reference to `mulx_mont_384'
          server.c:(.text.isogeny_map_to_E1+0x570): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_Uncompress':
          server.c:(.text.POINTonE1_Uncompress+0x1a0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_Uncompress+0x1c0): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_Uncompress+0x1e4): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_Uncompress+0x24c): undefined reference to `sgn0x_pty_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `reciprocal_fp2':
          server.c:(.text.reciprocal_fp2+0x60): undefined reference to `sqrx_mont_384'
          server.c:(.text.reciprocal_fp2+0x80): undefined reference to `sqrx_mont_384'
          server.c:(.text.reciprocal_fp2+0xc8): undefined reference to `mulx_mont_384'
          server.c:(.text.reciprocal_fp2+0xec): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_double':
          server.c:(.text.POINTonE1_double+0x60): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_double+0x8c): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_double+0xac): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_double+0xe4): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_double+0x150): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_double+0x1b4): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_double+0x1fc): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_add':
          server.c:(.text.POINTonE1_add+0x7c): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add+0xa0): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add+0xcc): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x100): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x130): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x15c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x184): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.POINTonE1_add+0x1b0): more undefined references to `mulx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_add':
          server.c:(.text.POINTonE1_add+0x200): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add+0x228): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x280): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x2a0): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add+0x318): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x340): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add+0x39c): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add+0x3e8): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_dadd':
          server.c:(.text.POINTonE1_dadd+0x94): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd+0xd8): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd+0xf8): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x11c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x14c): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x178): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x1c0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x1e8): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x20c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x230): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.POINTonE1_dadd+0x254): more undefined references to `mulx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_dadd':
          server.c:(.text.POINTonE1_dadd+0x334): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x358): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x37c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x3a0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x3c4): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x3e4): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x430): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd+0x468): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `hash_to_field':
          server.c:(.text.hash_to_field+0x3b0): undefined reference to `redcx_mont_384'
          server.c:(.text.hash_to_field+0x3cc): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_affine_Serialize_BE':
          server.c:(.text.POINTonE2_affine_Serialize_BE+0x54): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE2_affine_Serialize_BE+0xa4): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE2_affine_Serialize_BE+0xf4): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE2_affine_Serialize_BE+0x148): undefined reference to `fromx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_fp2_times_Zz':
          server.c:(.text.map_fp2_times_Zz+0x70): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `qi_x_iwsc':
          server.c:(.text.qi_x_iwsc+0x50): undefined reference to `mulx_mont_384x'
          server.c:(.text.qi_x_iwsc+0x68): undefined reference to `mulx_mont_384'
          server.c:(.text.qi_x_iwsc+0x80): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `qi_y_iwsc':
          server.c:(.text.qi_y_iwsc+0x60): undefined reference to `mulx_mont_384x'
          server.c:(.text.qi_y_iwsc+0xb8): undefined reference to `mulx_mont_384'
          server.c:(.text.qi_y_iwsc+0xdc): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `psi':
          server.c:(.text.psi+0x68): undefined reference to `sqrx_mont_384x'
          server.c:(.text.psi+0x90): undefined reference to `mulx_mont_384x'
          server.c:(.text.psi+0xc4): undefined reference to `mulx_mont_384x'
          server.c:(.text.psi+0x108): undefined reference to `mulx_mont_384x'
          server.c:(.text.psi+0x138): undefined reference to `mulx_mont_384x'
          server.c:(.text.psi+0x15c): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.psi+0x184): more undefined references to `mulx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `psi':
          server.c:(.text.psi+0x1a4): undefined reference to `sqrx_mont_384x'
          server.c:(.text.psi+0x1c8): undefined reference to `mulx_mont_384x'
          server.c:(.text.psi+0x1ec): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_affine_Compress_BE':
          server.c:(.text.POINTonE2_affine_Compress_BE+0x54): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE2_affine_Compress_BE+0xa4): undefined reference to `fromx_mont_384'
          server.c:(.text.POINTonE2_affine_Compress_BE+0xf0): undefined reference to `sgn0x_pty_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_affine_on_curve':
          server.c:(.text.POINTonE2_affine_on_curve+0x58): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_affine_on_curve+0x7c): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_affine_on_curve+0xb4): undefined reference to `sqrx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_Deserialize_BE':
          server.c:(.text.POINTonE2_Deserialize_BE+0x2a8): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE2_Deserialize_BE+0x2cc): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE2_Deserialize_BE+0x2f0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE2_Deserialize_BE+0x314): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_fp2':
          server.c:(.text.map_fp2+0x64): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sqr_n_mul_fp2':
          server.c:(.text.sqr_n_mul_fp2+0x4c): undefined reference to `sqrx_mont_382x'
          server.c:(.text.sqr_n_mul_fp2+0x8c): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `recip_sqrt_fp2_9mod16':
          server.c:(.text.recip_sqrt_fp2_9mod16+0x98): undefined reference to `sqrx_mont_384x'
          server.c:(.text.recip_sqrt_fp2_9mod16+0xd0): undefined reference to `mulx_mont_384x'
          server.c:(.text.recip_sqrt_fp2_9mod16+0xf4): undefined reference to `mulx_mont_384x'
          server.c:(.text.recip_sqrt_fp2_9mod16+0x118): undefined reference to `mulx_mont_384x'
          server.c:(.text.recip_sqrt_fp2_9mod16+0x13c): undefined reference to `mulx_mont_384x'
          server.c:(.text.recip_sqrt_fp2_9mod16+0x160): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.recip_sqrt_fp2_9mod16+0x184): more undefined references to `mulx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_add':
          server.c:(.text.POINTonE2_add+0x7c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add+0xa0): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add+0xcc): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x100): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x130): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x15c): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x184): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.POINTonE2_add+0x1b0): more undefined references to `mulx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_add':
          server.c:(.text.POINTonE2_add+0x200): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add+0x228): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x280): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x2a0): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add+0x318): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x340): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add+0x39c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add+0x3e8): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `line_add':
          server.c:(.text.line_add+0x7c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_add+0xac): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0xdc): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x100): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x140): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_add+0x194): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x1f4): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x214): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_add+0x278): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x2b4): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x314): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_add+0x364): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_add+0x38c): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_dadd':
          server.c:(.text.POINTonE2_dadd+0x94): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0xd8): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0xf8): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x11c): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x14c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x178): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x1c0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x1e8): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x20c): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x230): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.POINTonE2_dadd+0x254): more undefined references to `mulx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_dadd':
          server.c:(.text.POINTonE2_dadd+0x334): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x358): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x37c): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x3a0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x3c4): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x3e4): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x430): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd+0x468): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_double':
          server.c:(.text.POINTonE2_double+0x60): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_double+0x8c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_double+0xac): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_double+0xe4): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_double+0x150): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_double+0x1b4): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_double+0x1fc): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `line_dbl':
          server.c:(.text.line_dbl+0x78): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_dbl+0xa8): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_dbl+0xd4): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_dbl+0xfc): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_dbl+0x130): undefined reference to `sqrx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.line_dbl+0x1a8): more undefined references to `sqrx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `line_dbl':
          server.c:(.text.line_dbl+0x294): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_dbl+0x2c8): undefined reference to `sqrx_mont_384x'
          server.c:(.text.line_dbl+0x358): undefined reference to `mulx_mont_384x'
          server.c:(.text.line_dbl+0x37c): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `frobenius_map_fp6':
          server.c:(.text.frobenius_map_fp6+0xf0): undefined reference to `mulx_mont_384x'
          server.c:(.text.frobenius_map_fp6+0x120): undefined reference to `mulx_mont_384'
          server.c:(.text.frobenius_map_fp6+0x158): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `frobenius_map_fp12':
          server.c:(.text.frobenius_map_fp12+0x78): undefined reference to `mulx_mont_384x'
          server.c:(.text.frobenius_map_fp12+0x90): undefined reference to `mulx_mont_384x'
          server.c:(.text.frobenius_map_fp12+0xb8): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_from_Jacobian':
          server.c:(.text.POINTonE2_from_Jacobian+0x8c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_from_Jacobian+0xb0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_from_Jacobian+0xd4): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_from_Jacobian+0xf8): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_from_Jacobian':
          server.c:(.text.POINTonE1_from_Jacobian+0x8c): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_from_Jacobian+0xb0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_from_Jacobian+0xd4): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_from_Jacobian+0xf8): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sqr_fp4':
          server.c:(.text.sqr_fp4+0x5c): undefined reference to `sqrx_382x'
          server.c:(.text.sqr_fp4+0x74): undefined reference to `sqrx_382x'
          server.c:(.text.sqr_fp4+0x100): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp4+0x120): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp4+0x130): undefined reference to `sqrx_382x'
          server.c:(.text.sqr_fp4+0x1a0): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp4+0x1c0): undefined reference to `redcx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sqr_fp6':
          server.c:(.text.sqr_fp6+0x64): undefined reference to `sqrx_382x'
          server.c:(.text.sqr_fp6+0x88): undefined reference to `mulx_382x'
          server.c:(.text.sqr_fp6+0xc4): undefined reference to `mulx_382x'
          server.c:(.text.sqr_fp6+0xfc): undefined reference to `sqrx_382x'
          server.c:(.text.sqr_fp6+0x140): undefined reference to `sqrx_382x'
          server.c:(.text.sqr_fp6+0x214): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp6+0x234): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp6+0x2a8): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp6+0x2c8): undefined reference to `redcx_mont_384'
          server.c:(.text.sqr_fp6+0x344): undefined reference to `redcx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.sqr_fp6+0x364): more undefined references to `redcx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `mul_by_xy0_fp6x2':
          server.c:(.text.mul_by_xy0_fp6x2+0x5c): undefined reference to `mulx_382x'
          server.c:(.text.mul_by_xy0_fp6x2+0x80): undefined reference to `mulx_382x'
          server.c:(.text.mul_by_xy0_fp6x2+0x9c): undefined reference to `mulx_382x'
          server.c:(.text.mul_by_xy0_fp6x2+0x148): undefined reference to `mulx_382x'
          server.c:(.text.mul_by_xy0_fp6x2+0x1bc): undefined reference to `mulx_382x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.mul_by_xy00z0_fp12+0x74): more undefined references to `mulx_382x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `mul_by_xy00z0_fp12':
          server.c:(.text.mul_by_xy00z0_fp12+0x2b0): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_by_xy00z0_fp12+0x2d0): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_by_xy00z0_fp12+0x2f0): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_by_xy00z0_fp12+0x310): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_by_xy00z0_fp12+0x330): undefined reference to `redcx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.mul_by_xy00z0_fp12+0x350): more undefined references to `redcx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sqrt_align_fp2':
          server.c:(.text.sqrt_align_fp2+0x6c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.sqrt_align_fp2+0x2d8): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `sqrt_fp2':
          server.c:(.text.sqrt_fp2+0x5c): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_Uncompress':
          server.c:(.text.POINTonE2_Uncompress+0x224): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE2_Uncompress+0x24c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE2_Uncompress+0x26c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_Uncompress+0x290): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_Uncompress+0x2f8): undefined reference to `sgn0x_pty_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_add_affine':
          server.c:(.text.POINTonE2_add_affine+0x9c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0xc0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0xf4): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x118): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x158): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x1b4): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x210): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x238): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x298): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x2d8): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_add_affine+0x33c): undefined reference to `sqrx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_add_affine':
          server.c:(.text.POINTonE1_add_affine+0x98): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0xbc): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0xf0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x114): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x154): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x1b0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x20c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x234): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x294): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x2d4): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_add_affine+0x338): undefined reference to `sqrx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE2_dadd_affine':
          server.c:(.text.POINTonE2_dadd_affine+0x8c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0xdc): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x104): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x128): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x14c): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x1b0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x274): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x2a0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x2cc): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x2f0): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x314): undefined reference to `mulx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x338): undefined reference to `sqrx_mont_384x'
          server.c:(.text.POINTonE2_dadd_affine+0x384): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `POINTonE1_dadd_affine':
          server.c:(.text.POINTonE1_dadd_affine+0x8c): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0xdc): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x104): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x128): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x14c): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x1b0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x274): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x2a0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x2cc): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x2f0): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x314): undefined reference to `mulx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x338): undefined reference to `sqrx_mont_384'
          server.c:(.text.POINTonE1_dadd_affine+0x384): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_to_isogenous_E1':
          server.c:(.text.map_to_isogenous_E1+0x70): undefined reference to `sqrx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x98): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0xb8): undefined reference to `sqrx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x108): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x12c): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x154): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x1ec): undefined reference to `sqrx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x210): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x238): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x260): undefined reference to `sqrx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x298): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x2c0): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x2f4): undefined reference to `sqrx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x31c): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x340): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x370): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x390): undefined reference to `sqrx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x400): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x428): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x44c): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x470): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x4e4): undefined reference to `sgn0x_pty_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x504): undefined reference to `sgn0x_pty_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x540): undefined reference to `mulx_mont_384'
          server.c:(.text.map_to_isogenous_E1+0x564): undefined reference to `mulx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `mul_fp6x2':
          server.c:(.text.mul_fp6x2+0x58): undefined reference to `mulx_382x'
          server.c:(.text.mul_fp6x2+0x88): undefined reference to `mulx_382x'
          server.c:(.text.mul_fp6x2+0xb8): undefined reference to `mulx_382x'
          server.c:(.text.mul_fp6x2+0x110): undefined reference to `mulx_382x'
          server.c:(.text.mul_fp6x2+0x210): undefined reference to `mulx_382x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.mul_fp6x2+0x304): more undefined references to `mulx_382x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `mul_fp12':
          server.c:(.text.mul_fp12+0x230): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_fp12+0x250): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_fp12+0x270): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_fp12+0x290): undefined reference to `redcx_mont_384'
          server.c:(.text.mul_fp12+0x2b0): undefined reference to `redcx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.mul_fp12+0x2d0): more undefined references to `redcx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `inverse_fp12':
          server.c:(.text.inverse_fp12+0x104): undefined reference to `sqrx_mont_384x'
          server.c:(.text.inverse_fp12+0x128): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x16c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.inverse_fp12+0x1a0): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x1dc): undefined reference to `sqrx_mont_384x'
          server.c:(.text.inverse_fp12+0x208): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x240): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x26c): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x2b8): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x2f4): undefined reference to `sqrx_mont_384'
          server.c:(.text.inverse_fp12+0x31c): undefined reference to `sqrx_mont_384'
          server.c:(.text.inverse_fp12+0x374): undefined reference to `mulx_mont_384'
          server.c:(.text.inverse_fp12+0x3a0): undefined reference to `mulx_mont_384'
          server.c:(.text.inverse_fp12+0x3e0): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x40c): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x430): undefined reference to `mulx_mont_384x'
          server.c:(.text.inverse_fp12+0x464): undefined reference to `redcx_mont_384'
          server.c:(.text.inverse_fp12+0x484): undefined reference to `redcx_mont_384'
          server.c:(.text.inverse_fp12+0x4a4): undefined reference to `redcx_mont_384'
          server.c:(.text.inverse_fp12+0x4c4): undefined reference to `redcx_mont_384'
          server.c:(.text.inverse_fp12+0x4e4): undefined reference to `redcx_mont_384'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.inverse_fp12+0x504): more undefined references to `redcx_mont_384' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_to_isogenous_E2':
          server.c:(.text.map_to_isogenous_E2+0x74): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0xa0): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0xc0): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x110): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x134): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x15c): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x1fc): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x224): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x24c): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x26c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x2a4): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x2cc): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x30c): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x330): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x354): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x38c): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x3d0): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x3f8): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.map_to_isogenous_E2+0x41c): more undefined references to `mulx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_to_isogenous_E2':
          server.c:(.text.map_to_isogenous_E2+0x52c): undefined reference to `sgn0x_pty_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x54c): undefined reference to `sgn0x_pty_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x5a0): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_isogenous_E2+0x5c4): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_to_g2':
          server.c:(.text.map_to_g2+0xb0): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_g2+0xd4): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_g2+0xf8): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_g2+0x13c): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_g2+0x1f0): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_g2+0x234): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_g2+0x288): undefined reference to `mulx_mont_384x'
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o):server.c:(.text.map_to_g2+0x2f4): more undefined references to `mulx_mont_384x' follow
          /target/aarch64-unknown-linux-gnu/release/deps/libblst-4cbca568cdce9a19.rlib(server.o): In function `map_to_g2':
          server.c:(.text.map_to_g2+0x3ac): undefined reference to `sqrx_mont_384x'
          server.c:(.text.map_to_g2+0x3d4): undefined reference to `mulx_mont_384x'
          server.c:(.text.map_to_g2+0x3fc): undefined reference to `mulx_mont_384x'
          collect2: error: ld returned 1 exit status

Java binding issue with MinGW GCC on Windows

Environment: Windows, MinGW-64 GCC compiler, cygwin or msys2 shell.

When compiling blst_wrap.cpp via bindings/java/run.me the following error appears:

blst_wrap.cpp:194:21: error: 'long long long' is too long for GCC
  194 |   typedef long long __int64;

Just commenting that line in generated blst_wrap.cpp does the trick - everything builds fine

Here is what found out:
MinGW GCC has the header _mingw.h which does #define __int64 long long
The above breaks that some very old SWIG tweak (it was added more than 16 years ago):

/* Fix for jlong on some versions of gcc on Windows */
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
  typedef long long __int64;
#endif

The above code comes from the SWIG javahead.swg include

FYI: the _mingw.h is included via the following dependencies:

. ../blst.hpp
.. E:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/9.2.0/include/c++/string
... E:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/9.2.0/include/c++/bits/char_traits.h
.... E:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/9.2.0/include/c++/bits/postypes.h
..... E:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/9.2.0/include/c++/cwchar
...... E:/TDM-GCC-64/x86_64-w64-mingw32/include/wchar.h
....... E:/TDM-GCC-64/x86_64-w64-mingw32/include/corecrt.h
........ E:/TDM-GCC-64/x86_64-w64-mingw32/include/_mingw.h

It actually looks more like a SWIG issue. They should probably add something like && !defined(__int64) to their macro condition.

Though I'd like to ask you guys first as C/C++ gurus if we can fix/workaround this on Blst or our Teku side?

Error while performing signature

We need to use blst in order to perform a signature in our project, but it fails using blst_sign_pk_in_g1 function, specifically in POINTonE2_mult_gls. It has been built using arm-none-eabi-gcc from GNU Arm Embedded Toolchain as cross compiler and it's used in a nRF5340 board. Last working version was this one.

Symbol collision with openssl

I've been working to create portable versions of Lighthouse, which has meant vendoring openssl as a static library.

During linking I get the following error from cargo, which indicates duplicate symbols between openssl (already defined) and blst:

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.0.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.1.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.10.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.11.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.12.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.13.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.14.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.15.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.2.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.3.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.4.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.5.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.6.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.7.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.8.rcgu.o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.build_script_build.5xlfh9ot-cgu.9.rcgu.o" "-o" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1" "/target/release/build/eth2_testnet_config-f80d9826a04c3cd1/build_script_build-f80d9826a04c3cd1.3505t472p1rxx8d9.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-L" "/target/release/deps" "-L" "/target/release/build/blst-9371ea9d4f785b6a/out" "-L" "/target/release/build/ring-2576dc4f14a87596/out" "-L" "/target/release/build/libsqlite3-sys-028045c599cbd948/out" "-L" "/target/release/build/openssl-sys-b8f5860d05172a46/out/openssl-build/install/lib" "-L" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/target/release/deps/libreqwest-8554af7f94b086ee.rlib" "/target/release/deps/libhyper_tls-85c3f52119d8e093.rlib" "/target/release/deps/libipnet-a7fb6f02dcdb374c.rlib" "/target/release/deps/libtokio_tls-2bafd832aa83b03a.rlib" "/target/release/deps/libencoding_rs-f47002981754d86e.rlib" "/target/release/deps/libserde_urlencoded-0beb76c71f0f9b89.rlib" "/target/release/deps/libbase64-81fb7a3de7920337.rlib" "/target/release/deps/libmime_guess-0fce326879fca279.rlib" "/target/release/deps/libunicase-22c5590a75454b10.rlib" "/target/release/deps/libmime-9028ffd6b66d5a7a.rlib" "/target/release/deps/libnative_tls-f87010ecba179e74.rlib" "/target/release/deps/libopenssl_probe-c94d77228ca05eeb.rlib" "/target/release/deps/libopenssl-0382c8b8a815da34.rlib" "/target/release/deps/libopenssl_sys-ac675114625945ad.rlib" "/target/release/deps/libforeign_types-e6850f3f6ab87d8d.rlib" "/target/release/deps/libforeign_types_shared-514f271abd9dcb1d.rlib" "/target/release/deps/libhyper-5472c2bf7440e591.rlib" "/target/release/deps/libhttparse-0b84b879b01ace27.rlib" "/target/release/deps/libwant-2f95fb59033dc3cc.rlib" "/target/release/deps/libtry_lock-3fcfb9a79f999690.rlib" "/target/release/deps/libh2-fc76a0624648478f.rlib" "/target/release/deps/libindexmap-97a6c9a28c898ae9.rlib" "/target/release/deps/libhashbrown-1c75b6870c81d067.rlib" "/target/release/deps/libtokio_util-fd20f3c0dc0057ee.rlib" "/target/release/deps/libsocket2-527ba7744fe478af.rlib" "/target/release/deps/libtower_service-9d14a18aa9ec401f.rlib" "/target/release/deps/libtracing-bb64b643ab3ab47c.rlib" "/target/release/deps/libtracing_core-c16b67022a9bc9e2.rlib" "/target/release/deps/libtokio-53b210f35bd8ead5.rlib" "/target/release/deps/libsignal_hook_registry-307f62036afe760e.rlib" "/target/release/deps/libarc_swap-08b842736ed53d42.rlib" "/target/release/deps/libmio_uds-f1b01f66f1a6d177.rlib" "/target/release/deps/libmio-572e635e562870bc.rlib" "/target/release/deps/libiovec-4d3855f43e6ae4df.rlib" "/target/release/deps/libnet2-a96c450616b7ff39.rlib" "/target/release/deps/libpin_project_lite-26d68186f2482f16.rlib" "/target/release/deps/libhttp_body-2678c6cea2a1f74e.rlib" "/target/release/deps/libfutures_util-926b97d1a3e51a08.rlib" "/target/release/deps/libmemchr-fa9b7adacce34692.rlib" "/target/release/deps/libproc_macro_nested-ebcc1646b95e9e82.rlib" "/target/release/deps/libfutures-1e51387ca0ed956e.rlib" "/target/release/deps/libfutures_io-ec5b8a96624282f2.rlib" "/target/release/deps/libslab-e1b177a90421fcb5.rlib" "/target/release/deps/libfutures_channel-a06e86628c520166.rlib" "/target/release/deps/libpin_project-5888f93c514d4c4f.rlib" "/target/release/deps/libfutures_sink-f5a2e83e5606de49.rlib" "/target/release/deps/libfutures_task-6dee730c29d08740.rlib" "/target/release/deps/libonce_cell-4f89fede75132748.rlib" "/target/release/deps/libparking_lot-008820c471764ac5.rlib" "/target/release/deps/libparking_lot_core-6a8d5aac23394d22.rlib" "/target/release/deps/liblock_api-bc84e94bb6be3b36.rlib" "/target/release/deps/libpin_utils-abc99c3ae697a3d7.rlib" "/target/release/deps/libfutures_core-7394af138f43fd8e.rlib" "/target/release/deps/liburl-fd13b2968901b466.rlib" "/target/release/deps/libpercent_encoding-beb548f7fbaa198d.rlib" "/target/release/deps/libidna-619be24928d079c4.rlib" "/target/release/deps/libunicode_normalization-301d5ba88b28b166.rlib" "/target/release/deps/libtinyvec-1ea3f44ee5fc5858.rlib" "/target/release/deps/libunicode_bidi-e08f9552f9f382a4.rlib" "/target/release/deps/libmatches-8cd9af4a7f899158.rlib" "/target/release/deps/libhttp-d56db25500e32e7d.rlib" "/target/release/deps/libfnv-32aea7382b61848c.rlib" "/target/release/deps/libhandlebars-b08252ca284e3d53.rlib" "/target/release/deps/libpest-c9cf2d5a9dcebfd8.rlib" "/target/release/deps/libucd_trie-9376a72a54b14696.rlib" "/target/release/deps/libserde_json-3ebf8e5838f343ff.rlib" "/target/release/deps/libryu-fce13a80f1ff55e4.rlib" "/target/release/deps/libitoa-e8be65b96c1c4287.rlib" "/target/release/deps/libquick_error-414a73e455c6dbdd.rlib" "/target/release/deps/libeth2_config-b98313cbba557eaa.rlib" "/target/release/deps/libtypes-9922c132c755a3d2.rlib" "/target/release/deps/libslog-91b967d4301de7ab.rlib" "/target/release/deps/libcompare_fields-3d9c36773428e99a.rlib" "/target/release/deps/libdirs-061a3e8953d7b9a1.rlib" "/target/release/deps/libdirs_sys-0ddc1d62db5c4685.rlib" "/target/release/deps/librusqlite-f7ae25b21ba8b62e.rlib" "/target/release/deps/libtime-2cf742b08c31dbdf.rlib" "/target/release/deps/libbitflags-c74b1b8d1e8f9660.rlib" "/target/release/deps/libfallible_streaming_iterator-0ac1ce980e2d8ebc.rlib" "/target/release/deps/libfallible_iterator-12cc4918bbe1bf48.rlib" "/target/release/deps/liblru_cache-0988af52d825971e.rlib" "/target/release/deps/liblibsqlite3_sys-2587f56b8c60d5b9.rlib" "/target/release/deps/libswap_or_not_shuffle-ce9ba8310597e235.rlib" "/target/release/deps/libcached_tree_hash-e3269ddc876e285b.rlib" "/target/release/deps/libssz_types-f8e12236cc72e1c7.rlib" "/target/release/deps/libtypenum-972aadf3a52fcf7a.rlib" "/target/release/deps/librand_xorshift-b7beef0ae4da1a1d.rlib" "/target/release/deps/libeth2_interop_keypairs-98348466bfd611a7.rlib" "/target/release/deps/libserde_yaml-8147d4a7df260ce2.rlib" "/target/release/deps/libdtoa-a00da8193e23dc72.rlib" "/target/release/deps/libyaml_rust-b1132581acd8da15.rlib" "/target/release/deps/liblinked_hash_map-6585ebdbeac56aed.rlib" "/target/release/deps/libnum_bigint-2cc3c04e0fb19dc4.rlib" "/target/release/deps/libnum_integer-82310229b4a02121.rlib" "/target/release/deps/libnum_traits-fdea96309b91f98a.rlib" "/target/release/deps/liblog-2d4953f5690c3429.rlib" "/target/release/deps/libbls-f8fb8a157a1e5f73.rlib" "/target/release/deps/libmilagro_bls-378037218fcbbd41.rlib" "/target/release/deps/libamcl-2a75d0291c07f714.rlib" "/target/release/deps/libhex-cb9304af7205c48f.rlib" "/target/release/deps/libblst-f24ffced809e69d4.rlib" "/target/release/deps/libthreadpool-3f53d1bf42699f77.rlib" "/target/release/deps/libzeroize-15e0634389e4352b.rlib" "/target/release/deps/libssz-241fb120a8f7667a.rlib" "/target/release/deps/libserde_hex-b3f7ec2ba6bcb33e.rlib" "/target/release/deps/libhex-01e4031a68a52844.rlib" "/target/release/deps/libtree_hash-f510e2f95c45f4dc.rlib" "/target/release/deps/libsmallvec-be015730e60a1d5f.rlib" "/target/release/deps/librayon-439da60135725620.rlib" "/target/release/deps/librayon_core-e5bcb1180adc1be2.rlib" "/target/release/deps/libnum_cpus-df749efb73077f5f.rlib" "/target/release/deps/libcrossbeam_deque-a8b5f613ba1adc75.rlib" "/target/release/deps/libcrossbeam_epoch-3287268bfdc33002.rlib" "/target/release/deps/libscopeguard-981e0fd01390580f.rlib" "/target/release/deps/libmemoffset-e35e5516b0a74720.rlib" "/target/release/deps/libcrossbeam_queue-ef4de43db3543d2b.rlib" "/target/release/deps/libcrossbeam_utils-df47abda0d2411cd.rlib" "/target/release/deps/libmaybe_uninit-221c27a634e131c5.rlib" "/target/release/deps/libeither-277d2d8fb6dd8acf.rlib" "/target/release/deps/libmerkle_proof-88a6a6a415f087d8.rlib" "/target/release/deps/libsafe_arith-e6488697dafac224.rlib" "/target/release/deps/libethereum_types-24de5876b3fb154f.rlib" "/target/release/deps/libethbloom-fc3f1b2a32546fd5.rlib" "/target/release/deps/libtiny_keccak-c5ab25563b70a73e.rlib" "/target/release/deps/libprimitive_types-1c91ce6b1f45fff8.rlib" "/target/release/deps/libimpl_codec-19eea1bb4ceb871f.rlib" "/target/release/deps/libparity_scale_codec-42c213969c9c54f7.rlib" "/target/release/deps/libbyte_slice_cast-81b414f4afcce7e2.rlib" "/target/release/deps/libarrayvec-6e24743649c361b9.rlib" "/target/release/deps/libuint-17fc075c0c0f1515.rlib" "/target/release/deps/libcrunchy-61d5f9ffa08e7808.rlib" "/target/release/deps/libimpl_serde-e82472131d2d37fe.rlib" "/target/release/deps/libserde-be0a196a4cfea052.rlib" "/target/release/deps/libimpl_rlp-2a6de41817dac32e.rlib" "/target/release/deps/librlp-a03224ccba6b4199.rlib" "/target/release/deps/libfixed_hash-e71d48d5abff73b1.rlib" "/target/release/deps/librand-0b1da1fbe4932acc.rlib" "/target/release/deps/librand_chacha-618e4ef498dbe97f.rlib" "/target/release/deps/libppv_lite86-0feb83f6519fdc19.rlib" "/target/release/deps/librand_core-0d70a91769289afc.rlib" "/target/release/deps/libgetrandom-b4fb2a9bd67ca6b2.rlib" "/target/release/deps/libcfg_if-b54bd1f3a94e0e76.rlib" "/target/release/deps/librustc_hex-43614664506e6dcb.rlib" "/target/release/deps/libbyteorder-fb4a30392f846b17.rlib" "/target/release/deps/libstatic_assertions-f0e656d75f7dd446.rlib" "/target/release/deps/libeth2_hashing-c69517f0367e772b.rlib" "/target/release/deps/libring-00e4bf62b6678855.rlib" "/target/release/deps/liblazy_static-d64e9aa0f0de57b3.rlib" "/target/release/deps/libspin-ad732aaaa7d97aa6.rlib" "/target/release/deps/liblibc-636aca7798be1458.rlib" "/target/release/deps/libuntrusted-45d6058bac1acda1.rlib" "/target/release/deps/libint_to_bytes-8b87d8a5d3b49e80.rlib" "/target/release/deps/libbytes-f26916b0b8c43cfa.rlib" "-Wl,--start-group" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-8bb11f807a7b6b4c.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-ca8087507780d964.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-259c92b387c1c166.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-16e0a2fbbb8e14b3.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-8a1651b8e23d2aaf.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-23bdd98b0574083e.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-855a92055ec33e2e.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-24c70dd44fbacdfb.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-b326273841bae587.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-ac3c1f0e16507051.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-a5729542b65954aa.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-09bd1119ab1cad7d.rlib" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-9a787681bfbeaf61.rlib" "-Wl,--end-group" "/rust/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-5a0398ee67f74664.rlib" "-Wl,-Bdynamic" "-lutil" "-ldl" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-ldl" "-lutil"
  = note: /target/release/deps/libblst-f24ffced809e69d4.rlib(assembly.o): In function `sha256_block_data_order':
          (.text+0x4c0): multiple definition of `sha256_block_data_order'
          /target/release/deps/libopenssl_sys-ac675114625945ad.rlib(sha256-x86_64.o):(.text+0x0): first defined here
          collect2: error: ld returned 1 exit status

I can resolve this issue and produce a binary if I use the following commit of blst: sigp@284f705. This is basically s/sha256_block_data_order/blst_sha256_block_data_order across this project.

Linking is not my domain, so I open to more elegant solutions that my previous commit. Thank you :)

Rust bindings: expose safe blst_scalar constructors

In the Rust bindings, in order to use Signature::verify_multiple_aggregate_signatures you must initialize some blst_scalar values.

AFAIK, the only way to do this is via the unsafe blst_scalar_from_* functions.

It would be great if the bindings could wrap these in a non-unsafe function, if they are indeed as safe as all the other times we call the unsafe extern "C" functions.

keygen: salt is hashed

The function blst_keygen hashes the salt before using the HKDF, which is not the case in the specification. Is there any reason?

When writing an OCaml binding (available here), I tried to use the test vectors available in bls_sigs_ref. The test vectors use the seed to generate the sk and therefore the tests were not passing. While removing the hash, all the test vectors are fine (without any surprise ofc).
If anyone else would like to use the test vectors generated by bls_sigs_ref, I regenerated the correct signature for the current version (3f7d97e) of keygen. The MR history should be enough clear to be convinced the values are correct. The files can also be regenerated from the original as described in the MR.

[Optim] SIMD for Pornin's GCD inverse

The current implementation of inversion follows closely @pornin's paper and uses an inner loop with 4 31-bit integers stored in 2 64-bit registers:

$code.=<<___;
.type __inner_loop_31,\@abi-omnipotent
.align 32
__inner_loop_31: ################# by Thomas Pornin
mov \$0x7FFFFFFF80000000, $fg0 # |f0|=1, |g0|=0
mov \$0x800000007FFFFFFF, $fg1 # |f1|=0, |g1|=1
mov \$0x7FFFFFFF7FFFFFFF, $bias
.Loop_31:

https://github.com/pornin/bingcd/blob/700cc4d/src/gf25519.c#L1098-L1145

image

Instead it's possible to store 4 62-bit integers in 2 128-bit SIMD which are available in x86-64 (which implies SSE2) and ARM Neon.
This allows the inner loop to use 62 iterations instead of 31 and actually should remove the need for 2 distinct loops.

The main benefits would be:

  • for variable time inversion since we could eliminate more than 31 0 bits in a single iteration.
  • reducing bookkeeping since the hot loop is bigger and there is no more slow loop.
  • reducing general register pressure on x86-64 (if it was an issue).

However I do not know if in pure SSE2 it's possible to emulate CMOV efficiently and conditional swap.

In terms of use-cases:

  • inversion is used once for pairing but only represent a small portion of the total cost
  • inversion will likely be used for polynomial commitments for inverse FFTs

MacOS build fails

build.sh fails on MacOS with the following warnings (as errors):

nashatyrev@MacBook-Pro blst % ./build.sh          
+ cc -O -fno-builtin-memcpy -fPIC -Wall -Wextra -Werror -mno-avx -c ./src/server.c
In file included from ./src/server.c:19:
./src/bulk_addition.c:147:1: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
ADDITION_BTREE(POINTonE2, 384x, fp2, BLS12_381_Rx.p2)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/bulk_addition.c:113:49: note: expanded from macro 'ADDITION_BTREE'
#define ADDITION_BTREE(ptype, bits, field, one) \
                                                ^
./src/bulk_addition.c:57:37: note: expanded from macro '\
HEAD'
    static const vec##bits zero = { 0 }; \
                                    ^
In file included from ./src/server.c:20:
./src/multi_scalar.c:192:1: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
MULT_SCALAR_WBITS_IMPL(POINTonE1, 384, fp, BLS12_381_Rx.p)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/multi_scalar.c:101:46: note: expanded from macro 'MULT_SCALAR_WBITS_IMPL'
    static const ptype##_affine infinity = { 0 }; \
                                             ^
./src/multi_scalar.c:196:1: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
MULT_SCALAR_WBITS_IMPL(POINTonE2, 384x, fp2, BLS12_381_Rx.p2)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/multi_scalar.c:101:46: note: expanded from macro 'MULT_SCALAR_WBITS_IMPL'
    static const ptype##_affine infinity = { 0 }; \
                                             ^
./src/multi_scalar.c:196:1: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
MULT_SCALAR_WBITS_IMPL(POINTonE2, 384x, fp2, BLS12_381_Rx.p2)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./src/multi_scalar.c:101:46: note: expanded from macro 'MULT_SCALAR_WBITS_IMPL'
    static const ptype##_affine infinity = { 0 }; \
                                             ^
4 errors generated.

This is due to commit 46be9ea
Adding -Wno-missing-braces option to build.sh solves the problem

"BLS12381G1_XMD:BLAKE2B_SSWU_RO_"

It would be nice to be able to provide a custom hash routine to support other algorithms, such as "BLS12381G1_XMD:BLAKE2B_SSWU_RO_" for BBS+. OpenSSL includes support for "blake2b512".

Also looks like blake2b might make it into both Ethereum and Zcash. My interest is more around BBS+ though.
ethereum/EIPs#2129

Whatever the case, an option to use blake2b512 would be a nice addition.

Looking over expand_message_xmd in https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.html

Hash to scalar

Is there any chance of getting hash to scalar implemented?

https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.html#section-5-4
The hash_to_field function is also suitable for securely hashing to scalars. For example, when hashing to scalars for an elliptic curve (sub)group with prime order r, it suffices to instantiate hash_to_curve with target field GF(r).

I've been working on adding it but wanted to check the viability of this change before going too much further with it.

[low priority] Use C fallback on non-ARM non-x86 platforms

We can use the no_asm.h fallback for 32-bit also as a fallback for non-ARM, non-x86 platforms by changing the #if in

  • Assembly.S

    blst/build/assembly.S

    Lines 112 to 115 in 7cda6fa

    #elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__==4
    /* inaccurate way to detect a 32-bit processor, but it's close enough */
    #else
    # error "unsupported platform"
  • vect.h

    blst/src/vect.h

    Lines 11 to 35 in 7cda6fa

    #if defined(__x86_64__) || defined(__aarch64__) || defined(__mips64) || \
    defined(__ia64) || (defined(__VMS) && !defined(__vax))
    /* These are available even in ILP32 flavours, but even then they are
    * capable of performing 64-bit operations as efficiently as in *P64. */
    typedef unsigned long long limb_t;
    # define LIMB_T_BITS 64
    #elif defined(_WIN64) /* Win64 is P64 */
    typedef unsigned __int64 limb_t;
    # define LIMB_T_BITS 64
    #elif defined(__wasm64__)
    typedef unsigned int limb_t;
    # define LIMB_T_BITS 32
    # define __BLST_NO_ASM__
    # else /* 32 bits on 32-bit platforms, 64 - on 64-bit */
    typedef unsigned long limb_t;
    # ifdef _LP64
    # define LIMB_T_BITS 64
    # else
    # define LIMB_T_BITS 32
    # define __BLST_NO_ASM__
    # endif
    #endif

Tagging low-priority as we don't have a use case, at least yet but FWIW we had our PowerPC CI failing.

To "this" or not to "this"...

Quoting @Nashatyrev in #54.

  • (codestyle nit not directly related to this PR) there are methods like class P1 { P1 add(P1 a); } which modify and return this instance. From my perspective they could be erroneously interpreted as that a new instance is returned and this instance is left unmodified. Not sure about common C++ patterns, but Java dev would likely misinterpret this. Does it make sense to return void from these methods to avoid such misuse?

Infinity pubkey and signature

The Eth2 test vectors contain a test that requires the infinity signature to represent a valid signature by the infinity pubkey across any message:

input: {pubkey: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  message: '0xabababababababababababababababababababababababababababababababab', signature: '0xc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'}
output: true

The output: true here means that we should consider this pubkey/message/signature combination to be valid.

Presently blst will return output: false for the above test vector. I'm wondering if this project would expect to change their behaviour to match the Eth2 spec or if it plans to leave it as-is?

Thank you for your time :)

Rust unit tests fail in release

First, thanks again for producing this library!

During integration I noticed some odd behaviour and I tracked it down to a difference between compiling in release/debug.

For example:

  • cargo test: all tests pass.
  • cargo test --release: some tests fail.

Steps to reproduce

Run cargo test --release in bindings/rust/.

Logs

cargo test --release
    Finished release [optimized] target(s) in 0.02s
     Running target/release/deps/blst-a42debb43dd162a7

running 19 tests
test bindgen_test_layout_blst_fp ... ok
test bindgen_test_layout_blst_fp12 ... ok
test bindgen_test_layout_blst_fp2 ... ok
test bindgen_test_layout_blst_fp6 ... ok
test bindgen_test_layout_blst_fr ... ok
test bindgen_test_layout_blst_p1 ... ok
test bindgen_test_layout_blst_p1_affine ... ok
test bindgen_test_layout_blst_p2 ... ok
test bindgen_test_layout_blst_p2_affine ... ok
test bindgen_test_layout_blst_pairing ... ok
test bindgen_test_layout_blst_scalar ... ok
test min_pk::tests::test_serialization ... ok
test min_sig::tests::test_serialization ... ok
test min_sig::tests::test_sign ... FAILED
test min_pk::tests::test_sign ... FAILED
test min_sig::tests::test_aggregate ... FAILED
test min_sig::tests::test_multiple_agg_sigs ... FAILED
test min_pk::tests::test_aggregate ... FAILED
test min_pk::tests::test_multiple_agg_sigs ... FAILED

failures:

---- min_sig::tests::test_sign stdout ----
thread 'min_sig::tests::test_sign' panicked at 'assertion failed: `(left == right)`
  left: `BLST_VERIFY_FAIL`,
 right: `BLST_SUCCESS`', src/lib.rs:1340:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- min_pk::tests::test_sign stdout ----
thread 'min_pk::tests::test_sign' panicked at 'assertion failed: `(left == right)`
  left: `BLST_VERIFY_FAIL`,
 right: `BLST_SUCCESS`', src/lib.rs:1300:5

---- min_sig::tests::test_aggregate stdout ----
thread 'min_sig::tests::test_aggregate' panicked at 'assertion failed: `(left == right)`
  left: `[BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL]`,
 right: `[BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS]`', src/lib.rs:1340:5

---- min_sig::tests::test_multiple_agg_sigs stdout ----
thread 'min_sig::tests::test_multiple_agg_sigs' panicked at 'assertion failed: `(left == right)`
  left: `[BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL]`,
 right: `[BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS]`', src/lib.rs:1340:5

---- min_pk::tests::test_aggregate stdout ----
thread 'min_pk::tests::test_aggregate' panicked at 'assertion failed: `(left == right)`
  left: `[BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL]`,
 right: `[BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS]`', src/lib.rs:1300:5

---- min_pk::tests::test_multiple_agg_sigs stdout ----
thread 'min_pk::tests::test_multiple_agg_sigs' panicked at 'assertion failed: `(left == right)`
  left: `[BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL, BLST_VERIFY_FAIL]`,
 right: `[BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS, BLST_SUCCESS]`', src/lib.rs:1300:5


failures:
    min_pk::tests::test_aggregate
    min_pk::tests::test_multiple_agg_sigs
    min_pk::tests::test_sign
    min_sig::tests::test_aggregate
    min_sig::tests::test_multiple_agg_sigs
    min_sig::tests::test_sign

test result: FAILED. 13 passed; 6 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--lib'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.