Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux aarch64 support for EIP196 constantine #203

Merged
merged 30 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
06f1c4a
fixed mac libs not getting copied
NickSneo Aug 14, 2024
e5a532d
add support for linux aarch64
NickSneo Aug 14, 2024
5cadcba
test for nimble not found
NickSneo Aug 14, 2024
9493af9
extract to correct dir
NickSneo Aug 14, 2024
697a309
mkdir fix
NickSneo Aug 14, 2024
100f7cd
mkdir fix2
NickSneo Aug 14, 2024
7be8bfb
install in build.sh for aarch64
NickSneo Aug 14, 2024
e75b8c7
export path fix
NickSneo Aug 14, 2024
d2a77a5
check fix
NickSneo Aug 14, 2024
5f89d71
nim 2.0.4 test for aarch 64
NickSneo Aug 15, 2024
e9e38a3
set JAVA_HOME
NickSneo Aug 15, 2024
05d6d6f
nimble change revert
NickSneo Aug 15, 2024
380307f
use gcc instead of clang
NickSneo Aug 15, 2024
c7034ea
java 11 removed and java21 apt install added
NickSneo Aug 20, 2024
db152d7
JAVA_HOME export
NickSneo Aug 20, 2024
34bf436
JAVA_HOME fix try
NickSneo Aug 20, 2024
2178717
chech Java
NickSneo Aug 20, 2024
dcc9d60
set Java_home
NickSneo Aug 20, 2024
bc9e92d
updated Ubuntu to 22.04
NickSneo Aug 20, 2024
7d61c39
added GOROOT
NickSneo Aug 21, 2024
f6777dc
added GOROOT in build.sh
NickSneo Aug 21, 2024
d2031f1
convert to JNA, use static libconstantine.a
garyschulte Aug 21, 2024
f50bf95
use -fPIC in linux build of libconstantine
garyschulte Aug 21, 2024
da8dbd7
fix for x86_64
NickSneo Aug 21, 2024
82496a5
removed accidental comments
NickSneo Aug 21, 2024
ad0a2b2
revert accidental change in arm64
NickSneo Aug 21, 2024
836918d
check for config.nim already modified
NickSneo Aug 21, 2024
407f9c0
fix for tests
NickSneo Aug 21, 2024
fe758d1
add linx-arm lib upload action
garyschulte Aug 21, 2024
79c055d
tests fix 1
NickSneo Aug 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
native-build-linux-x86-64:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
env:
SKIP_GRADLE: true
steps:
Expand Down Expand Up @@ -111,6 +111,10 @@ jobs:
with:
name: gnark native build artifacts
path: gnark/build/
- uses: actions/[email protected]
with:
name: constantine native build artifacts
path: constantine/build/

native-build-macos:
runs-on: macos-13
Expand Down Expand Up @@ -258,7 +262,7 @@ jobs:
path: constantine/build/

final-assembly:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
needs:
- native-build-macos
- native-build-m1
Expand Down Expand Up @@ -349,6 +353,10 @@ jobs:
with:
name: jars
path: gnark/build/libs
- uses: actions/[email protected]
with:
name: jars
path: constantine/build/libs
- name: gradle publish
uses: gradle/gradle-build-action@v2
if: contains('refs/heads/release-', github.ref) || github.ref == 'refs/heads/main'
Expand Down
38 changes: 26 additions & 12 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ EOF
LIBRARY_EXTENSION=so
elif [[ "$OSTYPE" == "darwin"* ]]; then
LIBRARY_EXTENSION=dylib
export GOROOT=$(brew --prefix [email protected])/libexec
export PATH=$GOROOT/bin:$PATH
fi

go build -buildmode=c-shared -o libgnark_jni.$LIBRARY_EXTENSION gnark-jni.go
Expand All @@ -324,33 +326,45 @@ build_constantine() {
echo "####### build constantine ####"
echo "#############################"

# Skip if OSARCH is linux-gnu-aarch64
if [[ "$OSARCH" == "linux-gnu-aarch64" ]]; then
echo "Skipping build for OSARCH: ${OSARCH}"
return
fi

cd "$SCRIPTDIR/constantine/constantine"

# delete old build dir, if exists
rm -rf "$SCRIPTDIR/constantine/build" || true
mkdir -p "$SCRIPTDIR/constantine/build/${OSARCH}/lib"

export PATH=$HOME/.nimble/bin:$PATH
# Check and modify config.nims if on x86_64
if [[ "$OSARCH" == "linux-gnu-x86_64" ]]; then
# Check if the config.nims already contains the necessary flags
if ! grep -q 'switch("passC", "-fPIC")' config.nims; then
{
echo 'when defined(linux):'
echo ' switch("passC", "-fPIC")'
echo ' switch("passL", "-fPIC")'
} >> config.nims
fi
fi

# Build the constantine library
export CTT_LTO=false
nimble make_lib
if [[ "$OSARCH" == "linux-gnu-aarch64" ]]; then
# Download and extract Nim
wget https://github.com/nim-lang/nightlies/releases/download/2024-03-28-version-2-0-b47747d31844c6bd9af4322efe55e24fefea544c/nim-2.0.4-linux_arm64.tar.xz
NickSneo marked this conversation as resolved.
Show resolved Hide resolved
tar -xf nim-2.0.4-linux_arm64.tar.xz
git config --global --add safe.directory /home/ubuntu/constantine/constantine
export PATH=$(pwd)/nim-2.0.4/bin:$PATH
nimble make_lib
else
export PATH=$HOME/.nimble/bin:$PATH
nimble make_lib
fi

cd "$SCRIPTDIR/constantine/"

# Compile the native library
if [[ "$OSTYPE" == "darwin"* ]]; then
cp "$SCRIPTDIR/constantine/constantine/lib/libconstantine.dylib" "$SCRIPTDIR/constantine/build/${OSARCH}/lib/"
clang -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" -shared -o "$SCRIPTDIR/constantine/build/${OSARCH}/lib/libconstantineeip196.jnilib" ethereum_evm_precompiles.c -Iconstantine/include -I. -Lconstantine/lib -lconstantine
clang -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" -shared -o "$SCRIPTDIR/constantine/build/${OSARCH}/lib/libconstantineeip196.dylib" jna_ethereum_evm_precompiles.c -Iconstantine/include -I. constantine/lib/libconstantine.a
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
cp "$SCRIPTDIR/constantine/constantine/lib/libconstantine.so" "$SCRIPTDIR/constantine/build/${OSARCH}/lib/"
clang -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" -fPIC -shared -o "$SCRIPTDIR/constantine/build/${OSARCH}/lib/libconstantineeip196.so" ethereum_evm_precompiles.c -Iconstantine/include -I. -Lconstantine/lib -lconstantine
gcc -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" -fPIC -shared -o "$SCRIPTDIR/constantine/build/${OSARCH}/lib/libconstantineeip196.so" jna_ethereum_evm_precompiles.c -Iconstantine/include -I. -Lconstantine/lib constantine/lib/libconstantine.a
else
echo "Unsupported OS/architecture: ${OSARCH}"
exit 1
Expand Down
44 changes: 20 additions & 24 deletions constantine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,37 @@ tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

def osName = System.getProperty('os.name').toLowerCase()
def osArch = System.getProperty('os.arch')
def libDir

if (osName.contains('mac') && osArch.contains('aarch64')) {
libDir = 'darwin-aarch64'
} else if (osName.contains('mac')) {
libDir = 'darwin-x86-64'
} else if (osName.contains('linux') && osArch.contains('aarch64')) {
libDir = 'linux-gnu-aarch64'
} else {
libDir = 'linux-gnu-x86_64'
task macArmLibCopy(type: Copy) {
from "build/darwin-aarch64/lib/libconstantineeip196.dylib"
into 'build/resources/main/darwin-aarch64'
}

task libCopy(type: Copy) {
from "build/${libDir}/lib/"
into "build/resources/main/lib/${libDir}"
task macLibCopy(type: Copy) {
from "build/darwin-x86-64/lib/libconstantineeip196.dylib"
into 'build/resources/main/darwin-x86-64'
}

processResources.dependsOn libCopy
task linuxLibCopy(type: Copy) {
from "build/linux-gnu-x86_64/lib/libconstantineeip196.so"
into 'build/resources/main/linux-gnu-x86_64'

}

task compileJavaSource(type: Exec) {
description = 'Compiles the Java source files'
commandLine 'javac', '-d', 'build', 'src/main/java/org/hyperledger/besu/nativelib/constantine/LibConstantineEIP196.java'
dependsOn libCopy
task linuxArm64LibCopy(type: Copy) {
from "build/linux-gnu-aarch64/lib/libconstantineeip196.so"
into 'build/resources/main/linux-gnu-aarch64'
}

processResources.dependsOn macArmLibCopy, macLibCopy, linuxLibCopy, linuxArm64LibCopy

tasks.named('test', Test) {
description = 'Runs the Java tests'
useJUnit {
include '**/*Test.class'
}
environment 'LD_LIBRARY_PATH', "${System.env.LD_LIBRARY_PATH}:build/resources/main/lib/${libDir}"
jvmArgs = ["-Djava.library.path=build/resources/main/lib/${libDir}"]
dependsOn compileJavaSource
environment 'LD_LIBRARY_PATH', "${System.env.LD_LIBRARY_PATH}:build/resources/main/linux-gnu-x86_64"

dependsOn macArmLibCopy, macLibCopy, linuxLibCopy, linuxArm64LibCopy
}

jar {
Expand Down Expand Up @@ -142,4 +138,4 @@ artifactory {

test {
useJUnit()
}
}
30 changes: 30 additions & 0 deletions constantine/jna_ethereum_evm_precompiles.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "jna_ethereum_evm_precompiles.h"
#include <constantine.h>
#include <stdio.h>

void printByteArray(const char* label, const byte* array, size_t len) {
printf("%s: [", label);
for (size_t i = 0; i < len; i++) {
printf("%02x", array[i]);
if (i < len - 1) {
printf(", ");
}
}
printf("]\n");
}

int bn254_g1add(byte* r, int r_len, const byte* inputs, int inputs_len) {
// Call the original function
return (int) ctt_eth_evm_bn254_g1add(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len);
}

int bn254_g1mul(byte* r, int r_len, const byte* inputs, int inputs_len) {
// Call the original function
return (int) ctt_eth_evm_bn254_g1mul(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len);
}

int bn254_pairingCheck(byte* r, int r_len, const byte* inputs, int inputs_len) {
// Call the original function
return (int) ctt_eth_evm_bn254_ecpairingcheck(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len);
}

34 changes: 34 additions & 0 deletions constantine/jna_ethereum_evm_precompiles.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef _Included_LibConstantineEIP196_Wrapper
#define _Included_LibConstantineEIP196_Wrapper

#ifdef __cplusplus
extern "C" {
#endif

// Define byte as unsigned char
typedef unsigned char byte;

/*
* Function: ctt_eth_evm_bn254_g1add_wrapper
* Signature: (byte*, int, const byte*, int) -> int
*/
int bn254_g1add(byte* r, int r_len, const byte* inputs, int inputs_len);

/*
* Function: ctt_eth_evm_bn254_g1mul_wrapper
* Signature: (byte*, int, const byte*, int) -> int
*/
int bn254_g1mul(byte* r, int r_len, const byte* inputs, int inputs_len);

/*
* Function: ctt_eth_evm_bn254_pairingCheck_wrapper
* Signature: (byte*, int, const byte*, int) -> int
*/
int bn254_pairingCheck(byte* r, int r_len, const byte* inputs, int inputs_len);

#ifdef __cplusplus
}
#endif

#endif /* _Included_LibConstantineEIP196_Wrapper */

Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
package org.hyperledger.besu.nativelib.constantine;

import com.sun.jna.Native;

public class LibConstantineEIP196 {
public static final boolean ENABLED;

static {
System.loadLibrary("constantineeip196");
boolean enabled;
try {
Native.register(LibConstantineEIP196.class, "constantineeip196");
enabled = true;
} catch (final Throwable t) {
t.printStackTrace();
enabled = false;
}
ENABLED = enabled;
}

public native int ctt_eth_evm_bn254_g1add(byte[] r, int r_len, byte[] inputs, int inputs_len);
public native int ctt_eth_evm_bn254_g1mul(byte[] r, int r_len, byte[] inputs, int inputs_len);
public native int ctt_eth_evm_bn254_pairingCheck(byte[] r, int r_len, byte[] inputs, int inputs_len);

public static void loadNativeLibrary() {
System.loadLibrary("constantineeip196");
}
public static native int bn254_g1add(byte[] r, int r_len, byte[] inputs, int inputs_len);
public static native int bn254_g1mul(byte[] r, int r_len, byte[] inputs, int inputs_len);
public static native int bn254_pairingCheck(byte[] r, int r_len, byte[] inputs, int inputs_len);

public byte[] add(byte[] inputs) {
public static byte[] add(byte[] inputs) {
byte[] result = new byte[64];
int status = ctt_eth_evm_bn254_g1add(result, result.length, inputs, inputs.length);
int status = bn254_g1add(result, result.length, inputs, inputs.length);
if (status != 0) {
throw new RuntimeException("ctt_eth_evm_bn254_g1add failed with status: " + status);
}
return result;
}

public byte[] mul(byte[] inputs) {
public static byte[] mul(byte[] inputs) {
byte[] result = new byte[64];
int status = ctt_eth_evm_bn254_g1mul(result, result.length, inputs, inputs.length);
int status = bn254_g1mul(result, result.length, inputs, inputs.length);
if (status != 0) {
throw new RuntimeException("ctt_eth_evm_bn254_g1mul failed with status: " + status);
}
return result;
}

public byte[] pairingCheck(byte[] inputs) {
public static byte[] pairingCheck(byte[] inputs) {
byte[] result = new byte[32];
int status = ctt_eth_evm_bn254_pairingCheck(result, result.length, inputs, inputs.length);
int status = bn254_pairingCheck(result, result.length, inputs, inputs.length);
if (status != 0) {
throw new RuntimeException("ctt_eth_evm_bn254_pairingCheck failed with status: " + status);
}
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,10 @@ public void shouldCalculate() {
// skip the header row
return;
}
LibConstantineEIP196 constInstance = new LibConstantineEIP196();
byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe();

byte[] result = new byte[64];
int status = constInstance.ctt_eth_evm_bn254_g1add(result, result.length, inputBytes, inputBytes.length);
int status = LibConstantineEIP196.bn254_g1add(result, result.length, inputBytes, inputBytes.length);

Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult);
if (status != 0) {
Expand All @@ -63,4 +62,4 @@ public void shouldCalculate() {
assertTrue("Notes should be empty", notes.isEmpty());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ public void shouldCalculate() {
// skip the header row
return;
}
LibConstantineEIP196 constInstance = new LibConstantineEIP196();
byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe();

byte[] result = new byte[64];
int status = constInstance.ctt_eth_evm_bn254_g1mul(result, result.length, inputBytes, inputBytes.length);
int status = LibConstantineEIP196.bn254_g1mul(result, result.length, inputBytes, inputBytes.length);

Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult);

Expand All @@ -65,4 +64,4 @@ public void shouldCalculate() {
assertTrue("Notes should be empty", notes.isEmpty());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ public void shouldCalculate() {
if ("input".equals(input)) {
return;
}
LibConstantineEIP196 constInstance = new LibConstantineEIP196();
byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe();

byte[] result = new byte[32];
int status = constInstance.ctt_eth_evm_bn254_pairingCheck(result, result.length, inputBytes, inputBytes.length);
int status = LibConstantineEIP196.bn254_pairingCheck(result, result.length, inputBytes, inputBytes.length);

Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult);

Expand All @@ -62,4 +61,4 @@ public void shouldCalculate() {
assertTrue("Notes should be empty", notes.isEmpty());
}
}
}
}
Loading
Loading