├── .github └── workflows │ ├── build.yml │ ├── codeql.yml │ ├── dco.yml │ └── repolinter.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── RELEASE.md ├── SECURITY.md ├── arithmetic ├── arithmetic │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── arith.rs │ │ ├── lib.rs │ │ └── mpnat.rs ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── arithmetic │ │ └── LibArithmetic.java │ └── test │ └── java │ └── org │ └── hyperledger │ └── besu │ └── nativelib │ └── arithmetic │ └── TestLibArithmetic.java ├── blake2bf ├── aarch64 │ ├── blake2-impl.h │ ├── blake2.h │ ├── blake2b-load-neon.h │ ├── blake2b-round.h │ ├── blake2b.c │ └── makefile ├── arm64 │ ├── blake2-impl.h │ ├── blake2.h │ ├── blake2b-load-neon.h │ ├── blake2b-round.h │ ├── blake2b.c │ └── makefile ├── build.gradle ├── src │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── hyperledger │ │ │ └── besu │ │ │ └── nativelib │ │ │ └── blake2bf │ │ │ └── LibBlake2bf.java │ └── test │ │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── blake2bf │ │ └── LibBlake2bfTest.java └── x86_64 │ ├── blake2-config.h │ ├── blake2-impl.h │ ├── blake2.h │ ├── blake2b-load-sse2.h │ ├── blake2b-load-sse41.h │ ├── blake2b-round.h │ ├── blake2b.c │ └── makefile ├── boringssl ├── boringssl_jni │ ├── Makefile │ ├── p256_verify.c │ └── p256_verify.h ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── boringssl │ │ ├── LibP256Verify.java │ │ └── LibP256VerifyJNA.java │ └── test │ ├── java │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── boringssl │ │ ├── P256EdgeCaseTest.java │ │ ├── P256VerifyParameterizedTest.java │ │ └── P256VerifyTest.java │ └── resources │ └── org │ └── hyperledger │ └── besu │ └── nativelib │ └── boringssl │ └── p256_verify.csv ├── build.gradle ├── build.sh ├── common ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── hyperledger │ └── besu │ └── nativelib │ └── common │ └── BesuNativeLibraryLoader.java ├── constantine ├── build.gradle ├── jna_ethereum_evm_precompiles.c └── src │ ├── main │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── constantine │ │ ├── LibConstantineEIP196.java │ │ └── LibConstantineEIP2537.java │ └── test │ ├── java │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── constantine │ │ ├── ConstantineEIP196G1AddTest.java │ │ ├── ConstantineEIP196G1MulTest.java │ │ ├── ConstantineEIP196PairingCheckTest.java │ │ ├── ConstantineEIP2537FpToG1Test.java │ │ ├── ConstantineEIP2537G1AddTest.java │ │ ├── ConstantineEIP2537G1MsmTest.java │ │ ├── ConstantineEIP2537G1MulTest.java │ │ ├── ConstantineEIP2537G2AddTest.java │ │ ├── ConstantineEIP2537G2MsmTest.java │ │ ├── ConstantineEIP2537G2MulTest.java │ │ ├── ConstantineEIP2537PairingCheckTest.java │ │ ├── LibConstantineEIP196Test.java │ │ └── LibConstantineEIP2537Test.java │ └── resources │ ├── eip196_g1_add.csv │ ├── eip196_g1_mul.csv │ ├── eip196_pairing.csv │ ├── fp2_to_g2.csv │ ├── fp_to_g1.csv │ ├── g1_add.csv │ ├── g1_mul.csv │ ├── g1_multiexp.csv │ ├── g2_add.csv │ ├── g2_mul.csv │ ├── g2_multiexp.csv │ ├── invalid_pairing.csv │ └── pairing.csv ├── gnark ├── build.gradle ├── gnark-jni │ ├── README.md │ ├── gnark-eip-196.go │ ├── gnark-eip-2537.go │ ├── gnark-jni.go │ ├── gnark-test-data.go │ ├── go.mod │ └── go.sum └── src │ ├── main │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── gnark │ │ ├── LibGnark.java │ │ ├── LibGnarkEIP196.java │ │ ├── LibGnarkEIP2537.java │ │ └── LibGnarkUtils.java │ └── test │ ├── java │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── gnark │ │ ├── AltBN128G1AddPrecompiledContractTest.java │ │ ├── AltBN128G1MulPrecompiledContractTest.java │ │ ├── AltBN128PairingPrecompiledContractLegacyTest.java │ │ ├── AltBN128PairingPrecompiledContractTest.java │ │ ├── BLS12G1AddPrecompiledContractTest.java │ │ ├── BLS12G1MultiExpPrecompiledContractTest.java │ │ ├── BLS12G2AddPrecompiledContractTest.java │ │ ├── BLS12G2MultiExpPrecompiledContractTest.java │ │ ├── BLS12MapFp2ToG2PrecompiledContractTest.java │ │ ├── BLS12MapFpToG1PrecompiledContractTest.java │ │ ├── BLS12PairingPrecompiledContractTest.java │ │ └── LibGnarkTest.java │ └── resources │ └── org │ └── hyperledger │ └── besu │ └── nativelib │ └── gnark │ ├── eip196_g1_add.csv │ ├── eip196_g1_mul.csv │ ├── eip196_pairing.csv │ ├── fp2_to_g2.csv │ ├── fp_to_g1.csv │ ├── g1_add.csv │ ├── g1_mul.csv │ ├── g1_multiexp.csv │ ├── g1_multiexp_pair_comparison.csv │ ├── g2_add.csv │ ├── g2_mul.csv │ ├── g2_multiexp.csv │ ├── g2_multiexp_pair_comparison.csv │ ├── invalid_subgroup_for_pairing.csv │ └── pairing.csv ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ipa-multipoint ├── build.gradle ├── ipa_multipoint_jni │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── parsers.rs │ │ └── utils.rs └── src │ ├── main │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── ipamultipoint │ │ └── LibIpaMultipoint.java │ └── test │ ├── java │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── ipa_multipoint │ │ ├── CommitRootTest.java │ │ ├── LibIpaMultipointTest.java │ │ ├── PedersenCommitmentTest.java │ │ └── proof │ │ ├── ExecutionWitnessData.java │ │ └── VerifyProofTest.java │ └── resources │ ├── commit_root_test.json │ ├── invalid_block_72.json │ ├── invalid_block_73.json │ ├── pedersen_commitment_test.json │ ├── pedersen_hash_test.json │ ├── valid_block_1.json │ ├── valid_block_72.json │ └── valid_block_73.json ├── native-build.sh ├── secp256k1 ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── hyperledger │ └── besu │ └── nativelib │ └── secp256k1 │ └── LibSecp256k1.java ├── secp256r1 ├── build.gradle └── src │ ├── main │ └── java │ │ └── org │ │ └── hyperledger │ │ └── besu │ │ └── nativelib │ │ └── secp256r1 │ │ ├── LibSECP256R1.java │ │ ├── Signature.java │ │ └── besuNativeEC │ │ ├── BesuNativeEC.java │ │ ├── KeyRecoveryResult.java │ │ ├── SignResult.java │ │ └── VerifyResult.java │ └── test │ └── java │ └── org │ └── hyperledger │ └── besu │ └── nativelib │ └── secp256r1 │ └── LibSECP256R1Test.java └── settings.gradle /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | analyze: 11 | name: Analyze 12 | runs-on: ubuntu-latest 13 | permissions: 14 | actions: read 15 | contents: read 16 | security-events: write 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | language: [ java ] 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v3 26 | 27 | - name: Initialize CodeQL 28 | uses: github/codeql-action/init@v3 29 | with: 30 | languages: ${{ matrix.language }} 31 | queries: +security-and-quality 32 | 33 | - name: Autobuild 34 | uses: github/codeql-action/autobuild@v3 35 | 36 | - name: Perform CodeQL Analysis 37 | uses: github/codeql-action/analyze@v3 38 | with: 39 | category: "/language:${{ matrix.language }}" 40 | -------------------------------------------------------------------------------- /.github/workflows/dco.yml: -------------------------------------------------------------------------------- 1 | name: DCO 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | dco_check: 7 | runs-on: ubuntu-latest 8 | name: DCO 9 | if: ${{ github.actor != 'dependabot[bot]' }} 10 | steps: 11 | - name: Get PR Commits 12 | id: 'get-pr-commits' 13 | uses: tim-actions/get-pr-commits@198af03565609bb4ed924d1260247b4881f09e7d 14 | with: 15 | token: ${{ secrets.GITHUB_TOKEN }} 16 | - name: DCO Check 17 | uses: tim-actions/dco@f2279e6e62d5a7d9115b0cb8e837b777b1b02e21 18 | with: 19 | commits: ${{ steps.get-pr-commits.outputs.commits }} 20 | -------------------------------------------------------------------------------- /.github/workflows/repolinter.yml: -------------------------------------------------------------------------------- 1 | # Hyperledger Repolinter Action 2 | name: Repolinter 3 | 4 | on: 5 | workflow_dispatch: 6 | push: 7 | branches: 8 | - master 9 | - main 10 | pull_request: 11 | branches: 12 | - master 13 | - main 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | container: ghcr.io/todogroup/repolinter:v0.10.1 19 | steps: 20 | - name: Checkout Code 21 | uses: actions/checkout@v3 22 | - name: Lint Repo 23 | run: bundle exec /app/bin/repolinter.js --rulesetUrl https://raw.githubusercontent.com/hyperledger-labs/hyperledger-community-management-tools/main/repo_structure/repolint.json --format markdown 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | target 3 | 4 | Cargo.lock 5 | 6 | .idea 7 | .classpath 8 | .project 9 | .settings 10 | 11 | .gradle 12 | 13 | *.DS_Store 14 | 15 | ## build files 16 | *.com 17 | *.class 18 | *.dll 19 | *.exe 20 | *.o 21 | *.so 22 | 23 | *.a 24 | *.dylib 25 | constantine/out 26 | gnark/gnark-jni/*.h 27 | */bin 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "secp256k1/bitcoin-core-secp256k1"] 2 | path = secp256k1/bitcoin-core-secp256k1 3 | url = https://github.com/bitcoin-core/secp256k1.git 4 | [submodule "secp256r1/besu-native-ec"] 5 | path = secp256r1/besu-native-ec 6 | url = git@github.com:ConsenSys/besu-native-ec.git 7 | [submodule "constantine/constantine"] 8 | path = constantine/constantine 9 | url = https://github.com/mratsim/constantine.git 10 | [submodule "boringssl/google-boringssl"] 11 | path = boringssl/google-boringssl 12 | url = https://boringssl.googlesource.com/boringssl 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Hyperledger Besu 2 | ## :tada: Thanks for taking the time to contribute! :tada: 3 | 4 | Welcome to the Besu repository! The following links are a set of guidelines for contributing to this repo and its packages. These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a pull request. Contributions come in the form of code submissions, writing documentation, raising issues, helping others in chat, and any other actions that help develop Besu. 5 | 6 | ### LF/Github Accounts 7 | 8 | Having the following accounts is necessary for contributing code/issues to Besu. 9 | * If you want to contribute code, you can make a [github account here](https://github.com). 10 | * If you want to raise an issue, do so [in the issues tab](https://github.com/hyperledger/besu/issues). 11 | * Our Rocket Chat and wiki require a [Linux Foundation (LF) account]. 12 | 13 | ### Useful contributing links 14 | 15 | * [I just have a quick question](https://wiki.hyperledger.org/display/BESU/I+just+have+a+quick+question) 16 | * [How to Contribute] 17 | * [First contribution workflow](https://wiki.hyperledger.org/display/BESU/First+contribution?src=contextnavpagetreemode) 18 | * [Did you find a bug?](https://wiki.hyperledger.org/display/BESU/Reporting+Bugs) 19 | * [Issues](https://wiki.hyperledger.org/display/BESU/Issues) 20 | * [DCO](https://wiki.hyperledger.org/display/BESU/DCO) 21 | * [Suggesting Enhancements](https://wiki.hyperledger.org/display/BESU/Suggesting+Enhancements) 22 | * [Pull Requests](https://wiki.hyperledger.org/display/BESU/Pull+Requests) 23 | * [Code Reviews](https://wiki.hyperledger.org/display/BESU/Code+Reviews) 24 | 25 | 26 | * [Security contributions](https://wiki.hyperledger.org/display/BESU/Security) 27 | 28 | ### Other important information 29 | 30 | * [Roadmap](https://wiki.hyperledger.org/display/BESU/Roadmap) 31 | * [Code of Conduct](https://wiki.hyperledger.org/display/BESU/Code+of+Conduct) 32 | * [Governance](https://wiki.hyperledger.org/display/BESU/Governance) 33 | 34 | [How to Contribute]: https://wiki.hyperledger.org/display/BESU/How+to+Contribute 35 | [Linux Foundation (LF) account]: https://identity.linuxfoundation.org/ 36 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | Maintainers for this repository are the same as 4 | for [Hyperledger Besu](https://github.com/hyperledger/besu/blob/master/MAINTAINERS.md) 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Besu Native 2 | 3 | This repository contains scripts and tooling that is used to build and package the native libraries 4 | used by Hyperledger Besu. 5 | 6 | Besu Native libraries are licensed unde the [Apache 2.0 License](LICENSE). 7 | 8 | ## Prerequisites 9 | 10 | ### Linux 11 | 12 | You'll need to be sure that gcc, make, autoconf, automake, and libtool are installed. If you are 13 | building on Ubuntu or Debian, the following command will install these dependencies for you: 14 | 15 | ``` 16 | sudo apt-get install build-essential automake autoconf libtool patchelf 17 | ``` 18 | 19 | ### OS X 20 | 21 | You'll need to be sure that XCode Command Line Tools, make, autoconf, automake, and libtool are 22 | installed. The easiest way to do this is to install [Homebrew](https://brew.sh/), and then run the 23 | following command. Note that installing Homebrew will automatically install the XCode command line 24 | tools. 25 | 26 | ``` 27 | brew install autoconf automake libtool 28 | ``` 29 | 30 | ### Windows 31 | 32 | TBD 33 | 34 | 35 | ## Language tools 36 | 37 | Additionally you will need golang, rust, and nim. Distributions often do not have the latest 38 | versions of these languages. Check for latest builds: 39 | https://www.rust-lang.org/tools/install 40 | https://go.dev/dl/ 41 | https://nim-lang.org/install.html 42 | 43 | ### Golang 44 | 45 | Golang is required to compile the gnark-based libraries for all platforms and architectures. 46 | 47 | On MacOs, homebrew has a working golang target, e.g.: 48 | 49 | `brew install go` 50 | 51 | on Linux, for most recent distributions there is typically a somewhat recent go package, e.g. 52 | `apt install go` 53 | 54 | You can fetch the latest golang distribution here: 55 | https://go.dev/dl/ 56 | 57 | ### Nim 58 | 59 | Nim 2.2.x+ is required to build Constantine. Constantine is skipped on riscv64 architectures, so it is not needed for linux-riscv64. 60 | On MacOs, homebrew has a working nim target, e.g.: 61 | 62 | `brew install nim` 63 | 64 | on Linux, for most recent distributions there is typically a nim package, e.g. 65 | `apt install nim` 66 | 67 | Otherwise see: 68 | https://nim-lang.org/install.html 69 | 70 | ### Rust 71 | 72 | Rust needs to be installed to compile the arithmetic library. The default way to install it on Linux or OS X is: 73 | 74 | ``` 75 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 76 | ``` 77 | 78 | If you are Mac M1/M2/M3 you might need to add this after installing rust: 79 | 80 | ``` 81 | rustup target add x86_64-apple-darwin 82 | ``` 83 | 84 | If you prefer another installation method please refer to the [Rust installation instructions](https://www.rust-lang.org/tools/install). 85 | 86 | ## Building 87 | 88 | 1. This repository builds native libraries from source that is included as git submodules. To be 89 | sure that you have cloned those submodules into the appropriate locations, 90 | run `git submodule init && git submodule update` 91 | 2. The build steps are entirely contained within the `build.sh` script at the repository root. 92 | Simply run this script, and all the native modules contained herein will be configured with the 93 | correct build options for Hyperledger Besu, and built. 94 | 95 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | This document describes how to make releases of Besu Native. 2 | 3 | Please see https://besu.hyperledger.org/ to learn more and contact maintainers if you have questions. 4 | 5 | # Prepare the release 6 | 7 | Make sure the CHANGELOG is up-to-date with the latest changes. 8 | 9 | Communicate with Besu maintainers and announce your intention to conduct a release. 10 | 11 | # Publish the release 12 | 13 | Make a pull request changing [gradle.properties] version to the next best version. 14 | 15 | The repository abides loosely to [semver conventions](https://semver.org/). 16 | * Removing a library or API may require a major version increment (0.7.0 -> 1.0.0) 17 | * Adding a new JAR/Library has been done in minor versions increment (0.6.2 -> 0.7.0) 18 | * Adding a function or API to an existing library has been done in double-dot minor version (0.6.1 -> 0.6.2) 19 | 20 | # Create the github tag and release 21 | 22 | Create a tag with: `git tag VERSION` 23 | 24 | Example: `git tag 0.6.2` 25 | 26 | Push the tag to the repository: `git push origin --tags` 27 | 28 | Create the github release associated with the tag. Copy the contents of the CHANGELOG for your version as Github release notes. 29 | 30 | # Prepare for next release 31 | 32 | Change [gradle.properties] to the next minor version with a `-SNAPSHOT` suffix. 33 | 34 | Example: `version=0.6.2-SNAPSHOT` 35 | 36 | Add the new version to the [CHANGELOG.md]: 37 | 38 | Example: `# 0.6.2-SNAPSHOT` 39 | 40 | Open a PR with this change. -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Hyperledger Security Policy 2 | 3 | ## Reporting a Security Bug 4 | 5 | If you think you have discovered a security issue in any of the Hyperledger projects, we'd love to 6 | hear from you. We will take all security bugs seriously and if confirmed upon investigation we will 7 | patch it within a reasonable amount of time and release a public security bulletin discussing the 8 | impact and credit the discoverer. 9 | 10 | There are two ways to report a security bug. The easiest is to email a description of the flaw and 11 | any related information (e.g. reproduction steps, version) to 12 | [security at hyperledger dot org](mailto:security@hyperledger.org). 13 | 14 | The other way is to file a confidential security bug in our 15 | [JIRA bug tracking system](https://jira.hyperledger.org). Be sure to set the “Security Level” to 16 | “Security issue”. 17 | 18 | The process by which the Hyperledger Security Team handles security bugs is documented further in 19 | our [Defect Response page](https://wiki.hyperledger.org/display/SEC/Defect+Response) on our 20 | [wiki](https://wiki.hyperledger.org). 21 | -------------------------------------------------------------------------------- /arithmetic/arithmetic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "besu-native-arithmetic" 3 | version = "0.11.0" 4 | description = """Native arithemetic for EVM. 5 | Derived from aurora - https://github.com/aurora-is-near/aurora-engine/tree/0cfda4686dbdb7a57b2dc18dddc5106ec8e24a38/engine-modexp - originally CC0-1.0 license.""" 6 | license = "Apache-2.0" 7 | authors = ["Aurora Labs ", "Danno Ferrin "] 8 | repository = "https://github.com/hyperledger/besu-native" 9 | edition = "2021" 10 | 11 | [dependencies] 12 | ibig = { version = "0.3.6", default-features = false, features = ["num-traits"], optional = true } 13 | num = { version = "0.4.0", default-features = false, features = ["alloc"] } 14 | hex = { version = "0.4", default-features = false, features = ["alloc"] } 15 | libc = "0.2" 16 | 17 | [lib] 18 | name = "eth_arithmetic" 19 | crate-type = ["cdylib"] 20 | 21 | [features] 22 | default = [] 23 | -------------------------------------------------------------------------------- /arithmetic/arithmetic/README.md: -------------------------------------------------------------------------------- 1 | # Besu native `modexp` 2 | 3 | Originally from Aurora `modexp` [implementation](https://github.com/aurora-is-near/aurora-engine/tree/0cfda4686dbdb7a57b2dc18dddc5106ec8e24a38/engine-modexp) 4 | 5 | ## What this crate is 6 | 7 | This crate is an efficient implementation of the EVM `modexp` precompile. 8 | This crate exposes a single public function 9 | 10 | ```rust 11 | pub fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec 12 | ``` 13 | 14 | This function takes the base, exponent and modulus as big-endian encoded bytes and returns the result in big-endian as well. 15 | 16 | This crate is meant to be an efficient implementation, using as little memory as possible (for example, it does not copy the exponent slice). 17 | The exponentiation is done using the ["binary method"](https://en.wikipedia.org/wiki/Exponentiation_by_squaring). 18 | The multiplication steps within the exponentiation use ["Montgomery multiplication"](https://en.wikipedia.org/wiki/Montgomery_modular_multiplication). 19 | In the case of even modulus, Montgomery multiplication does not apply directly. 20 | However we can reduce the problem to one involving an odd modulus and one where the modulus is a power of two. 21 | These two sub-problems can be solved efficiently (the former using Montgomery multiplication, the latter the modular arithmetic is trivial on a binary computer), 22 | then the results are combined using the [Chinese remainder theorem](https://en.wikipedia.org/wiki/Chinese_remainder_theorem). 23 | 24 | The primary academic references for this implementation are: 25 | 26 | 1. [Analyzing and Comparing Montgomery Multiplication Algorithms](https://www.microsoft.com/en-us/research/wp-content/uploads/1996/01/j37acmon.pdf) 27 | 2. [Montgomery Reduction with Even Modulus](http://www.people.vcu.edu/~jwang3/CMSC691/j34monex.pdf) 28 | 3. [A Cryptographic Library for the Motorola DSP56000](https://link.springer.com/content/pdf/10.1007/3-540-46877-3_21.pdf) 29 | 4. [The Art of Computer Programming Volume 2](https://www-cs-faculty.stanford.edu/~knuth/taocp.html) 30 | 31 | ## What this crate is NOT 32 | 33 | This crate is not a general purpose big integer library. 34 | If you need anything other than `modexp`, then you should use something like [num-bigint](https://crates.io/crates/num-bigint) or [ibig](https://crates.io/crates/ibig). 35 | -------------------------------------------------------------------------------- /arithmetic/arithmetic/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright contributors to Hyperledger Besu 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | mod arith; 5 | mod mpnat; 6 | 7 | use std::rc::Rc; 8 | use std::io::Write; 9 | 10 | use core::{ 11 | cmp::{min, Ordering}, 12 | mem::size_of, 13 | }; 14 | 15 | #[derive(Debug, Clone)] 16 | pub enum RuntimeError { 17 | /// Input was a bad format. 18 | BadFormat, 19 | } 20 | 21 | 22 | #[no_mangle] 23 | pub extern "C" fn modexp_precompiled( 24 | i: *const std::os::raw::c_char, 25 | i_len: u32, 26 | o: *mut std::os::raw::c_char, 27 | o_len: *mut u32, 28 | ) -> u32 { 29 | let input_i8: &[libc::c_char] = unsafe { std::slice::from_raw_parts(i, i_len as usize) }; 30 | let input: &[u8] = unsafe { std::mem::transmute(input_i8) }; 31 | 32 | let raw_out_i8: &mut [libc::c_char] = unsafe { std::slice::from_raw_parts_mut(o, o_len as usize) }; 33 | let mut raw_out: &mut [u8] = unsafe { std::mem::transmute(raw_out_i8) }; 34 | let answer = modexp_precompiled_impl(input); 35 | 36 | let written = raw_out.write(answer.as_slice()); 37 | if let Ok(bytes_written) = written { 38 | unsafe { *o_len = bytes_written as u32 }; 39 | 0u32 40 | } else { 41 | 1u32 42 | } 43 | } 44 | 45 | 46 | /// from revm - https://github.com/bluealloy/revm/blob/main/crates/revm_precompiles/src/modexp.rs 47 | macro_rules! read_u64_with_overflow { 48 | ($input:expr,$from:expr,$to:expr, $overflow_limit:expr) => {{ 49 | const SPLIT: usize = 32 - size_of::(); 50 | let len = $input.len(); 51 | let from_zero = min($from, len); 52 | let from = min(from_zero + SPLIT, len); 53 | let to = min($to, len); 54 | let overflow_bytes = &$input[from_zero..from]; 55 | 56 | let mut len_bytes = [0u8; size_of::()]; 57 | len_bytes[..to - from].copy_from_slice(&$input[from..to]); 58 | let out = u64::from_be_bytes(len_bytes) as usize; 59 | let overflow = !(out < $overflow_limit && overflow_bytes.iter().all(|&x| x == 0)); 60 | (out, overflow) 61 | }}; 62 | } 63 | 64 | /// from revm - https://github.com/bluealloy/revm/blob/main/crates/revm_precompiles/src/modexp.rs 65 | fn modexp_precompiled_impl(input: &[u8]) -> Rc> { 66 | let len = input.len(); 67 | let (base_len, base_overflow) = read_u64_with_overflow!(input, 0, 32, u32::MAX as usize); 68 | let (exp_len, exp_overflow) = read_u64_with_overflow!(input, 32, 64, u32::MAX as usize); 69 | let (mod_len, mod_overflow) = read_u64_with_overflow!(input, 64, 96, u32::MAX as usize); 70 | 71 | if base_overflow || mod_overflow { 72 | return Rc::new(Vec::new()); 73 | } 74 | 75 | if base_len == 0 && mod_len == 0 { 76 | return Rc::new(Vec::new()); 77 | } 78 | // set limit for exp overflow 79 | if exp_overflow { 80 | return Rc::new(Vec::new()); 81 | } 82 | let base_start = 96; 83 | let base_end = base_start + base_len; 84 | let exp_end = base_end + exp_len; 85 | let mod_end = exp_end + mod_len; 86 | 87 | let read_big = |from: usize, to: usize| { 88 | let mut out = vec![0; to - from]; 89 | let from = min(from, len); 90 | let to = min(to, len); 91 | out[..to - from].copy_from_slice(&input[from..to]); 92 | out 93 | }; 94 | 95 | let base = read_big(base_start, base_end); 96 | let exponent = read_big(base_end, exp_end); 97 | let modulus = read_big(exp_end, mod_end); 98 | let bytes = modexp(base.as_slice(), exponent.as_slice(), modulus.as_slice()); 99 | 100 | // write output to given memory, left padded and same length as the modulus. 101 | // always true except in the case of zero-length modulus, which leads to 102 | // output of length and value 1. 103 | match bytes.len().cmp(&mod_len) { 104 | Ordering::Equal => Rc::new(bytes.to_vec()), 105 | Ordering::Less => { 106 | let mut ret = Vec::with_capacity(mod_len); 107 | ret.extend(core::iter::repeat(0).take(mod_len - bytes.len())); 108 | ret.extend_from_slice(&bytes[..]); 109 | Rc::new(ret.to_vec()) 110 | } 111 | Ordering::Greater => Rc::new(Vec::new()), 112 | } 113 | } 114 | 115 | // from aurora 116 | /// Computes `(base ^ exp) % modulus`, where all values are given as big-endian 117 | /// encoded bytes. 118 | pub fn modexp(base: &[u8], exp: &[u8], modulus: &[u8]) -> Vec { 119 | let mut x = mpnat::MPNat::from_big_endian(base); 120 | let m = mpnat::MPNat::from_big_endian(modulus); 121 | if m.digits.len() == 1 && m.digits[0] == 0 { 122 | return Vec::new(); 123 | } 124 | let result = x.modpow(exp, &m); 125 | result.to_big_endian() 126 | } 127 | -------------------------------------------------------------------------------- /arithmetic/src/main/java/org/hyperledger/besu/nativelib/arithmetic/LibArithmetic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright contributors to Hyperledger Besu 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.arithmetic; 17 | 18 | import com.sun.jna.Library; 19 | import com.sun.jna.ptr.IntByReference; 20 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 21 | 22 | public class LibArithmetic implements Library { 23 | 24 | private LibArithmetic() {} 25 | 26 | public static final boolean ENABLED; 27 | 28 | static { 29 | boolean enabled; 30 | try { 31 | BesuNativeLibraryLoader.registerJNA(LibArithmetic.class, "eth_arithmetic"); 32 | enabled = true; 33 | } catch (final Exception t) { 34 | enabled = false; 35 | } 36 | ENABLED = enabled; 37 | } 38 | 39 | public static native int modexp_precompiled(byte[] i, int i_len, byte[] o, IntByReference o_len); 40 | } 41 | -------------------------------------------------------------------------------- /blake2bf/aarch64/blake2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2_H 21 | #define BLAKE2_H 22 | 23 | #include 24 | #include 25 | 26 | #if defined(_MSC_VER) 27 | #define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) 28 | #else 29 | #define BLAKE2_PACKED(x) x __attribute__((packed)) 30 | #endif 31 | 32 | #if defined(__cplusplus) 33 | extern "C" { 34 | #endif 35 | 36 | 37 | enum blake2b_constant 38 | { 39 | BLAKE2B_BLOCKBYTES = 128, 40 | BLAKE2B_OUTBYTES = 64 41 | }; 42 | 43 | enum eip152_constant 44 | { 45 | EIP152_PAYLOAD_LEN=213, 46 | EIP152_ROUNDS_OFFSET=0, 47 | EIP152_ROUNDS_LEN=4, 48 | EIP152_H_OFFSET = EIP152_ROUNDS_OFFSET + EIP152_ROUNDS_LEN, 49 | EIP152_H_LEN = 64, 50 | EIP152_M_OFFSET = EIP152_H_OFFSET + EIP152_H_LEN, 51 | EIP152_M_LEN = 128, 52 | EIP152_T_OFFSET = EIP152_M_OFFSET + EIP152_M_LEN, 53 | EIP152_T_LEN = 16, 54 | EIP152_F_OFFSET = EIP152_T_OFFSET + EIP152_T_LEN, 55 | EIP152_F_LEN = 1 56 | }; 57 | 58 | void blake2bf_eip152(uint8_t out[BLAKE2B_OUTBYTES], const uint8_t payload[EIP152_PAYLOAD_LEN]); 59 | 60 | #if defined(__cplusplus) 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /blake2bf/aarch64/blake2b-round.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2B_ROUND_H 21 | #define BLAKE2B_ROUND_H 22 | 23 | #define vrorq_n_u64_32(x) vreinterpretq_u64_u32(vrev64q_u32(vreinterpretq_u32_u64((x)))) 24 | 25 | #define vrorq_n_u64_24(x) vcombine_u64( \ 26 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 3)), \ 27 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 3))) 28 | 29 | #define vrorq_n_u64_16(x) vcombine_u64( \ 30 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 2)), \ 31 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 2))) 32 | 33 | #define vrorq_n_u64_63(x) veorq_u64(vaddq_u64(x, x), vshrq_n_u64(x, 63)) 34 | 35 | #define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 36 | row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \ 37 | row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \ 38 | row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \ 39 | row4l = vrorq_n_u64_32(row4l); row4h = vrorq_n_u64_32(row4h); \ 40 | row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \ 41 | row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \ 42 | row2l = vrorq_n_u64_24(row2l); row2h = vrorq_n_u64_24(row2h); 43 | 44 | #define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 45 | row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \ 46 | row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \ 47 | row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \ 48 | row4l = vrorq_n_u64_16(row4l); row4h = vrorq_n_u64_16(row4h); \ 49 | row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \ 50 | row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \ 51 | row2l = vrorq_n_u64_63(row2l); row2h = vrorq_n_u64_63(row2h); 52 | 53 | #define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 54 | t0 = vextq_u64(row2l, row2h, 1); \ 55 | t1 = vextq_u64(row2h, row2l, 1); \ 56 | row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ 57 | t0 = vextq_u64(row4h, row4l, 1); t1 = vextq_u64(row4l, row4h, 1); \ 58 | row4l = t0; row4h = t1; 59 | 60 | #define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 61 | t0 = vextq_u64(row2h, row2l, 1); \ 62 | t1 = vextq_u64(row2l, row2h, 1); \ 63 | row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ 64 | t0 = vextq_u64(row4l, row4h, 1); t1 = vextq_u64(row4h, row4l, 1); \ 65 | row4l = t0; row4h = t1; 66 | 67 | #include "blake2b-load-neon.h" 68 | 69 | #define ROUND(r) \ 70 | LOAD_MSG_ ##r ##_1(b0, b1); \ 71 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 72 | LOAD_MSG_ ##r ##_2(b0, b1); \ 73 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 74 | DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ 75 | LOAD_MSG_ ##r ##_3(b0, b1); \ 76 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 77 | LOAD_MSG_ ##r ##_4(b0, b1); \ 78 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 79 | UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /blake2bf/aarch64/blake2b.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "blake2.h" 28 | #include "blake2-impl.h" 29 | 30 | #include "blake2b-round.h" 31 | 32 | #define be32toh(x) OSSwapBigToHostInt32(x) 33 | 34 | static const uint64_t blake2b_IV[8] = 35 | { 36 | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 37 | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 38 | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 39 | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 40 | }; 41 | 42 | static void blake2b_compress(uint8_t out[BLAKE2B_OUTBYTES], const uint32_t rounds, const uint64_t h[8], const uint8_t block[128], const uint64_t t[2], const uint64_t f[2]) 43 | { 44 | const uint64x2_t m0 = vreinterpretq_u64_u8(vld1q_u8(&block[ 0])); 45 | const uint64x2_t m1 = vreinterpretq_u64_u8(vld1q_u8(&block[ 16])); 46 | const uint64x2_t m2 = vreinterpretq_u64_u8(vld1q_u8(&block[ 32])); 47 | const uint64x2_t m3 = vreinterpretq_u64_u8(vld1q_u8(&block[ 48])); 48 | const uint64x2_t m4 = vreinterpretq_u64_u8(vld1q_u8(&block[ 64])); 49 | const uint64x2_t m5 = vreinterpretq_u64_u8(vld1q_u8(&block[ 80])); 50 | const uint64x2_t m6 = vreinterpretq_u64_u8(vld1q_u8(&block[ 96])); 51 | const uint64x2_t m7 = vreinterpretq_u64_u8(vld1q_u8(&block[112])); 52 | 53 | uint64x2_t row1l, row1h, row2l, row2h; 54 | uint64x2_t row3l, row3h, row4l, row4h; 55 | uint64x2_t t0, t1, b0, b1; 56 | 57 | const uint64x2_t h0 = row1l = vld1q_u64(&h[0]); 58 | const uint64x2_t h1 = row1h = vld1q_u64(&h[2]); 59 | const uint64x2_t h2 = row2l = vld1q_u64(&h[4]); 60 | const uint64x2_t h3 = row2h = vld1q_u64(&h[6]); 61 | 62 | size_t i, round; 63 | 64 | row3l = vld1q_u64(&blake2b_IV[0]); 65 | row3h = vld1q_u64(&blake2b_IV[2]); 66 | row4l = veorq_u64(vld1q_u64(&blake2b_IV[4]), vld1q_u64(&t[0])); 67 | row4h = veorq_u64(vld1q_u64(&blake2b_IV[6]), vld1q_u64(&f[0])); 68 | 69 | for( i = 0; i < rounds; i++) { 70 | round = i % 10; 71 | switch (round) 72 | { 73 | case 0: 74 | ROUND( 0 ); 75 | break; 76 | case 1: 77 | ROUND( 1 ); 78 | break; 79 | case 2: 80 | ROUND( 2 ); 81 | break; 82 | case 3: 83 | ROUND( 3 ); 84 | break; 85 | case 4: 86 | ROUND( 4 ); 87 | break; 88 | case 5: 89 | ROUND( 5 ); 90 | break; 91 | case 6: 92 | ROUND( 6 ); 93 | break; 94 | case 7: 95 | ROUND( 7 ); 96 | break; 97 | case 8: 98 | ROUND( 8 ); 99 | break; 100 | case 9: 101 | ROUND( 9 ); 102 | break; 103 | default: 104 | break; 105 | } 106 | 107 | } 108 | 109 | vst1q_u64(&h[0], veorq_u64(h0, veorq_u64(row1l, row3l))); 110 | vst1q_u64(&h[2], veorq_u64(h1, veorq_u64(row1h, row3h))); 111 | vst1q_u64(&h[4], veorq_u64(h2, veorq_u64(row2l, row4l))); 112 | vst1q_u64(&h[6], veorq_u64(h3, veorq_u64(row2h, row4h))); 113 | 114 | for( i = 0; i < 8; ++i ) 115 | store64( out + sizeof( h[i] ) * i, h[i] ); 116 | } 117 | 118 | void blake2bf_eip152(uint8_t out[BLAKE2B_OUTBYTES], const uint8_t payload[EIP152_PAYLOAD_LEN]) 119 | { 120 | union { 121 | uint32_t u32; 122 | uint8_t arr[4]; 123 | } r; 124 | uint64_t rounds; 125 | uint64_t h[EIP152_H_LEN]; 126 | uint8_t m[EIP152_M_LEN]; 127 | uint64_t t[EIP152_T_LEN]; 128 | uint64_t f[2] = {0}; 129 | size_t i; 130 | 131 | memcpy(r.arr, payload + EIP152_ROUNDS_OFFSET, EIP152_ROUNDS_LEN); 132 | rounds = be32toh(r.u32); 133 | 134 | for( i = 0; i < 8; i++) { 135 | h[i] = load64(payload + EIP152_H_OFFSET + i * sizeof(uint64_t)); 136 | } 137 | 138 | memcpy(m, payload + EIP152_M_OFFSET, EIP152_M_LEN); 139 | 140 | t[0] = load64(payload + EIP152_T_OFFSET); 141 | t[1] = load64(payload + EIP152_T_OFFSET + sizeof(uint64_t)); 142 | 143 | if(payload[EIP152_F_OFFSET] != 0) { 144 | f[0] = (uint64_t)-1; 145 | } 146 | 147 | blake2b_compress(out, rounds, h, m, t, f); 148 | } 149 | -------------------------------------------------------------------------------- /blake2bf/aarch64/makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-march=armv8-a -O2 -Wall -Wextra -pedantic -Wno-long-long 3 | 4 | all: libblake2bf.dylib 5 | 6 | compile: blake2b.c blake2b-round.h blake2b-load-neon.h 7 | $(CC) blake2b.c -c $(CFLAGS) 8 | 9 | libblake2bf.dylib: blake2b.o 10 | $(CC) -dynamiclib -o $@ $(CFLAGS) blake2b.o 11 | 12 | clean: 13 | rm -rf *.o *.dylib 14 | -------------------------------------------------------------------------------- /blake2bf/arm64/blake2-impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2_IMPL_H 21 | #define BLAKE2_IMPL_H 22 | 23 | #include 24 | #include 25 | 26 | #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) 27 | #if defined(_MSC_VER) 28 | #define BLAKE2_INLINE __inline 29 | #elif defined(__GNUC__) 30 | #define BLAKE2_INLINE __inline__ 31 | #else 32 | #define BLAKE2_INLINE 33 | #endif 34 | #else 35 | #define BLAKE2_INLINE inline 36 | #endif 37 | 38 | static BLAKE2_INLINE uint32_t load32( const void *src ) 39 | { 40 | #if defined(NATIVE_LITTLE_ENDIAN) 41 | uint32_t w; 42 | memcpy(&w, src, sizeof w); 43 | return w; 44 | #else 45 | const uint8_t *p = ( const uint8_t * )src; 46 | return (( uint32_t )( p[0] ) << 0) | 47 | (( uint32_t )( p[1] ) << 8) | 48 | (( uint32_t )( p[2] ) << 16) | 49 | (( uint32_t )( p[3] ) << 24) ; 50 | #endif 51 | } 52 | 53 | static BLAKE2_INLINE uint64_t load64( const void *src ) 54 | { 55 | #if defined(NATIVE_LITTLE_ENDIAN) 56 | uint64_t w; 57 | memcpy(&w, src, sizeof w); 58 | return w; 59 | #else 60 | const uint8_t *p = ( const uint8_t * )src; 61 | return (( uint64_t )( p[0] ) << 0) | 62 | (( uint64_t )( p[1] ) << 8) | 63 | (( uint64_t )( p[2] ) << 16) | 64 | (( uint64_t )( p[3] ) << 24) | 65 | (( uint64_t )( p[4] ) << 32) | 66 | (( uint64_t )( p[5] ) << 40) | 67 | (( uint64_t )( p[6] ) << 48) | 68 | (( uint64_t )( p[7] ) << 56) ; 69 | #endif 70 | } 71 | 72 | static BLAKE2_INLINE uint16_t load16( const void *src ) 73 | { 74 | #if defined(NATIVE_LITTLE_ENDIAN) 75 | uint16_t w; 76 | memcpy(&w, src, sizeof w); 77 | return w; 78 | #else 79 | const uint8_t *p = ( const uint8_t * )src; 80 | return ( uint16_t )((( uint32_t )( p[0] ) << 0) | 81 | (( uint32_t )( p[1] ) << 8)); 82 | #endif 83 | } 84 | 85 | static BLAKE2_INLINE void store16( void *dst, uint16_t w ) 86 | { 87 | #if defined(NATIVE_LITTLE_ENDIAN) 88 | memcpy(dst, &w, sizeof w); 89 | #else 90 | uint8_t *p = ( uint8_t * )dst; 91 | *p++ = ( uint8_t )w; w >>= 8; 92 | *p++ = ( uint8_t )w; 93 | #endif 94 | } 95 | 96 | static BLAKE2_INLINE void store32( void *dst, uint32_t w ) 97 | { 98 | #if defined(NATIVE_LITTLE_ENDIAN) 99 | memcpy(dst, &w, sizeof w); 100 | #else 101 | uint8_t *p = ( uint8_t * )dst; 102 | p[0] = (uint8_t)(w >> 0); 103 | p[1] = (uint8_t)(w >> 8); 104 | p[2] = (uint8_t)(w >> 16); 105 | p[3] = (uint8_t)(w >> 24); 106 | #endif 107 | } 108 | 109 | static BLAKE2_INLINE void store64( void *dst, uint64_t w ) 110 | { 111 | #if defined(NATIVE_LITTLE_ENDIAN) 112 | memcpy(dst, &w, sizeof w); 113 | #else 114 | uint8_t *p = ( uint8_t * )dst; 115 | p[0] = (uint8_t)(w >> 0); 116 | p[1] = (uint8_t)(w >> 8); 117 | p[2] = (uint8_t)(w >> 16); 118 | p[3] = (uint8_t)(w >> 24); 119 | p[4] = (uint8_t)(w >> 32); 120 | p[5] = (uint8_t)(w >> 40); 121 | p[6] = (uint8_t)(w >> 48); 122 | p[7] = (uint8_t)(w >> 56); 123 | #endif 124 | } 125 | 126 | static BLAKE2_INLINE uint64_t load48( const void *src ) 127 | { 128 | const uint8_t *p = ( const uint8_t * )src; 129 | return (( uint64_t )( p[0] ) << 0) | 130 | (( uint64_t )( p[1] ) << 8) | 131 | (( uint64_t )( p[2] ) << 16) | 132 | (( uint64_t )( p[3] ) << 24) | 133 | (( uint64_t )( p[4] ) << 32) | 134 | (( uint64_t )( p[5] ) << 40) ; 135 | } 136 | 137 | static BLAKE2_INLINE void store48( void *dst, uint64_t w ) 138 | { 139 | uint8_t *p = ( uint8_t * )dst; 140 | p[0] = (uint8_t)(w >> 0); 141 | p[1] = (uint8_t)(w >> 8); 142 | p[2] = (uint8_t)(w >> 16); 143 | p[3] = (uint8_t)(w >> 24); 144 | p[4] = (uint8_t)(w >> 32); 145 | p[5] = (uint8_t)(w >> 40); 146 | } 147 | 148 | static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) 149 | { 150 | return ( w >> c ) | ( w << ( 32 - c ) ); 151 | } 152 | 153 | static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) 154 | { 155 | return ( w >> c ) | ( w << ( 64 - c ) ); 156 | } 157 | 158 | /* prevents compiler optimizing out memset() */ 159 | static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) 160 | { 161 | static void *(*const volatile memset_v)(void *, int, size_t) = &memset; 162 | memset_v(v, 0, n); 163 | } 164 | 165 | #endif 166 | -------------------------------------------------------------------------------- /blake2bf/arm64/blake2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2_H 21 | #define BLAKE2_H 22 | 23 | #include 24 | #include 25 | 26 | #if defined(_MSC_VER) 27 | #define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) 28 | #else 29 | #define BLAKE2_PACKED(x) x __attribute__((packed)) 30 | #endif 31 | 32 | #if defined(__cplusplus) 33 | extern "C" { 34 | #endif 35 | 36 | 37 | enum blake2b_constant 38 | { 39 | BLAKE2B_BLOCKBYTES = 128, 40 | BLAKE2B_OUTBYTES = 64 41 | }; 42 | 43 | enum eip152_constant 44 | { 45 | EIP152_PAYLOAD_LEN=213, 46 | EIP152_ROUNDS_OFFSET=0, 47 | EIP152_ROUNDS_LEN=4, 48 | EIP152_H_OFFSET = EIP152_ROUNDS_OFFSET + EIP152_ROUNDS_LEN, 49 | EIP152_H_LEN = 64, 50 | EIP152_M_OFFSET = EIP152_H_OFFSET + EIP152_H_LEN, 51 | EIP152_M_LEN = 128, 52 | EIP152_T_OFFSET = EIP152_M_OFFSET + EIP152_M_LEN, 53 | EIP152_T_LEN = 16, 54 | EIP152_F_OFFSET = EIP152_T_OFFSET + EIP152_T_LEN, 55 | EIP152_F_LEN = 1 56 | }; 57 | 58 | void blake2bf_eip152(uint8_t out[BLAKE2B_OUTBYTES], const uint8_t payload[EIP152_PAYLOAD_LEN]); 59 | 60 | #if defined(__cplusplus) 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /blake2bf/arm64/blake2b-round.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2B_ROUND_H 21 | #define BLAKE2B_ROUND_H 22 | 23 | #define vrorq_n_u64_32(x) vreinterpretq_u64_u32(vrev64q_u32(vreinterpretq_u32_u64((x)))) 24 | 25 | #define vrorq_n_u64_24(x) vcombine_u64( \ 26 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 3)), \ 27 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 3))) 28 | 29 | #define vrorq_n_u64_16(x) vcombine_u64( \ 30 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 2)), \ 31 | vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 2))) 32 | 33 | #define vrorq_n_u64_63(x) veorq_u64(vaddq_u64(x, x), vshrq_n_u64(x, 63)) 34 | 35 | #define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 36 | row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \ 37 | row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \ 38 | row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \ 39 | row4l = vrorq_n_u64_32(row4l); row4h = vrorq_n_u64_32(row4h); \ 40 | row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \ 41 | row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \ 42 | row2l = vrorq_n_u64_24(row2l); row2h = vrorq_n_u64_24(row2h); 43 | 44 | #define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 45 | row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \ 46 | row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \ 47 | row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \ 48 | row4l = vrorq_n_u64_16(row4l); row4h = vrorq_n_u64_16(row4h); \ 49 | row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \ 50 | row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \ 51 | row2l = vrorq_n_u64_63(row2l); row2h = vrorq_n_u64_63(row2h); 52 | 53 | #define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 54 | t0 = vextq_u64(row2l, row2h, 1); \ 55 | t1 = vextq_u64(row2h, row2l, 1); \ 56 | row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ 57 | t0 = vextq_u64(row4h, row4l, 1); t1 = vextq_u64(row4l, row4h, 1); \ 58 | row4l = t0; row4h = t1; 59 | 60 | #define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 61 | t0 = vextq_u64(row2h, row2l, 1); \ 62 | t1 = vextq_u64(row2l, row2h, 1); \ 63 | row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \ 64 | t0 = vextq_u64(row4l, row4h, 1); t1 = vextq_u64(row4h, row4l, 1); \ 65 | row4l = t0; row4h = t1; 66 | 67 | #include "blake2b-load-neon.h" 68 | 69 | #define ROUND(r) \ 70 | LOAD_MSG_ ##r ##_1(b0, b1); \ 71 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 72 | LOAD_MSG_ ##r ##_2(b0, b1); \ 73 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 74 | DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ 75 | LOAD_MSG_ ##r ##_3(b0, b1); \ 76 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 77 | LOAD_MSG_ ##r ##_4(b0, b1); \ 78 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 79 | UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /blake2bf/arm64/blake2b.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "blake2.h" 27 | #include "blake2-impl.h" 28 | 29 | #include "blake2b-round.h" 30 | 31 | static const uint64_t blake2b_IV[8] = 32 | { 33 | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 34 | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 35 | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 36 | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 37 | }; 38 | 39 | static void blake2b_compress(uint8_t out[BLAKE2B_OUTBYTES], const uint32_t rounds, const uint64_t h[8], const uint8_t block[128], const uint64_t t[2], const uint64_t f[2]) 40 | { 41 | const uint64x2_t m0 = vreinterpretq_u64_u8(vld1q_u8(&block[ 0])); 42 | const uint64x2_t m1 = vreinterpretq_u64_u8(vld1q_u8(&block[ 16])); 43 | const uint64x2_t m2 = vreinterpretq_u64_u8(vld1q_u8(&block[ 32])); 44 | const uint64x2_t m3 = vreinterpretq_u64_u8(vld1q_u8(&block[ 48])); 45 | const uint64x2_t m4 = vreinterpretq_u64_u8(vld1q_u8(&block[ 64])); 46 | const uint64x2_t m5 = vreinterpretq_u64_u8(vld1q_u8(&block[ 80])); 47 | const uint64x2_t m6 = vreinterpretq_u64_u8(vld1q_u8(&block[ 96])); 48 | const uint64x2_t m7 = vreinterpretq_u64_u8(vld1q_u8(&block[112])); 49 | 50 | uint64x2_t row1l, row1h, row2l, row2h; 51 | uint64x2_t row3l, row3h, row4l, row4h; 52 | uint64x2_t t0, t1, b0, b1; 53 | 54 | const uint64x2_t h0 = row1l = vld1q_u64(&h[0]); 55 | const uint64x2_t h1 = row1h = vld1q_u64(&h[2]); 56 | const uint64x2_t h2 = row2l = vld1q_u64(&h[4]); 57 | const uint64x2_t h3 = row2h = vld1q_u64(&h[6]); 58 | 59 | size_t i, round; 60 | 61 | row3l = vld1q_u64(&blake2b_IV[0]); 62 | row3h = vld1q_u64(&blake2b_IV[2]); 63 | row4l = veorq_u64(vld1q_u64(&blake2b_IV[4]), vld1q_u64(&t[0])); 64 | row4h = veorq_u64(vld1q_u64(&blake2b_IV[6]), vld1q_u64(&f[0])); 65 | 66 | for( i = 0; i < rounds; i++) { 67 | round = i % 10; 68 | switch (round) 69 | { 70 | case 0: 71 | ROUND( 0 ); 72 | break; 73 | case 1: 74 | ROUND( 1 ); 75 | break; 76 | case 2: 77 | ROUND( 2 ); 78 | break; 79 | case 3: 80 | ROUND( 3 ); 81 | break; 82 | case 4: 83 | ROUND( 4 ); 84 | break; 85 | case 5: 86 | ROUND( 5 ); 87 | break; 88 | case 6: 89 | ROUND( 6 ); 90 | break; 91 | case 7: 92 | ROUND( 7 ); 93 | break; 94 | case 8: 95 | ROUND( 8 ); 96 | break; 97 | case 9: 98 | ROUND( 9 ); 99 | break; 100 | default: 101 | break; 102 | } 103 | 104 | } 105 | 106 | vst1q_u64(&h[0], veorq_u64(h0, veorq_u64(row1l, row3l))); 107 | vst1q_u64(&h[2], veorq_u64(h1, veorq_u64(row1h, row3h))); 108 | vst1q_u64(&h[4], veorq_u64(h2, veorq_u64(row2l, row4l))); 109 | vst1q_u64(&h[6], veorq_u64(h3, veorq_u64(row2h, row4h))); 110 | 111 | for( i = 0; i < 8; ++i ) 112 | store64( out + sizeof( h[i] ) * i, h[i] ); 113 | } 114 | 115 | void blake2bf_eip152(uint8_t out[BLAKE2B_OUTBYTES], const uint8_t payload[EIP152_PAYLOAD_LEN]) 116 | { 117 | union { 118 | uint32_t u32; 119 | uint8_t arr[4]; 120 | } r; 121 | uint64_t rounds; 122 | uint64_t h[EIP152_H_LEN]; 123 | uint8_t m[EIP152_M_LEN]; 124 | uint64_t t[EIP152_T_LEN]; 125 | uint64_t f[2] = {0}; 126 | size_t i; 127 | 128 | memcpy(r.arr, payload + EIP152_ROUNDS_OFFSET, EIP152_ROUNDS_LEN); 129 | rounds = be32toh(r.u32); 130 | 131 | for( i = 0; i < 8; i++) { 132 | h[i] = load64(payload + EIP152_H_OFFSET + i * sizeof(uint64_t)); 133 | } 134 | 135 | memcpy(m, payload + EIP152_M_OFFSET, EIP152_M_LEN); 136 | 137 | t[0] = load64(payload + EIP152_T_OFFSET); 138 | t[1] = load64(payload + EIP152_T_OFFSET + sizeof(uint64_t)); 139 | 140 | if(payload[EIP152_F_OFFSET] != 0) { 141 | f[0] = (uint64_t)-1; 142 | } 143 | 144 | blake2b_compress(out, rounds, h, m, t, f); 145 | } 146 | -------------------------------------------------------------------------------- /blake2bf/arm64/makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-march=armv8-a -O2 -Wall -Wextra -pedantic -Wno-long-long 3 | 4 | all: libblake2bf 5 | 6 | compile: blake2b.c blake2b-round.h blake2b-load-neon.h 7 | $(CC) blake2b.c -c $(CFLAGS) 8 | 9 | libblake2bf: blake2b.o 10 | $(CC) -shared -o $@.so $(CFLAGS) blake2b.o 11 | 12 | clean: 13 | rm -rf *.o *.so 14 | -------------------------------------------------------------------------------- /blake2bf/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu Contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | plugins { 17 | id 'java-library' 18 | id 'maven-publish' 19 | id 'com.jfrog.artifactory' version '5.2.3' 20 | } 21 | 22 | dependencies { 23 | implementation project(':common') 24 | implementation 'net.java.dev.jna:jna:5.12.1' 25 | testImplementation 'junit:junit:4.13.2' 26 | testImplementation 'org.assertj:assertj-core:3.22.0' 27 | } 28 | 29 | task macAarch64LibCopy(type: Copy) { 30 | from 'build/darwin-aarch64/lib/libblake2bf.dylib' 31 | into 'build/resources/main/lib/aarch64' 32 | } 33 | 34 | processResources.dependsOn macAarch64LibCopy 35 | 36 | task macLibCopy(type: Copy) { 37 | from 'build/darwin-x86-64/lib/libblake2bf.dylib' 38 | into 'build/resources/main/lib/x86-64' 39 | } 40 | 41 | processResources.dependsOn macLibCopy 42 | 43 | task linuxLibCopy(type: Copy) { 44 | from 'build/linux-gnu-x86_64/lib/libblake2bf.so' 45 | into 'build/resources/main/lib/x86-64' 46 | } 47 | processResources.dependsOn linuxLibCopy 48 | 49 | task linuxArm64LibCopy(type: Copy) { 50 | from 'build/linux-gnu-aarch64/lib/libblake2bf.so' 51 | into 'build/resources/main/lib/aarch64' 52 | } 53 | processResources.dependsOn linuxArm64LibCopy 54 | 55 | jar { 56 | archiveBaseName = 'besu-native-blake2bf' 57 | includeEmptyDirs = false 58 | manifest { 59 | attributes( 60 | 'Specification-Title': archiveBaseName, 61 | 'Specification-Version': project.version, 62 | 'Implementation-Title': archiveBaseName, 63 | 'Implementation-Version': project.version, 64 | 'Automatic-Module-Name': 'org.hyperledger.besu.nativelib.blake2bf' 65 | ) 66 | } 67 | } 68 | 69 | task sourcesJar(type: Jar, dependsOn: classes) { 70 | archiveBaseName = 'besu-native-blake2bf' 71 | archiveClassifier = 'sources' 72 | from sourceSets.main.allSource 73 | } 74 | 75 | task javadocJar(type: Jar, dependsOn: javadoc) { 76 | archiveBaseName = 'besu-native-blake2bf' 77 | archiveClassifier = 'javadoc' 78 | from javadoc.destinationDir 79 | } 80 | 81 | publishing { 82 | publications { 83 | mavenJava(MavenPublication) { 84 | groupId "org.hyperledger.besu" 85 | artifactId 'blake2bf' 86 | version "${project.version}" 87 | 88 | from components.java 89 | artifact sourcesJar 90 | artifact javadocJar 91 | 92 | pom { 93 | name = "Besu Native - ${project.name}" 94 | description = 'Adapter for native blake2bf' 95 | url = 'http://github.com/hyperledger/besu-native' 96 | licenses { 97 | license { 98 | name = 'The Apache License, Version 2.0' 99 | url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 100 | } 101 | } 102 | scm { 103 | connection = 'scm:git:git://github.com/hyperledger/besu-native.git' 104 | developerConnection = 'scm:git:ssh://github.com/hyperledger/besu-native.git' 105 | url = 'https://github.com/hyperledger/besu-native' 106 | } 107 | } 108 | } 109 | } 110 | } 111 | 112 | def artifactoryUser = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : System.getenv('ARTIFACTORY_USER') 113 | def artifactoryKey = project.hasProperty('artifactoryApiKey') ? project.property('artifactoryApiKey') : System.getenv('ARTIFACTORY_KEY') 114 | def artifactoryRepo = System.getenv('ARTIFACTORY_REPO') ?: 'besu-maven' 115 | def artifactoryOrg = System.getenv('ARTIFACTORY_ORG') ?: 'hyperledger' 116 | 117 | artifactory { 118 | contextUrl = "https://hyperledger.jfrog.io/${artifactoryOrg}" 119 | publish { 120 | repository { 121 | repoKey = artifactoryRepo 122 | username = artifactoryUser 123 | password = artifactoryKey 124 | } 125 | defaults { 126 | publications('mavenJava') 127 | publishArtifacts = true 128 | publishPom = true 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /blake2bf/src/main/java/org/hyperledger/besu/nativelib/blake2bf/LibBlake2bf.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu Contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.blake2bf; 17 | 18 | import com.sun.jna.Library; 19 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 20 | 21 | public class LibBlake2bf implements Library { 22 | @SuppressWarnings("WeakerAccess") 23 | public static final boolean ENABLED; 24 | 25 | static { 26 | boolean enabled; 27 | try { 28 | BesuNativeLibraryLoader.registerJNA(LibBlake2bf.class, "blake2bf"); 29 | enabled = true; 30 | } catch (final Throwable t) { 31 | enabled = false; 32 | } 33 | ENABLED = enabled; 34 | } 35 | 36 | public static native void blake2bf_eip152(byte[] out, byte[] payload); 37 | } 38 | -------------------------------------------------------------------------------- /blake2bf/x86_64/blake2-config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2_CONFIG_H 21 | #define BLAKE2_CONFIG_H 22 | 23 | /* These don't work everywhere */ 24 | #if defined(__SSE2__) || defined(__x86_64__) || defined(__amd64__) 25 | #define HAVE_SSE2 26 | #endif 27 | 28 | #if defined(__SSSE3__) 29 | #define HAVE_SSSE3 30 | #endif 31 | 32 | #if defined(__SSE4_1__) 33 | #define HAVE_SSE41 34 | #endif 35 | 36 | #if defined(__AVX__) 37 | #define HAVE_AVX 38 | #endif 39 | 40 | #if defined(__XOP__) 41 | #define HAVE_XOP 42 | #endif 43 | 44 | 45 | #ifdef HAVE_AVX2 46 | #ifndef HAVE_AVX 47 | #define HAVE_AVX 48 | #endif 49 | #endif 50 | 51 | #ifdef HAVE_XOP 52 | #ifndef HAVE_AVX 53 | #define HAVE_AVX 54 | #endif 55 | #endif 56 | 57 | #ifdef HAVE_AVX 58 | #ifndef HAVE_SSE41 59 | #define HAVE_SSE41 60 | #endif 61 | #endif 62 | 63 | #ifdef HAVE_SSE41 64 | #ifndef HAVE_SSSE3 65 | #define HAVE_SSSE3 66 | #endif 67 | #endif 68 | 69 | #ifdef HAVE_SSSE3 70 | #define HAVE_SSE2 71 | #endif 72 | 73 | #if !defined(HAVE_SSE2) 74 | #error "This code requires at least SSE2." 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /blake2bf/x86_64/blake2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | #ifndef BLAKE2_H 20 | #define BLAKE2_H 21 | 22 | #include 23 | #include 24 | 25 | #if defined(_MSC_VER) 26 | #define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) 27 | #else 28 | #define BLAKE2_PACKED(x) x __attribute__((packed)) 29 | #endif 30 | 31 | #if defined(__cplusplus) 32 | extern "C" { 33 | #endif 34 | 35 | enum blake2b_constant 36 | { 37 | BLAKE2B_BLOCKBYTES = 128, 38 | BLAKE2B_OUTBYTES = 64 39 | }; 40 | 41 | enum eip152_constant 42 | { 43 | EIP152_PAYLOAD_LEN=213, 44 | EIP152_ROUNDS_OFFSET=0, 45 | EIP152_ROUNDS_LEN=4, 46 | EIP152_H_OFFSET = EIP152_ROUNDS_OFFSET + EIP152_ROUNDS_LEN, 47 | EIP152_H_LEN = 64, 48 | EIP152_M_OFFSET = EIP152_H_OFFSET + EIP152_H_LEN, 49 | EIP152_M_LEN = 128, 50 | EIP152_T_OFFSET = EIP152_M_OFFSET + EIP152_M_LEN, 51 | EIP152_T_LEN = 16, 52 | EIP152_F_OFFSET = EIP152_T_OFFSET + EIP152_T_LEN, 53 | EIP152_F_LEN = 1 54 | }; 55 | 56 | void blake2bf_eip152(uint8_t out[BLAKE2B_OUTBYTES], const uint8_t payload[EIP152_PAYLOAD_LEN]); 57 | 58 | #if defined(__cplusplus) 59 | } 60 | #endif 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /blake2bf/x86_64/blake2b-load-sse2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, Samuel Neves . 3 | * Copyright Hyperledger Besu Contributors. 4 | * 5 | * Copied and adapted from BLAKE2 reference source code (https://github.com/BLAKE2/BLAKE2) 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations under the License. 15 | * 16 | * 17 | * SPDX-License-Identifier: Apache-2.0 18 | */ 19 | 20 | #ifndef BLAKE2B_LOAD_SSE2_H 21 | #define BLAKE2B_LOAD_SSE2_H 22 | 23 | #define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4) 24 | #define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5) 25 | #define LOAD_MSG_0_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12) 26 | #define LOAD_MSG_0_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13) 27 | #define LOAD_MSG_1_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9) 28 | #define LOAD_MSG_1_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15) 29 | #define LOAD_MSG_1_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11) 30 | #define LOAD_MSG_1_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7) 31 | #define LOAD_MSG_2_1(b0, b1) b0 = _mm_set_epi64x(m12, m11); b1 = _mm_set_epi64x(m15, m5) 32 | #define LOAD_MSG_2_2(b0, b1) b0 = _mm_set_epi64x(m0, m8); b1 = _mm_set_epi64x(m13, m2) 33 | #define LOAD_MSG_2_3(b0, b1) b0 = _mm_set_epi64x(m3, m10); b1 = _mm_set_epi64x(m9, m7) 34 | #define LOAD_MSG_2_4(b0, b1) b0 = _mm_set_epi64x(m6, m14); b1 = _mm_set_epi64x(m4, m1) 35 | #define LOAD_MSG_3_1(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m13) 36 | #define LOAD_MSG_3_2(b0, b1) b0 = _mm_set_epi64x(m1, m9); b1 = _mm_set_epi64x(m14, m12) 37 | #define LOAD_MSG_3_3(b0, b1) b0 = _mm_set_epi64x(m5, m2); b1 = _mm_set_epi64x(m15, m4) 38 | #define LOAD_MSG_3_4(b0, b1) b0 = _mm_set_epi64x(m10, m6); b1 = _mm_set_epi64x(m8, m0) 39 | #define LOAD_MSG_4_1(b0, b1) b0 = _mm_set_epi64x(m5, m9); b1 = _mm_set_epi64x(m10, m2) 40 | #define LOAD_MSG_4_2(b0, b1) b0 = _mm_set_epi64x(m7, m0); b1 = _mm_set_epi64x(m15, m4) 41 | #define LOAD_MSG_4_3(b0, b1) b0 = _mm_set_epi64x(m11, m14); b1 = _mm_set_epi64x(m3, m6) 42 | #define LOAD_MSG_4_4(b0, b1) b0 = _mm_set_epi64x(m12, m1); b1 = _mm_set_epi64x(m13, m8) 43 | #define LOAD_MSG_5_1(b0, b1) b0 = _mm_set_epi64x(m6, m2); b1 = _mm_set_epi64x(m8, m0) 44 | #define LOAD_MSG_5_2(b0, b1) b0 = _mm_set_epi64x(m10, m12); b1 = _mm_set_epi64x(m3, m11) 45 | #define LOAD_MSG_5_3(b0, b1) b0 = _mm_set_epi64x(m7, m4); b1 = _mm_set_epi64x(m1, m15) 46 | #define LOAD_MSG_5_4(b0, b1) b0 = _mm_set_epi64x(m5, m13); b1 = _mm_set_epi64x(m9, m14) 47 | #define LOAD_MSG_6_1(b0, b1) b0 = _mm_set_epi64x(m1, m12); b1 = _mm_set_epi64x(m4, m14) 48 | #define LOAD_MSG_6_2(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m10, m13) 49 | #define LOAD_MSG_6_3(b0, b1) b0 = _mm_set_epi64x(m6, m0); b1 = _mm_set_epi64x(m8, m9) 50 | #define LOAD_MSG_6_4(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m2) 51 | #define LOAD_MSG_7_1(b0, b1) b0 = _mm_set_epi64x(m7, m13); b1 = _mm_set_epi64x(m3, m12) 52 | #define LOAD_MSG_7_2(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m9, m1) 53 | #define LOAD_MSG_7_3(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m2, m8) 54 | #define LOAD_MSG_7_4(b0, b1) b0 = _mm_set_epi64x(m4, m0); b1 = _mm_set_epi64x(m10, m6) 55 | #define LOAD_MSG_8_1(b0, b1) b0 = _mm_set_epi64x(m14, m6); b1 = _mm_set_epi64x(m0, m11) 56 | #define LOAD_MSG_8_2(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m8, m3) 57 | #define LOAD_MSG_8_3(b0, b1) b0 = _mm_set_epi64x(m13, m12); b1 = _mm_set_epi64x(m10, m1) 58 | #define LOAD_MSG_8_4(b0, b1) b0 = _mm_set_epi64x(m7, m2); b1 = _mm_set_epi64x(m5, m4) 59 | #define LOAD_MSG_9_1(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m1, m7) 60 | #define LOAD_MSG_9_2(b0, b1) b0 = _mm_set_epi64x(m4, m2); b1 = _mm_set_epi64x(m5, m6) 61 | #define LOAD_MSG_9_3(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m13, m3) 62 | #define LOAD_MSG_9_4(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m0, m12) 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /blake2bf/x86_64/makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-O2 -Wall -Wextra -pedantic -Wno-long-long -fpic 3 | 4 | UNAME := $(shell uname) 5 | 6 | all: libblake2bf.so libblake2bf.dylib 7 | 8 | compile: blake2b.c 9 | $(CC) blake2b.c -c $(CFLAGS) 10 | 11 | libblake2bf.so: blake2b.o 12 | $(CC) -o $@ -shared $(CFLAGS) blake2b.o 13 | 14 | libblake2bf.dylib: blake2b.o 15 | ifeq ($(UNAME), Darwin) 16 | $(CC) -o $@ -dynamiclib $(CFLAGS) blake2b.o 17 | endif 18 | 19 | 20 | clean: 21 | rm -rf *.o *.dylib *.so 22 | -------------------------------------------------------------------------------- /boringssl/boringssl_jni/Makefile: -------------------------------------------------------------------------------- 1 | # Detect platform and architecture 2 | UNAME_S := $(shell uname -s) 3 | UNAME_M := $(shell uname -m) 4 | 5 | # Determine shared library extension and dynamic link flags 6 | ifeq ($(UNAME_S),Darwin) 7 | LIB_EXT = dylib 8 | JNI_OS_DIR = darwin 9 | CC ?= clang 10 | LDFLAGS = -dynamiclib -undefined dynamic_lookup 11 | else 12 | LIB_EXT = so 13 | JNI_OS_DIR = linux 14 | CC ?= gcc 15 | LDFLAGS = -shared 16 | endif 17 | 18 | # Directories 19 | BUILD_DIR = build 20 | BSSL_DIR = ../google-boringssl 21 | BSSL_BUILD_DIR = $(BSSL_DIR)/build 22 | INCLUDES = -I$(BSSL_DIR)/include -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(JNI_OS_DIR) 23 | 24 | # Flags 25 | CFLAGS = -O2 -fPIC $(INCLUDES) 26 | LIBS = $(BSSL_BUILD_DIR)/libcrypto.a 27 | 28 | # Files 29 | LIB_NAME = libp256verify.$(LIB_EXT) 30 | SRCS = p256_verify.c 31 | OBJS = $(SRCS:.c=.o) 32 | BUILD_OBJS = $(addprefix $(BUILD_DIR)/, $(OBJS)) 33 | BUILD_LIB = $(BUILD_DIR)/$(LIB_NAME) 34 | 35 | # Default target 36 | all: $(BUILD_DIR) $(BUILD_LIB) 37 | 38 | $(BUILD_DIR): 39 | mkdir -p $@ 40 | 41 | $(BUILD_LIB): $(BUILD_OBJS) 42 | $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) 43 | 44 | $(BUILD_DIR)/%.o: %.c | $(BUILD_DIR) 45 | $(CC) $(CFLAGS) -c $< -o $@ 46 | 47 | clean: 48 | rm -rf $(BUILD_DIR) 49 | 50 | .PHONY: all clean 51 | -------------------------------------------------------------------------------- /boringssl/boringssl_jni/p256_verify.c: -------------------------------------------------------------------------------- 1 | #include "p256_verify.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define P256_KEY_LEN 65 12 | #define P256_COORD_LEN 32 13 | 14 | #define RETURN_OK() return 0 15 | #define RETURN_INVALID(msg) do { snprintf(error_message_buf, error_message_buf_len, "%s", msg); return 1; } while (0) 16 | #define RETURN_ERROR(msg) do { snprintf(error_message_buf, error_message_buf_len, "%s", msg); return 2; } while (0) 17 | 18 | int p256_verify( 19 | const char data_hash[], int data_hash_length, 20 | const char signature_r[], const char signature_s[], 21 | const char public_key_data[], 22 | char error_message_buf[], int error_message_buf_len) { 23 | 24 | EC_KEY *ec_key = NULL; 25 | EC_POINT *point = NULL; 26 | ECDSA_SIG *sig = NULL; 27 | BIGNUM *r = NULL, *s = NULL; 28 | const EC_GROUP *group = NULL; 29 | 30 | if (!data_hash || !signature_r || !signature_s || !public_key_data) { 31 | RETURN_ERROR("null input"); 32 | } 33 | 34 | if (data_hash_length != 32) { 35 | RETURN_ERROR("invalid hash length"); 36 | } 37 | 38 | if ((unsigned char)public_key_data[0] != 0x04) { 39 | RETURN_INVALID("public key must start with 0x04"); 40 | } 41 | 42 | group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 43 | if (!group) { 44 | RETURN_ERROR("EC_GROUP allocation failed"); 45 | } 46 | 47 | ec_key = EC_KEY_new(); 48 | if (!ec_key || EC_KEY_set_group(ec_key, group) != 1) { 49 | RETURN_ERROR("EC_KEY init failed"); 50 | } 51 | 52 | point = EC_POINT_new(group); 53 | if (!point) { 54 | RETURN_ERROR("EC_POINT allocation failed"); 55 | } 56 | 57 | if (!EC_POINT_oct2point(group, point, (const uint8_t *)public_key_data, P256_KEY_LEN, NULL)) { 58 | RETURN_INVALID("failed to parse public key point"); 59 | } 60 | 61 | if (!EC_POINT_is_on_curve(group, point, NULL)) { 62 | RETURN_INVALID("public key not on curve"); 63 | } 64 | 65 | if (EC_KEY_set_public_key(ec_key, point) != 1) { 66 | RETURN_ERROR("failed to assign public key to EC_KEY"); 67 | } 68 | 69 | r = BN_bin2bn((const uint8_t *)signature_r, P256_COORD_LEN, NULL); 70 | s = BN_bin2bn((const uint8_t *)signature_s, P256_COORD_LEN, NULL); 71 | if (!r || !s) { 72 | RETURN_ERROR("failed to parse r or s"); 73 | } 74 | 75 | sig = ECDSA_SIG_new(); 76 | if (!sig || ECDSA_SIG_set0(sig, r, s) != 1) { 77 | BN_free(r); 78 | BN_free(s); 79 | RETURN_ERROR("failed to create ECDSA_SIG"); 80 | } 81 | 82 | r = NULL; // ownership transferred to sig 83 | s = NULL; 84 | 85 | int verify_status = ECDSA_do_verify((const uint8_t *)data_hash, data_hash_length, sig, ec_key); 86 | if (verify_status == 1) { 87 | error_message_buf[0] = '\0'; // No error message 88 | RETURN_OK(); 89 | } else if (verify_status == 0) { 90 | RETURN_INVALID("signature verification failed"); 91 | } else { 92 | RETURN_ERROR("internal error during signature verification"); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /boringssl/boringssl_jni/p256_verify.h: -------------------------------------------------------------------------------- 1 | #ifndef P256_VERIFY_H 2 | #define P256_VERIFY_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // Verifies a P-256 signature (r, s) on data_hash using an uncompressed public key. 9 | // All inputs are raw big-endian byte arrays. 10 | // Writes a null-terminated diagnostic message (if any) into error_message_buf (must be at least error_message_buf_len bytes). 11 | // Returns: 0 = OK, 1 = INVALID, 2 = ERROR 12 | int p256_verify( 13 | const char data_hash[], int data_hash_length, 14 | const char signature_r[], const char signature_s[], 15 | const char public_key_data[], 16 | char* error_message_buf, 17 | int error_message_buf_len); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif // P256_VERIFY_H 24 | -------------------------------------------------------------------------------- /boringssl/src/main/java/org/hyperledger/besu/nativelib/boringssl/LibP256Verify.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.boringssl; 2 | 3 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 4 | 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.Arrays; 7 | 8 | public class LibP256Verify { 9 | 10 | public static final boolean ENABLED; 11 | 12 | static { 13 | boolean enabled; 14 | try { 15 | BesuNativeLibraryLoader.registerJNA(LibP256Verify.class, "p256verify"); 16 | enabled = true; 17 | } catch (final Throwable t) { 18 | t.printStackTrace(); 19 | enabled = false; 20 | } 21 | ENABLED = enabled; 22 | } 23 | 24 | // Native method 25 | static native int p256_verify(byte[] data_hash, int data_hash_length, byte[] signature_r, 26 | byte[] signature_s, byte[] public_key_data, byte[] error_message_buf, 27 | int error_message_buf_len); 28 | 29 | // Wrapper result class 30 | public static class Result { 31 | public final int status; 32 | public final String message; 33 | 34 | public Result(int status, String message) { 35 | this.status = status; 36 | this.message = message; 37 | } 38 | } 39 | 40 | // Safe, wrapped version of the native call 41 | final static int ERROR_BUF_SIZE = 256; 42 | 43 | public static Result p256Verify(byte[] input, int inputLength) { 44 | 45 | byte[] errorBuf = new byte[ERROR_BUF_SIZE]; 46 | 47 | if (inputLength != 160) { 48 | return new Result(2, "incorrect input size"); 49 | } 50 | 51 | byte[] dataHash = Arrays.copyOfRange(input, 0, 32); 52 | byte[] signatureR = Arrays.copyOfRange(input, 32, 64); 53 | byte[] signatureS = Arrays.copyOfRange(input, 64, 96); 54 | byte[] uncompressedPubKey = new byte[65]; 55 | // uncompressed point prefix 56 | uncompressedPubKey[0] = 0x04; 57 | System.arraycopy(input, 96, uncompressedPubKey, 1, 64); 58 | 59 | int status = p256_verify( 60 | dataHash, 61 | dataHash.length, 62 | signatureR, 63 | signatureS, 64 | uncompressedPubKey, 65 | errorBuf, 66 | ERROR_BUF_SIZE); 67 | 68 | int nullTerminator = 0; 69 | while (nullTerminator < errorBuf.length && errorBuf[nullTerminator] != 0) { 70 | nullTerminator++; 71 | } 72 | 73 | String message = new String(errorBuf, 0, nullTerminator, StandardCharsets.UTF_8); 74 | return new Result(status, message); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /boringssl/src/main/java/org/hyperledger/besu/nativelib/boringssl/LibP256VerifyJNA.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.boringssl; 2 | 3 | import com.sun.jna.Structure; 4 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 5 | 6 | public class LibP256VerifyJNA { 7 | 8 | public static final boolean ENABLED; 9 | 10 | static { 11 | boolean enabled; 12 | try { 13 | BesuNativeLibraryLoader.registerJNA(LibP256VerifyJNA.class, "p256verify"); 14 | enabled = true; 15 | } catch (final Throwable t) { 16 | t.printStackTrace(); 17 | enabled = false; 18 | } 19 | ENABLED = enabled; 20 | } 21 | 22 | /** 23 | * Original signature : verify_result p256_verify_jna(const char[], const int, const char[], const char[], const char[])
24 | */ 25 | public static native VerifyResultByValue p256_verify_jna(byte[] data_hash, int data_hash_length, byte[] signature_r, byte[] signature_s, byte[] public_key_data); 26 | 27 | @Structure.FieldOrder({"status", "message"}) 28 | public static class VerifyResultByValue extends Structure implements Structure.ByValue { 29 | public int status; // 0 = OK, 1 = INVALID, 2 = ERROR 30 | public String message; // optional diagnostic string 31 | 32 | public VerifyResultByValue() { 33 | super(); 34 | } 35 | 36 | public VerifyResultByValue(int status, String message) { 37 | this.status = status; 38 | this.message = message; 39 | } 40 | } 41 | 42 | // Wrapper result class for consistency with JNI version 43 | public static class Result { 44 | public final int status; 45 | public final String message; 46 | 47 | public Result(int status, String message) { 48 | this.status = status; 49 | this.message = message; 50 | } 51 | } 52 | 53 | // Safe, wrapped version of the native call 54 | public static Result p256Verify(byte[] dataHash, byte[] signatureR, byte[] signatureS, 55 | byte[] publicKey) { 56 | 57 | VerifyResultByValue result = p256_verify_jna(dataHash, dataHash.length, signatureR, signatureS, publicKey); 58 | 59 | return new Result(result.status, result.message != null ? result.message : ""); 60 | } 61 | 62 | /** 63 | * BoringSSL wants a 0x04 type prefix. Upstream Besu should prefix keys since 64 | * EIP-7951 only specifies 64 byte public key. 65 | */ 66 | public static byte[] prefixPublicKey(byte[] pubKeyBytes) { 67 | byte[] prefixed = new byte[1 + pubKeyBytes.length]; 68 | prefixed[0] = 0x04; 69 | System.arraycopy(pubKeyBytes, 0, prefixed, 1, pubKeyBytes.length); 70 | return prefixed; 71 | } 72 | } -------------------------------------------------------------------------------- /boringssl/src/test/java/org/hyperledger/besu/nativelib/boringssl/P256VerifyParameterizedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | package org.hyperledger.besu.nativelib.boringssl; 17 | 18 | import com.google.common.io.CharStreams; 19 | import org.apache.tuweni.bytes.Bytes; 20 | import org.junit.Assume; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.Parameterized; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStreamReader; 27 | import java.util.stream.Collectors; 28 | 29 | import static java.nio.charset.StandardCharsets.UTF_8; 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | @RunWith(Parameterized.class) 33 | public class P256VerifyParameterizedTest { 34 | 35 | @Parameterized.Parameter(0) 36 | public String input; 37 | 38 | @Parameterized.Parameter(1) 39 | public String expectedStatus; 40 | 41 | @Parameterized.Parameter(2) 42 | public String expectedMessage; 43 | 44 | @Parameterized.Parameter(3) 45 | public String notes; 46 | 47 | @Parameterized.Parameters 48 | public static Iterable parameters() throws IOException { 49 | return CharStreams.readLines( 50 | new InputStreamReader( 51 | P256VerifyParameterizedTest.class.getResourceAsStream("p256_verify.csv"), UTF_8)) 52 | .stream() 53 | .map(line -> line.split(",", 7)) 54 | .collect(Collectors.toList()); 55 | } 56 | 57 | @Test 58 | public void shouldCalculateP256VerifyFromCSV() { 59 | // Skip the header row 60 | if ("input".equals(input)) { 61 | return; 62 | } 63 | 64 | Assume.assumeTrue("P256Verify must be enabled", LibP256Verify.ENABLED); 65 | 66 | 67 | // Handle null input case 68 | if (input == null || input.isEmpty()) { 69 | LibP256Verify.Result result = LibP256Verify.p256Verify(null, 0); 70 | int expectedStatusInt = Integer.parseInt(expectedStatus); 71 | assertThat(result.status).as("Test case: %s", notes).isEqualTo(expectedStatusInt); 72 | if (!expectedMessage.isEmpty()) { 73 | assertThat(result.message).as("Error message for test case: %s", notes).isEqualTo(expectedMessage); 74 | } 75 | return; 76 | } 77 | 78 | // Call P256 verify 79 | byte[] inputBytes = Bytes.fromHexString(input).toArrayUnsafe(); 80 | LibP256Verify.Result result = LibP256Verify.p256Verify(inputBytes, inputBytes.length); 81 | 82 | // Parse expected status 83 | int expectedStatusInt = Integer.parseInt(expectedStatus); 84 | 85 | // Verify the result 86 | assertThat(result.status) 87 | .as("Test case: %s", notes) 88 | .isEqualTo(expectedStatusInt); 89 | 90 | // Verify error message if expected 91 | if (!expectedMessage.isEmpty()) { 92 | assertThat(result.message) 93 | .as("Error message for test case: %s", notes) 94 | .isEqualTo(expectedMessage); 95 | } else { 96 | // For successful cases, message should be empty 97 | assertThat(result.message) 98 | .as("Success case should have empty message: %s", notes) 99 | .isEmpty(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /boringssl/src/test/java/org/hyperledger/besu/nativelib/boringssl/P256VerifyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | package org.hyperledger.besu.nativelib.boringssl; 17 | 18 | import org.apache.tuweni.bytes.Bytes; 19 | import org.apache.tuweni.units.bigints.UInt256; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.security.MessageDigest; 24 | import java.security.NoSuchAlgorithmException; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | public class P256VerifyTest { 29 | 30 | final private Bytes data = Bytes.fromHexString( 31 | "c35e2f092553c55772926bdbe87c9796827d17024dbb9233a545366e2e5987dd344deb72df987144b8c6c43bc41b654b94cc856e16b96d7a821c8ec039b503e3d86728c494a967d83011a0e090b5d54cd47f4e366c0912bc808fbb2ea96efac88fb3ebec9342738e225f7c7c2b011ce375b56621a20642b4d36e060db4524af1"); 32 | // implied, but not used: 33 | // final private Bytes privateKey = Bytes.fromHexString("0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813"); 34 | final private Bytes publicKey = Bytes.fromHexString( 35 | "e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8abfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39"); 36 | final private Bytes invalidPublicKey = Bytes.fromHexString( 37 | "f266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8abfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39"); 38 | final private Bytes signatureR = 39 | Bytes.fromHexString("976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db"); 40 | final private Bytes invalidSignatureR = 41 | Bytes.fromHexString("a76d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db"); 42 | final private Bytes signatureS = 43 | Bytes.fromHexString("1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932"); 44 | 45 | private byte[] dataHash; 46 | 47 | @Before 48 | public void setUp() throws NoSuchAlgorithmException { 49 | MessageDigest digest = MessageDigest.getInstance("SHA-256"); 50 | dataHash = digest.digest(data.toArrayUnsafe()); 51 | } 52 | 53 | @Test 54 | public void verifyValidSignatureSucceeds() { 55 | byte[] input = createInput(dataHash, signatureR.toArrayUnsafe(), signatureS.toArrayUnsafe(), publicKey.toArrayUnsafe()); 56 | var res = LibP256Verify.p256Verify(input, input.length); 57 | 58 | assertThat(res.status).isEqualTo(0); 59 | } 60 | 61 | @Test 62 | public void verifyMalleatedSignatureSucceeds() { 63 | var order = 64 | UInt256.fromHexString("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"); 65 | var malleatedSignatureS = order.subtract(UInt256.fromBytes(signatureS)); 66 | 67 | byte[] input = createInput(dataHash, signatureR.toArrayUnsafe(), malleatedSignatureS.toArrayUnsafe(), publicKey.toArrayUnsafe()); 68 | var res = LibP256Verify.p256Verify(input, input.length); 69 | 70 | assertThat(res.status).isEqualTo(0); 71 | } 72 | 73 | @Test 74 | public void verifyShouldReturnErrorIfSignatureIsInvalid() { 75 | byte[] input = createInput(dataHash, invalidSignatureR.toArrayUnsafe(), signatureS.toArrayUnsafe(), publicKey.toArrayUnsafe()); 76 | var res = LibP256Verify.p256Verify(input, input.length); 77 | 78 | assertThat(res.status).isEqualTo(1); 79 | } 80 | 81 | @Test 82 | public void verifyShouldThrowExceptionIfAnyOtherParameterIsInvalid() { 83 | byte[] input = createInput(dataHash, signatureR.toArrayUnsafe(), signatureS.toArrayUnsafe(), invalidPublicKey.toArrayUnsafe()); 84 | var res = LibP256Verify.p256Verify(input, input.length); 85 | 86 | assertThat(res.status).isEqualTo(1); 87 | assertThat(res.message).isEqualTo("failed to parse public key point"); 88 | } 89 | 90 | // Helper method to create 160-byte input array: hash(32) + r(32) + s(32) + pubkey(64) 91 | private byte[] createInput(byte[] hash, byte[] r, byte[] s, byte[] pubkey) { 92 | if (hash.length != 32 || r.length != 32 || s.length != 32 || pubkey.length != 64) { 93 | throw new IllegalArgumentException("Invalid component lengths for input creation"); 94 | } 95 | 96 | byte[] input = new byte[160]; 97 | System.arraycopy(hash, 0, input, 0, 32); 98 | System.arraycopy(r, 0, input, 32, 32); 99 | System.arraycopy(s, 0, input, 64, 32); 100 | System.arraycopy(pubkey, 0, input, 96, 64); 101 | return input; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | allprojects { 17 | apply plugin: 'java-library' 18 | 19 | sourceCompatibility = 21 20 | targetCompatibility = 21 21 | 22 | repositories { 23 | mavenCentral() 24 | maven { 25 | url "https://artifacts.consensys.net/public/maven/maven/" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | plugins { 17 | id 'java-library' 18 | id 'maven-publish' 19 | id 'com.jfrog.artifactory' version '5.2.3' 20 | } 21 | 22 | dependencies { 23 | implementation 'net.java.dev.jna:jna:5.12.1' 24 | } 25 | jar { 26 | archiveBaseName = 'besu-native-common' 27 | includeEmptyDirs = false 28 | manifest { 29 | attributes( 30 | 'Specification-Title': archiveBaseName, 31 | 'Specification-Version': project.version, 32 | 'Implementation-Title': archiveBaseName, 33 | 'Implementation-Version': project.version, 34 | 'Automatic-Module-Name': 'org.hyperledger.besu.nativelib.common' 35 | ) 36 | } 37 | } 38 | 39 | 40 | task sourcesJar(type: Jar, dependsOn: classes) { 41 | archiveBaseName = 'besu-native-common' 42 | archiveClassifier = 'sources' 43 | from sourceSets.main.allSource 44 | } 45 | 46 | task javadocJar(type: Jar, dependsOn: javadoc) { 47 | archiveBaseName = 'besu-native-common' 48 | archiveClassifier = 'javadoc' 49 | from javadoc.destinationDir 50 | } 51 | 52 | publishing { 53 | publications { 54 | mavenJava(MavenPublication) { 55 | groupId "org.hyperledger.besu" 56 | artifactId 'besu-native-common' 57 | version "${project.version}" 58 | 59 | from components.java 60 | artifact sourcesJar 61 | artifact javadocJar 62 | 63 | pom { 64 | name = "Besu Native - ${project.name}" 65 | description = 'Shared lib for besu-native implementations' 66 | url = 'http://github.com/hyperledger/besu-native' 67 | licenses { 68 | license { 69 | name = 'The Apache License, Version 2.0' 70 | url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 71 | } 72 | } 73 | scm { 74 | connection = 'scm:git:git://github.com/hyperledger/besu-native.git' 75 | developerConnection = 'scm:git:ssh://github.com/hyperledger/besu-native.git' 76 | url = 'https://github.com/hyperledger/besu-native' 77 | } 78 | } 79 | } 80 | } 81 | } 82 | 83 | def artifactoryUser = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : System.getenv('ARTIFACTORY_USER') 84 | def artifactoryKey = project.hasProperty('artifactoryApiKey') ? project.property('artifactoryApiKey') : System.getenv('ARTIFACTORY_KEY') 85 | def artifactoryRepo = System.getenv('ARTIFACTORY_REPO') ?: 'besu-maven' 86 | def artifactoryOrg = System.getenv('ARTIFACTORY_ORG') ?: 'hyperledger' 87 | 88 | artifactory { 89 | contextUrl = "https://hyperledger.jfrog.io/${artifactoryOrg}" 90 | publish { 91 | repository { 92 | repoKey = artifactoryRepo 93 | username = artifactoryUser 94 | password = artifactoryKey 95 | } 96 | defaults { 97 | publications('mavenJava') 98 | publishArtifacts = true 99 | publishPom = true 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /constantine/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-library' 3 | id 'maven-publish' 4 | id 'com.jfrog.artifactory' version '5.2.3' 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | implementation project(':common') 13 | implementation 'net.java.dev.jna:jna:5.12.1' 14 | testImplementation 'com.google.guava:guava:31.1-jre' 15 | testImplementation 'io.tmio:tuweni-bytes:2.4.2' 16 | testImplementation 'junit:junit:4.13.2' 17 | } 18 | 19 | java { 20 | toolchain { 21 | languageVersion = JavaLanguageVersion.of(21) 22 | } 23 | } 24 | 25 | tasks.withType(JavaCompile) { 26 | options.encoding = 'UTF-8' 27 | } 28 | 29 | task macArmLibCopy(type: Copy) { 30 | from "build/darwin-aarch64/lib/libconstantinebindings.dylib" 31 | into 'build/resources/main/lib/aarch64' 32 | } 33 | 34 | task macLibCopy(type: Copy) { 35 | from "build/darwin-x86-64/lib/libconstantinebindings.dylib" 36 | into 'build/resources/main/lib/x86-64' 37 | } 38 | 39 | task linuxLibCopy(type: Copy) { 40 | from "build/linux-gnu-x86_64/lib/libconstantinebindings.so" 41 | into 'build/resources/main/lib/x86-64' 42 | 43 | } 44 | 45 | task linuxArm64LibCopy(type: Copy) { 46 | from "build/linux-gnu-aarch64/lib/libconstantinebindings.so" 47 | into 'build/resources/main/lib/aarch64' 48 | } 49 | 50 | processResources.dependsOn macArmLibCopy, macLibCopy, linuxLibCopy, linuxArm64LibCopy 51 | 52 | test { 53 | // Check if the OS architecture is riscv64 54 | if (System.getProperty("os.arch").equals("riscv64")) { 55 | // Skip for riscv64 since we are not building constantine for riscv64 yet 56 | enabled = false 57 | } else { 58 | // environment 'LD_LIBRARY_PATH', "${System.env.LD_LIBRARY_PATH}:build/resources/main/linux-gnu-x86_64" 59 | systemProperty 'jna.library.path', file('build/resources/main/linux-gnu-x86_64').absolutePath 60 | dependsOn macArmLibCopy, macLibCopy, linuxLibCopy, linuxArm64LibCopy 61 | } 62 | } 63 | 64 | jar { 65 | archiveBaseName = 'besu-native-constantine' 66 | includeEmptyDirs = false 67 | manifest { 68 | attributes( 69 | 'Specification-Title': archiveBaseName, 70 | 'Specification-Version': project.version, 71 | 'Implementation-Title': archiveBaseName, 72 | 'Implementation-Version': project.version, 73 | 'Automatic-Module-Name': 'org.hyperledger.besu.nativelib.constantine' 74 | ) 75 | } 76 | } 77 | 78 | task sourcesJar(type: Jar, dependsOn: classes) { 79 | archiveBaseName = 'besu-native-constantine' 80 | archiveClassifier = 'sources' 81 | from sourceSets.main.allSource 82 | } 83 | 84 | task javadocJar(type: Jar, dependsOn: javadoc) { 85 | archiveBaseName = 'besu-native-constantine' 86 | archiveClassifier = 'javadoc' 87 | from javadoc.destinationDir 88 | } 89 | 90 | publishing { 91 | publications { 92 | mavenJava(MavenPublication) { 93 | groupId "org.hyperledger.besu" 94 | artifactId 'constantine' 95 | version "${project.version}" 96 | 97 | from components.java 98 | artifact sourcesJar 99 | artifact javadocJar 100 | 101 | pom { 102 | name = "Besu Native - ${project.name}" 103 | description = 'Adapter for native constantine library' 104 | url = 'http://github.com/hyperledger/besu-native' 105 | licenses { 106 | license { 107 | name = 'The Apache License, Version 2.0' 108 | url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 109 | } 110 | } 111 | scm { 112 | connection = 'scm:git:git://github.com/hyperledger/besu-native.git' 113 | developerConnection = 'scm:git:ssh://github.com/hyperledger/besu-native.git' 114 | url = 'https://github.com/hyperledger/besu-native' 115 | } 116 | } 117 | } 118 | } 119 | } 120 | 121 | def artifactoryUser = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : System.getenv('ARTIFACTORY_USER') 122 | def artifactoryKey = project.hasProperty('artifactoryApiKey') ? project.property('artifactoryApiKey') : System.getenv('ARTIFACTORY_KEY') 123 | def artifactoryRepo = System.getenv('ARTIFACTORY_REPO') ?: 'besu-maven' 124 | def artifactoryOrg = System.getenv('ARTIFACTORY_ORG') ?: 'hyperledger' 125 | 126 | artifactory { 127 | contextUrl = "https://hyperledger.jfrog.io/${artifactoryOrg}" 128 | publish { 129 | repository { 130 | repoKey = artifactoryRepo 131 | username = artifactoryUser 132 | password = artifactoryKey 133 | } 134 | defaults { 135 | publications('mavenJava') 136 | publishArtifacts = true 137 | publishPom = true 138 | } 139 | } 140 | } 141 | 142 | test { 143 | useJUnit() 144 | } 145 | -------------------------------------------------------------------------------- /constantine/jna_ethereum_evm_precompiles.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void printByteArray(const char* label, const byte* array, size_t len) { 5 | printf("%s: [", label); 6 | for (size_t i = 0; i < len; i++) { 7 | printf("%02x", array[i]); 8 | if (i < len - 1) { 9 | printf(", "); 10 | } 11 | } 12 | printf("]\n"); 13 | } 14 | 15 | // BN254 functions 16 | int bn254_g1add(byte* r, int r_len, const byte* inputs, int inputs_len) { 17 | return (int) ctt_eth_evm_bn254_g1add(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 18 | } 19 | 20 | int bn254_g1mul(byte* r, int r_len, const byte* inputs, int inputs_len) { 21 | return (int) ctt_eth_evm_bn254_g1mul(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 22 | } 23 | 24 | int bn254_pairingCheck(byte* r, int r_len, const byte* inputs, int inputs_len) { 25 | return (int) ctt_eth_evm_bn254_ecpairingcheck(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 26 | } 27 | 28 | // BLS12-381 functions 29 | int bls12381_g1add(byte* r, int r_len, const byte* inputs, int inputs_len) { 30 | return (int) ctt_eth_evm_bls12381_g1add(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 31 | } 32 | 33 | int bls12381_g2add(byte* r, int r_len, const byte* inputs, int inputs_len) { 34 | return (int) ctt_eth_evm_bls12381_g2add(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 35 | } 36 | 37 | int bls12381_g1mul(byte* r, int r_len, const byte* inputs, int inputs_len) { 38 | return (int) ctt_eth_evm_bls12381_g1mul(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 39 | } 40 | 41 | int bls12381_g2mul(byte* r, int r_len, const byte* inputs, int inputs_len) { 42 | return (int) ctt_eth_evm_bls12381_g2mul(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 43 | } 44 | 45 | int bls12381_g1msm(byte* r, int r_len, const byte* inputs, int inputs_len) { 46 | return (int) ctt_eth_evm_bls12381_g1msm(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 47 | } 48 | 49 | int bls12381_g2msm(byte* r, int r_len, const byte* inputs, int inputs_len) { 50 | return (int) ctt_eth_evm_bls12381_g2msm(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 51 | } 52 | 53 | int bls12381_pairingCheck(byte* r, int r_len, const byte* inputs, int inputs_len) { 54 | return (int) ctt_eth_evm_bls12381_pairingcheck(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 55 | } 56 | 57 | int bls12381_mapFpToG1(byte* r, int r_len, const byte* inputs, int inputs_len) { 58 | return (int) ctt_eth_evm_bls12381_map_fp_to_g1(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 59 | } 60 | 61 | int bls12381_mapFp2ToG2(byte* r, int r_len, const byte* inputs, int inputs_len) { 62 | return (int) ctt_eth_evm_bls12381_map_fp2_to_g2(r, (ptrdiff_t)r_len, inputs, (ptrdiff_t)inputs_len); 63 | } -------------------------------------------------------------------------------- /constantine/src/main/java/org/hyperledger/besu/nativelib/constantine/LibConstantineEIP196.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 4 | 5 | public class LibConstantineEIP196 { 6 | public static final boolean ENABLED; 7 | 8 | static { 9 | boolean enabled; 10 | try { 11 | BesuNativeLibraryLoader.registerJNA(LibConstantineEIP196.class, "constantinebindings"); 12 | enabled = true; 13 | } catch (final Throwable t) { 14 | t.printStackTrace(); 15 | enabled = false; 16 | } 17 | ENABLED = enabled; 18 | } 19 | 20 | public static native int bn254_g1add(byte[] r, int r_len, byte[] inputs, int inputs_len); 21 | public static native int bn254_g1mul(byte[] r, int r_len, byte[] inputs, int inputs_len); 22 | public static native int bn254_pairingCheck(byte[] r, int r_len, byte[] inputs, int inputs_len); 23 | 24 | public static byte[] add(byte[] inputs) { 25 | byte[] result = new byte[64]; 26 | int status = bn254_g1add(result, result.length, inputs, inputs.length); 27 | if (status != 0) { 28 | throw new RuntimeException("ctt_eth_evm_bn254_g1add failed with status: " + status); 29 | } 30 | return result; 31 | } 32 | 33 | public static byte[] mul(byte[] inputs) { 34 | byte[] result = new byte[64]; 35 | int status = bn254_g1mul(result, result.length, inputs, inputs.length); 36 | if (status != 0) { 37 | throw new RuntimeException("ctt_eth_evm_bn254_g1mul failed with status: " + status); 38 | } 39 | return result; 40 | } 41 | 42 | public static byte[] pairingCheck(byte[] inputs) { 43 | byte[] result = new byte[32]; 44 | int status = bn254_pairingCheck(result, result.length, inputs, inputs.length); 45 | if (status != 0) { 46 | throw new RuntimeException("ctt_eth_evm_bn254_pairingCheck failed with status: " + status); 47 | } 48 | return result; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /constantine/src/main/java/org/hyperledger/besu/nativelib/constantine/LibConstantineEIP2537.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 4 | 5 | public class LibConstantineEIP2537 { 6 | public static final boolean ENABLED; 7 | 8 | static { 9 | boolean enabled; 10 | try { 11 | BesuNativeLibraryLoader.registerJNA(LibConstantineEIP2537.class, "constantinebindings"); 12 | enabled = true; 13 | } catch (final Throwable t) { 14 | t.printStackTrace(); 15 | enabled = false; 16 | } 17 | ENABLED = enabled; 18 | } 19 | 20 | public static native int bls12381_g1add(byte[] r, int r_len, byte[] inputs, int inputs_len); 21 | public static native int bls12381_g2add(byte[] r, int r_len, byte[] inputs, int inputs_len); 22 | public static native int bls12381_g1mul(byte[] r, int r_len, byte[] inputs, int inputs_len); 23 | public static native int bls12381_g2mul(byte[] r, int r_len, byte[] inputs, int inputs_len); 24 | public static native int bls12381_g1msm(byte[] r, int r_len, byte[] inputs, int inputs_len); 25 | public static native int bls12381_g2msm(byte[] r, int r_len, byte[] inputs, int inputs_len); 26 | public static native int bls12381_pairingCheck(byte[] r, int r_len, byte[] inputs, int inputs_len); 27 | public static native int bls12381_mapFpToG1(byte[] r, int r_len, byte[] inputs, int inputs_len); 28 | public static native int bls12381_mapFp2ToG2(byte[] r, int r_len, byte[] inputs, int inputs_len); 29 | 30 | public static byte[] g1add(byte[] inputs) { 31 | byte[] result = new byte[128]; 32 | int status = bls12381_g1add(result, result.length, inputs, inputs.length); 33 | if (status != 0) { 34 | throw new RuntimeException("eth_evm_bls12381_g1add failed with status: " + status); 35 | } 36 | return result; 37 | } 38 | 39 | public static byte[] g2add(byte[] inputs) { 40 | byte[] result = new byte[256]; 41 | int status = bls12381_g2add(result, result.length, inputs, inputs.length); 42 | if (status != 0) { 43 | throw new RuntimeException("eth_evm_bls12381_g2add failed with status: " + status); 44 | } 45 | return result; 46 | } 47 | 48 | public static byte[] g1mul(byte[] inputs) { 49 | byte[] result = new byte[128]; 50 | int status = bls12381_g1mul(result, result.length, inputs, inputs.length); 51 | if (status != 0) { 52 | throw new RuntimeException("eth_evm_bls12381_g1mul failed with status: " + status); 53 | } 54 | return result; 55 | } 56 | 57 | public static byte[] g2mul(byte[] inputs) { 58 | byte[] result = new byte[256]; 59 | int status = bls12381_g2mul(result, result.length, inputs, inputs.length); 60 | if (status != 0) { 61 | throw new RuntimeException("eth_evm_bls12381_g2mul failed with status: " + status); 62 | } 63 | return result; 64 | } 65 | 66 | public static byte[] g1msm(byte[] inputs) { 67 | byte[] result = new byte[128]; 68 | int status = bls12381_g1msm(result, result.length, inputs, inputs.length); 69 | if (status != 0) { 70 | throw new RuntimeException("eth_evm_bls12381_g1msm failed with status: " + status); 71 | } 72 | return result; 73 | } 74 | 75 | public static byte[] g2msm(byte[] inputs) { 76 | byte[] result = new byte[256]; 77 | int status = bls12381_g2msm(result, result.length, inputs, inputs.length); 78 | if (status != 0) { 79 | throw new RuntimeException("eth_evm_bls12381_g2msm failed with status: " + status); 80 | } 81 | return result; 82 | } 83 | 84 | public static byte[] pairingCheck(byte[] inputs) { 85 | byte[] result = new byte[32]; 86 | int status = bls12381_pairingCheck(result, result.length, inputs, inputs.length); 87 | if (status != 0) { 88 | throw new RuntimeException("eth_evm_bls12381_pairingcheck failed with status: " + status); 89 | } 90 | return result; 91 | } 92 | 93 | public static byte[] mapFpToG1(byte[] inputs) { 94 | byte[] result = new byte[128]; 95 | int status = bls12381_mapFpToG1(result, result.length, inputs, inputs.length); 96 | if (status != 0) { 97 | throw new RuntimeException("eth_evm_bls12381_map_fp_to_g1 failed with status: " + status); 98 | } 99 | return result; 100 | } 101 | 102 | public static byte[] mapFp2ToG2(byte[] inputs) { 103 | byte[] result = new byte[256]; 104 | int status = bls12381_mapFp2ToG2(result, result.length, inputs, inputs.length); 105 | if (status != 0) { 106 | throw new RuntimeException("eth_evm_bls12381_map_fp2_to_g2 failed with status: " + status); 107 | } 108 | return result; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP196G1AddTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP196G1AddTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP196G1AddTest.class.getResourceAsStream("/eip196_g1_add.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | // skip the header row 46 | return; 47 | } 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | 50 | byte[] result = new byte[64]; 51 | int status = LibConstantineEIP196.bn254_g1add(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty", new byte[64], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if(actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 62 | assertTrue("Notes should be empty", notes.isEmpty()); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP196G1MulTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | 21 | @RunWith(Parameterized.class) 22 | public class ConstantineEIP196G1MulTest { 23 | 24 | @Parameterized.Parameter(0) 25 | public String input; 26 | @Parameterized.Parameter(1) 27 | public String expectedResult; 28 | @Parameterized.Parameter(2) 29 | public String expectedGasUsed; 30 | @Parameterized.Parameter(3) 31 | public String notes; 32 | 33 | @Parameterized.Parameters 34 | public static Iterable parameters() throws IOException { 35 | return CharStreams.readLines( 36 | new InputStreamReader( 37 | ConstantineEIP196G1MulTest.class.getResourceAsStream("/eip196_g1_mul.csv"), UTF_8)) 38 | .stream() 39 | .map(line -> line.split(",", 4)) 40 | .collect(Collectors.toList()); 41 | } 42 | 43 | @Test 44 | public void shouldCalculate() { 45 | if ("input".equals(input)) { 46 | // skip the header row 47 | return; 48 | } 49 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 50 | 51 | byte[] result = new byte[64]; 52 | int status = LibConstantineEIP196.bn254_g1mul(result, result.length, inputBytes, inputBytes.length); 53 | 54 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 55 | 56 | if (status != 0) { 57 | assertNotNull("Notes should not be empty", notes); 58 | assertNotEquals("Status should not be success", 0, status); 59 | assertArrayEquals("Result should be empty", new byte[64], result); 60 | } else { 61 | Bytes actualComputation = Bytes.wrap(result); 62 | if(actualComputation.isZero()) actualComputation = Bytes.EMPTY; 63 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 64 | assertTrue("Notes should be empty", notes.isEmpty()); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP196PairingCheckTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP196PairingCheckTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP196PairingCheckTest.class.getResourceAsStream("/eip196_pairing.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; 46 | } 47 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 48 | 49 | byte[] result = new byte[32]; 50 | int status = LibConstantineEIP196.bn254_pairingCheck(result, result.length, inputBytes, inputBytes.length); 51 | 52 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 53 | 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty", new byte[32], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 61 | assertTrue("Notes should be empty", notes.isEmpty()); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537FpToG1Test.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537FpToG1Test { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537FpToG1Test.class.getResourceAsStream("/fp_to_g1.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; // skip header row 46 | } 47 | 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | byte[] result = new byte[96]; // G1 element in BLS12-381 is 96 bytes 50 | 51 | int status = LibConstantineEIP2537.bls12381_mapFpToG1(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty on failure", new byte[96], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | 62 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 63 | assertTrue("Notes should be empty on success", notes.isEmpty()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537G1AddTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537G1AddTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537G1AddTest.class.getResourceAsStream("/g1_add.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | // skip the header row 46 | return; 47 | } 48 | 49 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 50 | 51 | // Allocate buffer for the result of G1 add, size 96 for BLS12-381 G1 element 52 | byte[] result = new byte[96]; 53 | 54 | // Call the native G1 add function for EIP2537 55 | int status = LibConstantineEIP2537.bls12381_g1add(result, result.length, inputBytes, inputBytes.length); 56 | 57 | // Convert the expected result to Bytes object 58 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 59 | 60 | // Check the status and result based on the computation 61 | if (status != 0) { 62 | assertNotNull("Notes should not be empty", notes); // Check if error notes are present 63 | assertNotEquals("Status should not be success", 0, status); // Ensure the status is not success 64 | assertArrayEquals("Result should be empty on failure", new byte[96], result); // Ensure result is empty on failure 65 | } else { 66 | // If the status is 0 (success), wrap the result in a Bytes object and compare with expected result 67 | Bytes actualComputation = Bytes.wrap(result); 68 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; // Handle zero computation 69 | 70 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); // Ensure result matches 71 | assertTrue("Notes should be empty on success", notes.isEmpty()); // Ensure no notes on success 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537G1MsmTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537G1MsmTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537G1MsmTest.class.getResourceAsStream("/g1_multiexp.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; // skip header row 46 | } 47 | 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | byte[] result = new byte[96]; // G1 element in BLS12-381 is 96 bytes 50 | 51 | int status = LibConstantineEIP2537.bls12381_g1msm(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty on failure", new byte[96], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | 62 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 63 | assertTrue("Notes should be empty on success", notes.isEmpty()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537G1MulTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537G1MulTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537G1MulTest.class.getResourceAsStream("/g1_mul.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; // skip header row 46 | } 47 | 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | byte[] result = new byte[96]; // G1 element in BLS12-381 is 96 bytes 50 | 51 | int status = LibConstantineEIP2537.bls12381_g1mul(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty on failure", new byte[96], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | 62 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 63 | assertTrue("Notes should be empty on success", notes.isEmpty()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537G2AddTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537G2AddTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537G2AddTest.class.getResourceAsStream("/g2_add.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; // skip header row 46 | } 47 | 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | byte[] result = new byte[192]; // G2 element is 192 bytes in BLS12-381 50 | 51 | int status = LibConstantineEIP2537.bls12381_g2add(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty on failure", new byte[192], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | 62 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 63 | assertTrue("Notes should be empty on success", notes.isEmpty()); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537G2MsmTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537G2MsmTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537G2MsmTest.class.getResourceAsStream("/g2_multiexp.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; // skip header row 46 | } 47 | 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | byte[] result = new byte[192]; // G2 element is 192 bytes in BLS12-381 50 | 51 | int status = LibConstantineEIP2537.bls12381_g2msm(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty on failure", new byte[192], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | 62 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 63 | assertTrue("Notes should be empty on success", notes.isEmpty()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537G2MulTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.io.CharStreams; 4 | import org.apache.tuweni.bytes.Bytes; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.junit.runners.Parameterized; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.stream.Collectors; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | import static org.junit.Assert.assertArrayEquals; 15 | import static org.junit.Assert.assertEquals; 16 | import static org.junit.Assert.assertNotEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | @RunWith(Parameterized.class) 21 | public class ConstantineEIP2537G2MulTest { 22 | 23 | @Parameterized.Parameter(0) 24 | public String input; 25 | @Parameterized.Parameter(1) 26 | public String expectedResult; 27 | @Parameterized.Parameter(2) 28 | public String expectedGasUsed; 29 | @Parameterized.Parameter(3) 30 | public String notes; 31 | 32 | @Parameterized.Parameters 33 | public static Iterable parameters() throws IOException { 34 | return CharStreams.readLines( 35 | new InputStreamReader( 36 | ConstantineEIP2537G2MulTest.class.getResourceAsStream("/g2_mul.csv"), UTF_8)) 37 | .stream() 38 | .map(line -> line.split(",", 4)) 39 | .collect(Collectors.toList()); 40 | } 41 | 42 | @Test 43 | public void shouldCalculate() { 44 | if ("input".equals(input)) { 45 | return; // skip header row 46 | } 47 | 48 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 49 | byte[] result = new byte[192]; // G2 element is 192 bytes in BLS12-381 50 | 51 | int status = LibConstantineEIP2537.bls12381_g2mul(result, result.length, inputBytes, inputBytes.length); 52 | 53 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 54 | if (status != 0) { 55 | assertNotNull("Notes should not be empty", notes); 56 | assertNotEquals("Status should not be success", 0, status); 57 | assertArrayEquals("Result should be empty on failure", new byte[192], result); 58 | } else { 59 | Bytes actualComputation = Bytes.wrap(result); 60 | if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; 61 | 62 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); 63 | assertTrue("Notes should be empty on success", notes.isEmpty()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/ConstantineEIP2537PairingCheckTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import com.google.common.collect.Streams; 4 | import com.google.common.io.CharStreams; 5 | import org.apache.tuweni.bytes.Bytes; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.junit.runners.Parameterized; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.util.stream.Collectors; 13 | 14 | import static java.nio.charset.StandardCharsets.UTF_8; 15 | import static org.junit.Assert.assertArrayEquals; 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertNotEquals; 18 | import static org.junit.Assert.assertNotNull; 19 | import static org.junit.Assert.assertTrue; 20 | 21 | @RunWith(Parameterized.class) 22 | public class ConstantineEIP2537PairingCheckTest { 23 | 24 | @Parameterized.Parameter(0) 25 | public String input; 26 | @Parameterized.Parameter(1) 27 | public String expectedResult; 28 | @Parameterized.Parameter(2) 29 | public String expectedGasUsed; 30 | @Parameterized.Parameter(3) 31 | public String notes; 32 | 33 | @Parameterized.Parameters 34 | public static Iterable parameters() throws IOException { 35 | return 36 | Streams.concat( 37 | CharStreams.readLines( 38 | new InputStreamReader( 39 | ConstantineEIP2537PairingCheckTest.class.getResourceAsStream("/pairing.csv"), 40 | UTF_8)) 41 | .stream(), 42 | CharStreams.readLines( 43 | new InputStreamReader( 44 | ConstantineEIP2537PairingCheckTest.class.getResourceAsStream( 45 | "/invalid_pairing.csv"), 46 | UTF_8)) 47 | .stream()) 48 | .filter(line -> !line.startsWith("#")) 49 | .map(line -> line.split(",", 4)) 50 | .collect(Collectors.toList()); 51 | } 52 | 53 | @Test 54 | public void shouldCalculatePairingCheck() { 55 | if ("input".equals(input)) { 56 | // skip the header row 57 | return; 58 | } 59 | 60 | byte[] inputBytes = Bytes.fromHexString(this.input).toArrayUnsafe(); 61 | 62 | // Allocate buffer for the result of pairing check, expected to be 32 bytes for BLS12-381 pairing check 63 | byte[] result = new byte[32]; 64 | 65 | // Call the native Pairing Check function for EIP2537 66 | int status = LibConstantineEIP2537.bls12381_pairingCheck(result, result.length, inputBytes, inputBytes.length); 67 | 68 | // Convert the expected result to Bytes object 69 | Bytes expectedComputation = expectedResult == null ? null : Bytes.fromHexString(expectedResult); 70 | 71 | // Check the status and result based on the computation 72 | if (status != 0) { 73 | assertNotNull("Notes should not be empty", notes); // Check if error notes are present 74 | assertNotEquals("Status should not be success", 0, status); // Ensure the status is not success 75 | assertArrayEquals("Result should be empty on failure", new byte[32], result); // Ensure result is empty on failure 76 | } else { 77 | // If the status is 0 (success), wrap the result in a Bytes object and compare with expected result 78 | Bytes actualComputation = Bytes.wrap(result); 79 | // if (actualComputation.isZero()) actualComputation = Bytes.EMPTY; // Handle zero computation 80 | 81 | assertEquals("Computed result should match expected result", expectedComputation, actualComputation); // Ensure result matches 82 | assertTrue("Notes should be empty on success", notes.isEmpty()); // Ensure no notes on success 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/LibConstantineEIP196Test.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | import static org.junit.Assert.assertNotNull; 7 | 8 | public class LibConstantineEIP196Test { 9 | 10 | @Test 11 | public void testG1Add() { 12 | byte[] inputs = new byte[128]; 13 | 14 | byte[] result = LibConstantineEIP196.add(inputs); 15 | assertNotNull("Result array should not be null", result); 16 | assertEquals("Result array length should be 64", 64, result.length); 17 | } 18 | 19 | @Test 20 | public void testG1Mul() { 21 | byte[] inputs = new byte[96]; 22 | 23 | byte[] result = LibConstantineEIP196.mul(inputs); 24 | assertNotNull("Result array should not be null", result); 25 | assertEquals("Result array length should be 64", 64, result.length); 26 | } 27 | 28 | @Test 29 | public void testPairingCheck() { 30 | byte[] inputs = new byte[0]; 31 | 32 | byte[] result = LibConstantineEIP196.pairingCheck(inputs); 33 | assertNotNull("Result array should not be null", result); 34 | assertEquals("Result array length should be 32", 32, result.length); 35 | assertEquals("The last byte of the result should be 1", 1, result[31]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /constantine/src/test/java/org/hyperledger/besu/nativelib/constantine/LibConstantineEIP2537Test.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.constantine; 2 | 3 | import org.junit.Test; 4 | 5 | import java.nio.charset.StandardCharsets; 6 | import java.util.Arrays; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | import static org.junit.Assert.assertNotNull; 10 | 11 | public class LibConstantineEIP2537Test { 12 | 13 | @Test 14 | public void testG1Add() { 15 | byte[] inputs = new byte[256]; 16 | byte[] result = LibConstantineEIP2537.g1add(inputs); 17 | assertNotNull("Result array should not be null", result); 18 | assertEquals("Result array length should be 128", 128, result.length); 19 | } 20 | 21 | @Test 22 | public void testG2Add() { 23 | byte[] inputs = new byte[512]; 24 | 25 | byte[] result = LibConstantineEIP2537.g2add(inputs); 26 | assertNotNull("Result array should not be null", result); 27 | assertEquals("Result array length should be 256", 256, result.length); 28 | } 29 | 30 | @Test 31 | public void testG1Mul() { 32 | byte[] inputs = new byte[160]; 33 | 34 | byte[] result = LibConstantineEIP2537.g1mul(inputs); 35 | assertNotNull("Result array should not be null", result); 36 | assertEquals("Result array length should be 128", 128, result.length); 37 | } 38 | 39 | @Test 40 | public void testG2Mul() { 41 | byte[] inputs = new byte[288]; 42 | 43 | byte[] result = LibConstantineEIP2537.g2mul(inputs); 44 | assertNotNull("Result array should not be null", result); 45 | assertEquals("Result array length should be 256", 256, result.length); 46 | } 47 | 48 | @Test 49 | public void testG1Msm() { 50 | byte[] inputs = new byte[160]; 51 | 52 | byte[] result = LibConstantineEIP2537.g1msm(inputs); 53 | assertNotNull("Result array should not be null", result); 54 | assertEquals("Result array length should be 128", 128, result.length); 55 | } 56 | 57 | @Test 58 | public void testG2Msm() { 59 | byte[] inputs = new byte[288]; 60 | 61 | byte[] result = LibConstantineEIP2537.g2msm(inputs); 62 | assertNotNull("Result array should not be null", result); 63 | assertEquals("Result array length should be 256", 256, result.length); 64 | } 65 | 66 | @Test 67 | public void testPairingCheck() { 68 | byte[] inputs = new byte[384]; 69 | 70 | byte[] result = LibConstantineEIP2537.pairingCheck(inputs); 71 | assertNotNull("Result array should not be null", result); 72 | assertEquals("Result array length should be 32", 32, result.length); 73 | assertEquals("The last byte of the result should be 1", 1, result[31]); 74 | } 75 | 76 | @Test 77 | public void testMapFpToG1() { 78 | byte[] inputs = new byte[64]; 79 | 80 | byte[] result = LibConstantineEIP2537.mapFpToG1(inputs); 81 | assertNotNull("Result array should not be null", result); 82 | assertEquals("Result array length should be 128", 128, result.length); 83 | } 84 | 85 | @Test 86 | public void testMapFp2ToG2() { 87 | byte[] inputs = new byte[128]; 88 | 89 | byte[] result = LibConstantineEIP2537.mapFp2ToG2(inputs); 90 | assertNotNull("Result array should not be null", result); 91 | assertEquals("Result array length should be 256", 256, result.length); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /gnark/gnark-jni/README.md: -------------------------------------------------------------------------------- 1 | # Gnark-JNI 2 | 3 | Wraps gnark-crypto in a suitable interface for besu to use with JNA/JNI 4 | 5 | # Test Data Generator 6 | 7 | helper to generate random data for ECC precompiles, run via: 8 | 9 | `go run gnark-test-data.go` 10 | -------------------------------------------------------------------------------- /gnark/gnark-jni/gnark-jni.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "C" 4 | import ( 5 | "unsafe" 6 | 7 | mimcBls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/mimc" 8 | mimcBn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" 9 | ) 10 | 11 | func MiMCBls12377Hash(b []byte) []byte { 12 | hasher := mimcBls12377.NewMiMC() 13 | hasher.Write(b) 14 | return hasher.Sum(nil) 15 | } 16 | 17 | func MiMCBn254Hash(b []byte) []byte { 18 | hasher := mimcBn254.NewMiMC() 19 | hasher.Write(b) 20 | return hasher.Sum(nil) 21 | } 22 | 23 | //export computeMimcBn254 24 | func computeMimcBn254(input *C.char, inputLength C.int, output *C.char) C.int { 25 | inputSlice := C.GoBytes(unsafe.Pointer(input), inputLength) 26 | outputSlice := (*[32]byte)(unsafe.Pointer(output))[:] 27 | hash := MiMCBn254Hash(inputSlice) 28 | copy(outputSlice, hash) 29 | return C.int(len(hash)) 30 | } 31 | 32 | //export computeMimcBls12377 33 | func computeMimcBls12377(input *C.char, inputLength C.int, output *C.char) C.int { 34 | inputSlice := C.GoBytes(unsafe.Pointer(input), inputLength) 35 | outputSlice := (*[32]byte)(unsafe.Pointer(output))[:] 36 | hash := MiMCBls12377Hash(inputSlice) 37 | copy(outputSlice, hash) 38 | return C.int(len(hash)) 39 | } 40 | 41 | func main() {} 42 | -------------------------------------------------------------------------------- /gnark/gnark-jni/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hyperledger/besu-native 2 | 3 | go 1.22 4 | 5 | toolchain go1.22.4 6 | 7 | require github.com/consensys/gnark-crypto v0.17.0 8 | 9 | require ( 10 | github.com/bits-and-blooms/bitset v1.20.0 // indirect 11 | github.com/consensys/bavard v0.1.29 // indirect 12 | github.com/mmcloughlin/addchain v0.4.0 // indirect 13 | golang.org/x/crypto v0.33.0 // indirect 14 | golang.org/x/sys v0.30.0 // indirect 15 | rsc.io/tmplfunc v0.0.3 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /gnark/gnark-jni/go.sum: -------------------------------------------------------------------------------- 1 | github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= 2 | github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= 3 | github.com/consensys/bavard v0.1.29 h1:fobxIYksIQ+ZSrTJUuQgu+HIJwclrAPcdXqd7H2hh1k= 4 | github.com/consensys/bavard v0.1.29/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= 5 | github.com/consensys/gnark-crypto v0.17.0 h1:vKDhZMOrySbpZDCvGMOELrHFv/A9mJ7+9I8HEfRZSkI= 6 | github.com/consensys/gnark-crypto v0.17.0/go.mod h1:A2URlMHUT81ifJ0UlLzSlm7TmnE3t7VxEThApdMukJw= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= 10 | github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= 11 | github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= 12 | github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= 13 | github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= 14 | github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= 15 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 16 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 17 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 18 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 19 | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= 20 | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= 21 | golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= 22 | golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 23 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 24 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 25 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 26 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 27 | rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= 28 | rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= 29 | -------------------------------------------------------------------------------- /gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 19 | 20 | /** 21 | * Java interface to gnark 22 | */ 23 | public class LibGnark { 24 | 25 | @SuppressWarnings("WeakerAccess") 26 | public static final boolean ENABLED; 27 | 28 | static { 29 | boolean enabled; 30 | try { 31 | BesuNativeLibraryLoader.registerJNA(LibGnark.class, "gnark_jni"); 32 | enabled = true; 33 | } catch (final Throwable t) { 34 | t.printStackTrace(); 35 | enabled = false; 36 | } 37 | ENABLED = enabled; 38 | } 39 | 40 | public static native int computeMimcBn254( 41 | byte[] i, int i_len, byte[] o); 42 | 43 | public static native int computeMimcBls12377( 44 | byte[] i, int i_len, byte[] o); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnarkEIP196.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.gnark; 2 | 3 | import com.sun.jna.ptr.IntByReference; 4 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 5 | 6 | public class LibGnarkEIP196 { 7 | 8 | public static final int EIP196_PREALLOCATE_FOR_RESULT_BYTES = 128; 9 | public static final int EIP196_PREALLOCATE_FOR_ERROR_BYTES = 256; // includes error string 10 | @SuppressWarnings("WeakerAccess") 11 | public static final byte EIP196_ADD_OPERATION_RAW_VALUE = 1; 12 | public static final byte EIP196_MUL_OPERATION_RAW_VALUE = 2; 13 | public static final byte EIP196_PAIR_OPERATION_RAW_VALUE = 3; 14 | 15 | public static final boolean ENABLED; 16 | 17 | static { 18 | boolean enabled; 19 | try { 20 | BesuNativeLibraryLoader.registerJNA(LibGnarkEIP196.class, "gnark_eip_196"); 21 | enabled = true; 22 | } catch (final Throwable t) { 23 | t.printStackTrace(); 24 | enabled = false; 25 | } 26 | ENABLED = enabled; 27 | } 28 | 29 | /** 30 | * Here as a compatibility shim for the pre-existing matter-labs implementation. 31 | */ 32 | public static int eip196_perform_operation( 33 | byte op, 34 | byte[] i, 35 | int i_len, 36 | byte[] output, 37 | IntByReference o_len, 38 | byte[] err, 39 | IntByReference err_len) { 40 | 41 | int ret = -1; 42 | switch(op) { 43 | case EIP196_ADD_OPERATION_RAW_VALUE: 44 | ret = eip196altbn128G1Add(i, output, err, i_len, o_len, err_len); 45 | break; 46 | case EIP196_MUL_OPERATION_RAW_VALUE: 47 | ret = eip196altbn128G1Mul(i, output, err, i_len, o_len, err_len); 48 | break; 49 | case EIP196_PAIR_OPERATION_RAW_VALUE: 50 | ret = eip196altbn128Pairing(i, output, err, i_len, o_len, err_len); 51 | break; 52 | default: 53 | throw new RuntimeException("Not Implemented EIP-196 operation " + op); 54 | } 55 | 56 | return ret; 57 | } 58 | 59 | public static native int eip196altbn128G1Add( 60 | byte[] input, 61 | byte[] output, 62 | byte[] error, 63 | int inputSize, IntByReference outputSize, IntByReference err_len); 64 | 65 | public static native int eip196altbn128G1Mul( 66 | byte[] input, 67 | byte[] output, 68 | byte[] error, 69 | int inputSize, IntByReference output_len, IntByReference err_len); 70 | 71 | public static native int eip196altbn128Pairing( 72 | byte[] input, 73 | byte[] output, 74 | byte[] error, 75 | int inputSize, IntByReference output_len, IntByReference err_len); 76 | } 77 | -------------------------------------------------------------------------------- /gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnarkUtils.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.gnark; 2 | 3 | public class LibGnarkUtils { 4 | 5 | public static int findFirstTrailingZeroIndex(byte[] array) { 6 | for (int i = array.length - 1; i >= 0; i--) { 7 | if (array[i] != 0) { 8 | return i + 1; // The first trailing zero is after this non-zero byte 9 | } 10 | } 11 | // If all bytes are zero, return 0 12 | return 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128G1AddPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import com.google.common.io.CharStreams; 19 | import com.sun.jna.ptr.IntByReference; 20 | import org.apache.tuweni.bytes.Bytes; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.Parameterized; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStreamReader; 27 | import java.util.stream.Collectors; 28 | 29 | import static java.nio.charset.StandardCharsets.UTF_8; 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | @RunWith(Parameterized.class) 33 | public class AltBN128G1AddPrecompiledContractTest { 34 | 35 | @Parameterized.Parameter(0) 36 | public String input; 37 | @Parameterized.Parameter(1) 38 | public String expectedResult; 39 | @Parameterized.Parameter(2) 40 | public String expectedGasUsed; 41 | @Parameterized.Parameter(3) 42 | public String notes; 43 | 44 | @Parameterized.Parameters 45 | public static Iterable parameters() throws IOException { 46 | return CharStreams.readLines( 47 | new InputStreamReader( 48 | AltBN128G1AddPrecompiledContractTest.class.getResourceAsStream("eip196_g1_add.csv"), UTF_8)) 49 | .stream() 50 | .map(line -> line.split(",", 4)) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | @Test 55 | public void shouldCalculate() { 56 | if ("input".equals(input)) { 57 | // skip the header row 58 | return; 59 | } 60 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 61 | 62 | final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES]; 63 | final IntByReference outputLength = new IntByReference(); 64 | final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES]; 65 | final IntByReference errorLength = new IntByReference(); 66 | 67 | LibGnarkEIP196.eip196_perform_operation(LibGnarkEIP196.EIP196_ADD_OPERATION_RAW_VALUE, input, 68 | input.length, output, outputLength, error, errorLength); 69 | final Bytes expectedComputation = 70 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 71 | if (errorLength.getValue() > 0) { 72 | assertThat(notes).isNotEmpty(); 73 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 74 | assertThat(outputLength.getValue()).isZero(); 75 | } else { 76 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 77 | assertThat(actualComputation).isEqualTo(expectedComputation); 78 | assertThat(notes).isEmpty(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128G1MulPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import com.google.common.io.CharStreams; 19 | import com.sun.jna.ptr.IntByReference; 20 | import org.apache.tuweni.bytes.Bytes; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.Parameterized; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStreamReader; 27 | import java.util.stream.Collectors; 28 | 29 | import static java.nio.charset.StandardCharsets.UTF_8; 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | @RunWith(Parameterized.class) 33 | public class AltBN128G1MulPrecompiledContractTest { 34 | 35 | @Parameterized.Parameter(0) 36 | public String input; 37 | @Parameterized.Parameter(1) 38 | public String expectedResult; 39 | @Parameterized.Parameter(2) 40 | public String expectedGasUsed; 41 | @Parameterized.Parameter(3) 42 | public String notes; 43 | 44 | @Parameterized.Parameters 45 | public static Iterable parameters() throws IOException { 46 | return CharStreams.readLines( 47 | new InputStreamReader( 48 | AltBN128G1MulPrecompiledContractTest.class.getResourceAsStream("eip196_g1_mul.csv"), UTF_8)) 49 | .stream() 50 | .map(line -> line.split(",", 4)) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | @Test 55 | public void shouldCalculate() { 56 | if ("input".equals(input)) { 57 | // skip the header row 58 | return; 59 | } 60 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 61 | 62 | final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES]; 63 | final IntByReference outputLength = new IntByReference(); 64 | final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES]; 65 | final IntByReference errorLength = new IntByReference(); 66 | 67 | LibGnarkEIP196.eip196_perform_operation(LibGnarkEIP196.EIP196_MUL_OPERATION_RAW_VALUE, input, 68 | input.length, output, outputLength, error, errorLength); 69 | final Bytes expectedComputation = 70 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 71 | if (errorLength.getValue() > 0) { 72 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).contains(notes); 73 | assertThat(outputLength.getValue()).isZero(); 74 | } else { 75 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 76 | assertThat(actualComputation).isEqualTo(expectedComputation); 77 | assertThat(notes).isEmpty(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128PairingPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import com.google.common.io.CharStreams; 19 | import com.sun.jna.ptr.IntByReference; 20 | import org.apache.tuweni.bytes.Bytes; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.Parameterized; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStreamReader; 27 | import java.util.stream.Collectors; 28 | 29 | import static java.nio.charset.StandardCharsets.UTF_8; 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | @RunWith(Parameterized.class) 33 | public class AltBN128PairingPrecompiledContractTest { 34 | 35 | @Parameterized.Parameter(0) 36 | public String input; 37 | @Parameterized.Parameter(1) 38 | public String expectedResult; 39 | @Parameterized.Parameter(2) 40 | public String expectedGasUsed; 41 | @Parameterized.Parameter(3) 42 | public String notes; 43 | 44 | @Parameterized.Parameters 45 | public static Iterable parameters() throws IOException { 46 | return CharStreams.readLines( 47 | new InputStreamReader( 48 | AltBN128PairingPrecompiledContractTest.class.getResourceAsStream("eip196_pairing.csv"), UTF_8)) 49 | .stream() 50 | .map(line -> line.split(",", 4)) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | @Test 55 | public void shouldCalculate() { 56 | if ("input".equals(input)) { 57 | // skip the header row 58 | return; 59 | } 60 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 61 | 62 | final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES]; 63 | final IntByReference outputLength = new IntByReference(); 64 | final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES]; 65 | final IntByReference errorLength = new IntByReference(); 66 | 67 | LibGnarkEIP196.eip196_perform_operation( 68 | LibGnarkEIP196.EIP196_PAIR_OPERATION_RAW_VALUE, 69 | input, 70 | input.length, 71 | output, 72 | outputLength, 73 | error, 74 | errorLength); 75 | 76 | final Bytes expectedComputation = 77 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 78 | if (errorLength.getValue() > 0) { 79 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 80 | assertThat(outputLength.getValue()).isZero(); 81 | } else { 82 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 83 | assertThat(actualComputation).isEqualTo(expectedComputation); 84 | assertThat(notes).isEmpty(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12G1AddPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import com.google.common.base.Stopwatch; 19 | import com.google.common.io.CharStreams; 20 | import com.sun.jna.ptr.IntByReference; 21 | import org.apache.tuweni.bytes.Bytes; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.Parameterized; 25 | 26 | import java.io.IOException; 27 | import java.io.InputStreamReader; 28 | import java.util.stream.Collectors; 29 | 30 | import static java.nio.charset.StandardCharsets.UTF_8; 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | @RunWith(Parameterized.class) 34 | public class BLS12G1AddPrecompiledContractTest { 35 | 36 | @Parameterized.Parameter(0) 37 | public String input; 38 | @Parameterized.Parameter(1) 39 | public String expectedResult; 40 | @Parameterized.Parameter(2) 41 | public String expectedGasUsed; 42 | @Parameterized.Parameter(3) 43 | public String notes; 44 | 45 | @Parameterized.Parameters 46 | public static Iterable parameters() throws IOException { 47 | return CharStreams.readLines( 48 | new InputStreamReader( 49 | BLS12G1AddPrecompiledContractTest.class.getResourceAsStream("g1_add.csv"), UTF_8)) 50 | .stream() 51 | .map(line -> line.split(",", 4)) 52 | .collect(Collectors.toList()); 53 | } 54 | 55 | @Test 56 | public void shouldCalculate() { 57 | if ("input".equals(input)) { 58 | // skip the header row 59 | return; 60 | } 61 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 62 | 63 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 64 | final IntByReference outputLength = new IntByReference(); 65 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 66 | final IntByReference errorLength = new IntByReference(); 67 | 68 | LibGnarkEIP2537.eip2537_perform_operation(LibGnarkEIP2537.BLS12_G1ADD_OPERATION_SHIM_VALUE, 69 | input, input.length, output, outputLength, error, errorLength); 70 | 71 | final Bytes expectedComputation = 72 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 73 | if (errorLength.getValue() > 0) { 74 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 75 | assertThat(outputLength.getValue()).isZero(); 76 | } else { 77 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 78 | assertThat(actualComputation).isEqualTo(expectedComputation); 79 | assertThat(notes).isEmpty(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12G1MultiExpPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | // 19 | 20 | import static java.nio.charset.StandardCharsets.UTF_8; 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStreamReader; 25 | import java.util.stream.Collectors; 26 | 27 | import com.google.common.io.CharStreams; 28 | import com.sun.jna.ptr.IntByReference; 29 | import org.apache.tuweni.bytes.Bytes; 30 | import org.junit.Test; 31 | import org.junit.runner.RunWith; 32 | import org.junit.runners.Parameterized; 33 | 34 | @RunWith(Parameterized.class) 35 | public class BLS12G1MultiExpPrecompiledContractTest { 36 | @Parameterized.Parameter(0) 37 | public String input; 38 | @Parameterized.Parameter(1) 39 | public String expectedResult; 40 | @Parameterized.Parameter(2) 41 | public String expectedGasUsed; 42 | @Parameterized.Parameter(3) 43 | public String notes; 44 | 45 | @Parameterized.Parameters 46 | public static Iterable parameters() throws IOException { 47 | return CharStreams.readLines( 48 | new InputStreamReader( 49 | BLS12G1MultiExpPrecompiledContractTest.class.getResourceAsStream("g1_multiexp.csv"), 50 | UTF_8)) 51 | .stream() 52 | .map(line -> line.split(",", 4)) 53 | .collect(Collectors.toList()); 54 | } 55 | 56 | @Test 57 | public void shouldCalculate() { 58 | if ("input".equals(input)) { 59 | // skip the header row 60 | return; 61 | } 62 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 63 | 64 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 65 | final IntByReference outputLength = new IntByReference(); 66 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 67 | final IntByReference errorLength = new IntByReference(); 68 | 69 | LibGnarkEIP2537.eip2537_perform_operation(LibGnarkEIP2537.BLS12_G1MULTIEXP_OPERATION_SHIM_VALUE, 70 | input, input.length, output, outputLength, error, errorLength); 71 | 72 | final Bytes expectedComputation = 73 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 74 | if (errorLength.getValue() > 0) { 75 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 76 | assertThat(outputLength.getValue()).isZero(); 77 | } else { 78 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 79 | assertThat(actualComputation).isEqualTo(expectedComputation); 80 | assertThat(notes).isEmpty(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12G2AddPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import static java.nio.charset.StandardCharsets.UTF_8; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | import java.util.stream.Collectors; 24 | 25 | import com.google.common.base.Stopwatch; 26 | import com.google.common.io.CharStreams; 27 | import com.sun.jna.ptr.IntByReference; 28 | import org.apache.tuweni.bytes.Bytes; 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.junit.runners.Parameterized; 32 | 33 | @RunWith(Parameterized.class) 34 | public class BLS12G2AddPrecompiledContractTest { 35 | 36 | @Parameterized.Parameter(0) 37 | public String input; 38 | @Parameterized.Parameter(1) 39 | public String expectedResult; 40 | @Parameterized.Parameter(2) 41 | public String expectedGasUsed; 42 | @Parameterized.Parameter(3) 43 | public String notes; 44 | 45 | @Parameterized.Parameters 46 | public static Iterable parameters() throws IOException { 47 | return CharStreams.readLines( 48 | new InputStreamReader( 49 | BLS12G2AddPrecompiledContractTest.class.getResourceAsStream("g2_add.csv"), UTF_8)) 50 | .stream() 51 | .map(line -> line.split(",", 4)) 52 | .collect(Collectors.toList()); 53 | } 54 | 55 | @Test 56 | public void shouldCalculate() { 57 | if ("input".equals(input)) { 58 | // skip the header row 59 | return; 60 | } 61 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 62 | 63 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 64 | final IntByReference outputLength = new IntByReference(); 65 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 66 | final IntByReference errorLength = new IntByReference(); 67 | 68 | LibGnarkEIP2537.eip2537_perform_operation( 69 | LibGnarkEIP2537.BLS12_G2ADD_OPERATION_SHIM_VALUE, 70 | input, 71 | input.length, 72 | output, 73 | outputLength, 74 | error, 75 | errorLength); 76 | 77 | final Bytes expectedComputation = 78 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 79 | if (errorLength.getValue() > 0) { 80 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 81 | assertThat(outputLength.getValue()).isZero(); 82 | } else { 83 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 84 | assertThat(actualComputation).isEqualTo(expectedComputation); 85 | assertThat(notes).isEmpty(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12G2MultiExpPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import static java.nio.charset.StandardCharsets.UTF_8; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | import java.util.stream.Collectors; 24 | 25 | import com.google.common.io.CharStreams; 26 | import com.sun.jna.ptr.IntByReference; 27 | import org.apache.tuweni.bytes.Bytes; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.Parameterized; 31 | 32 | @RunWith(Parameterized.class) 33 | public class BLS12G2MultiExpPrecompiledContractTest { 34 | 35 | @Parameterized.Parameter(0) 36 | public String input; 37 | @Parameterized.Parameter(1) 38 | public String expectedResult; 39 | @Parameterized.Parameter(2) 40 | public String expectedGasUsed; 41 | @Parameterized.Parameter(3) 42 | public String notes; 43 | 44 | @Parameterized.Parameters 45 | public static Iterable parameters() throws IOException { 46 | return CharStreams.readLines( 47 | new InputStreamReader( 48 | BLS12G2MultiExpPrecompiledContractTest.class.getResourceAsStream("g2_multiexp.csv"), 49 | UTF_8)) 50 | .stream() 51 | .map(line -> line.split(",", 4)) 52 | .collect(Collectors.toList()); 53 | } 54 | 55 | @Test 56 | public void shouldCalculate() { 57 | if ("input".equals(input)) { 58 | // skip the header row 59 | return; 60 | } 61 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 62 | 63 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 64 | final IntByReference outputLength = new IntByReference(); 65 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 66 | final IntByReference errorLength = new IntByReference(); 67 | 68 | LibGnarkEIP2537.eip2537_perform_operation( 69 | LibGnarkEIP2537.BLS12_G2MULTIEXP_OPERATION_SHIM_VALUE, 70 | input, 71 | input.length, 72 | output, 73 | outputLength, 74 | error, 75 | errorLength); 76 | 77 | final Bytes expectedComputation = 78 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 79 | if (errorLength.getValue() > 0) { 80 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 81 | assertThat(outputLength.getValue()).isZero(); 82 | } else { 83 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 84 | assertThat(actualComputation).isEqualTo(expectedComputation); 85 | assertThat(notes).isEmpty(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12MapFp2ToG2PrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import static java.nio.charset.StandardCharsets.UTF_8; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | import java.util.stream.Collectors; 24 | 25 | import com.google.common.io.CharStreams; 26 | import com.sun.jna.ptr.IntByReference; 27 | import org.apache.tuweni.bytes.Bytes; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.Parameterized; 31 | 32 | @RunWith(Parameterized.class) 33 | public class BLS12MapFp2ToG2PrecompiledContractTest { 34 | @Parameterized.Parameter(0) 35 | public String input; 36 | @Parameterized.Parameter(1) 37 | public String expectedResult; 38 | @Parameterized.Parameter(2) 39 | public String expectedGasUsed; 40 | @Parameterized.Parameter(3) 41 | public String notes; 42 | 43 | @Parameterized.Parameters 44 | public static Iterable parameters() throws IOException { 45 | return CharStreams.readLines( 46 | new InputStreamReader( 47 | BLS12MapFp2ToG2PrecompiledContractTest.class.getResourceAsStream("fp2_to_g2.csv"), 48 | UTF_8)) 49 | .stream() 50 | .map(line -> line.split(",", 4)) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | @Test 55 | public void shouldCalculate() { 56 | if ("input".equals(input)) { 57 | // skip the header row 58 | return; 59 | } 60 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 61 | 62 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 63 | final IntByReference outputLength = new IntByReference(); 64 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 65 | final IntByReference errorLength = new IntByReference(); 66 | 67 | LibGnarkEIP2537.eip2537_perform_operation( 68 | LibGnarkEIP2537.BLS12_MAP_FP2_TO_G2_OPERATION_SHIM_VALUE, 69 | input, 70 | input.length, 71 | output, 72 | outputLength, 73 | error, 74 | errorLength); 75 | 76 | final Bytes expectedComputation = 77 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 78 | if (errorLength.getValue() > 0) { 79 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 80 | assertThat(outputLength.getValue()).isZero(); 81 | } else { 82 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 83 | assertThat(actualComputation).isEqualTo(expectedComputation); 84 | assertThat(notes).isEmpty(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12MapFpToG1PrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import static java.nio.charset.StandardCharsets.UTF_8; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | import java.util.stream.Collectors; 24 | 25 | import com.google.common.io.CharStreams; 26 | import com.sun.jna.ptr.IntByReference; 27 | import org.apache.tuweni.bytes.Bytes; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.Parameterized; 31 | 32 | @RunWith(Parameterized.class) 33 | public class BLS12MapFpToG1PrecompiledContractTest { 34 | @Parameterized.Parameter(0) 35 | public String input; 36 | @Parameterized.Parameter(1) 37 | public String expectedResult; 38 | @Parameterized.Parameter(2) 39 | public String expectedGasUsed; 40 | @Parameterized.Parameter(3) 41 | public String notes; 42 | 43 | @Parameterized.Parameters 44 | public static Iterable parameters() throws IOException { 45 | return CharStreams.readLines( 46 | new InputStreamReader( 47 | BLS12MapFpToG1PrecompiledContractTest.class.getResourceAsStream("fp_to_g1.csv"), 48 | UTF_8)) 49 | .stream() 50 | .map(line -> line.split(",", 4)) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | @Test 55 | public void shouldCalculate() { 56 | if ("input".equals(input)) { 57 | // skip the header row 58 | return; 59 | } 60 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 61 | 62 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 63 | final IntByReference outputLength = new IntByReference(); 64 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 65 | final IntByReference errorLength = new IntByReference(); 66 | 67 | LibGnarkEIP2537.eip2537_perform_operation( 68 | LibGnarkEIP2537.BLS12_MAP_FP_TO_G1_OPERATION_SHIM_VALUE, 69 | input, 70 | input.length, 71 | output, 72 | outputLength, 73 | error, 74 | errorLength); 75 | 76 | final Bytes expectedComputation = 77 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 78 | if (errorLength.getValue() > 0) { 79 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 80 | assertThat(outputLength.getValue()).isZero(); 81 | } else { 82 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 83 | assertThat(actualComputation).isEqualTo(expectedComputation); 84 | assertThat(notes).isEmpty(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/BLS12PairingPrecompiledContractTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import static java.nio.charset.StandardCharsets.UTF_8; 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | import java.io.IOException; 22 | import java.io.InputStreamReader; 23 | import java.util.stream.Collectors; 24 | 25 | import com.google.common.collect.Streams; 26 | import com.google.common.io.CharStreams; 27 | import com.sun.jna.ptr.IntByReference; 28 | import org.apache.tuweni.bytes.Bytes; 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.junit.runners.Parameterized; 32 | 33 | @RunWith(Parameterized.class) 34 | public class BLS12PairingPrecompiledContractTest { 35 | @Parameterized.Parameter(0) 36 | public String input; 37 | @Parameterized.Parameter(1) 38 | public String expectedResult; 39 | @Parameterized.Parameter(2) 40 | public String expectedGasUsed; 41 | @Parameterized.Parameter(3) 42 | public String notes; 43 | 44 | @Parameterized.Parameters 45 | public static Iterable parameters() throws IOException { 46 | return 47 | Streams.concat( 48 | CharStreams.readLines( 49 | new InputStreamReader( 50 | BLS12PairingPrecompiledContractTest.class.getResourceAsStream("pairing.csv"), 51 | UTF_8)) 52 | .stream(), 53 | CharStreams.readLines( 54 | new InputStreamReader( 55 | BLS12PairingPrecompiledContractTest.class.getResourceAsStream( 56 | "invalid_subgroup_for_pairing.csv"), 57 | UTF_8)) 58 | .stream()) 59 | .map(line -> line.split(",", 4)) 60 | .collect(Collectors.toList()); 61 | } 62 | 63 | @Test 64 | public void shouldCalculate() { 65 | if ("input".equals(input)) { 66 | // skip the header row 67 | return; 68 | } 69 | final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe(); 70 | 71 | final byte[] output = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_RESULT_BYTES]; 72 | final IntByReference outputLength = new IntByReference(); 73 | final byte[] error = new byte[LibGnarkEIP2537.EIP2537_PREALLOCATE_FOR_ERROR_BYTES]; 74 | final IntByReference errorLength = new IntByReference(); 75 | 76 | LibGnarkEIP2537.eip2537_perform_operation( 77 | LibGnarkEIP2537.BLS12_PAIR_OPERATION_SHIM_VALUE, 78 | input, 79 | input.length, 80 | output, 81 | outputLength, 82 | error, 83 | errorLength); 84 | 85 | final Bytes expectedComputation = 86 | expectedResult == null ? null : Bytes.fromHexString(expectedResult); 87 | if (errorLength.getValue() > 0) { 88 | assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes); 89 | assertThat(outputLength.getValue()).isZero(); 90 | } else { 91 | final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue()); 92 | assertThat(actualComputation).isEqualTo(expectedComputation); 93 | assertThat(notes).isEmpty(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/LibGnarkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.gnark; 17 | 18 | import org.apache.tuweni.bytes.Bytes; 19 | import org.apache.tuweni.bytes.Bytes32; 20 | import org.apache.tuweni.bytes.MutableBytes; 21 | import org.junit.Test; 22 | 23 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat; 24 | 25 | public class LibGnarkTest { 26 | 27 | @Test 28 | public void testHashZeroBn254() { 29 | byte[] output = new byte[Bytes32.SIZE]; 30 | LibGnark.computeMimcBn254(Bytes32.ZERO.toArrayUnsafe(), Bytes32.SIZE, output); 31 | assertThat(Bytes.wrap(output)).isEqualTo(Bytes.fromHexString("0x2c7298fd87d3039ffea208538f6b297b60b373a63792b4cd0654fdc88fd0d6ee")); 32 | } 33 | 34 | @Test 35 | public void testHashOneBn254() { 36 | byte[] output = new byte[Bytes32.SIZE]; 37 | LibGnark.computeMimcBn254(Bytes32.leftPad(Bytes.of(1)).toArrayUnsafe(), Bytes32.SIZE, output); 38 | assertThat(Bytes.wrap(output)).isEqualTo(Bytes.fromHexString("0x27e5458b666ef581475a9acddbc3524ca252185cae3936506e65cda9c358222b")); 39 | } 40 | 41 | @Test 42 | public void testLongStringBn254() { 43 | MutableBytes input = MutableBytes.of(new byte[Bytes32.SIZE*16]); 44 | for (int i = 0; i < 16; i++) { 45 | input.set(Bytes32.SIZE*(i+1)-1,(byte) i); 46 | } 47 | byte[] output = new byte[Bytes32.SIZE]; 48 | LibGnark.computeMimcBn254(input.toArrayUnsafe(), input.size(), output); 49 | assertThat(Bytes.wrap(output)).isEqualTo(Bytes.fromHexString("0x145875dd085ea2fb9796333e55c9da80228eb321df0ca9a41ca64ba6fe90b167")); 50 | } 51 | 52 | @Test 53 | public void testHashZeroBls12377() { 54 | byte[] output = new byte[Bytes32.SIZE]; 55 | LibGnark.computeMimcBls12377(Bytes32.ZERO.toArrayUnsafe(), Bytes32.SIZE, output); 56 | assertThat(Bytes.wrap(output)).isEqualTo(Bytes.fromHexString("0x0134373b65f439c874734ff51ea349327c140cde2e47a933146e6f9f2ad8eb17")); 57 | } 58 | 59 | @Test 60 | public void testHashOneBls12377() { 61 | byte[] output = new byte[Bytes32.SIZE]; 62 | LibGnark.computeMimcBls12377(Bytes32.leftPad(Bytes.of(1)).toArrayUnsafe(), Bytes32.SIZE, output); 63 | assertThat(Bytes.wrap(output)).isEqualTo(Bytes.fromHexString("0x0d962bab9f4e4213383f25abc12d6ee78855fff118c94ca4352032b802ef8b87")); 64 | } 65 | 66 | @Test 67 | public void testLongStringBls12377() { 68 | MutableBytes input = MutableBytes.of(new byte[Bytes32.SIZE*16]); 69 | for (int i = 0; i < 16; i++) { 70 | input.set(Bytes32.SIZE*(i+1)-1,(byte) i); 71 | } 72 | byte[] output = new byte[Bytes32.SIZE]; 73 | LibGnark.computeMimcBls12377(input.toArrayUnsafe(), input.size(), output); 74 | assertThat(Bytes.wrap(output)).isEqualTo(Bytes.fromHexString("0x12900ae41a010e54e3b1ed95efa39071d357ff642aeedd30a2c4e13250409662")); 75 | } 76 | 77 | 78 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=1.3.2-SNAPSHOT 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/besu-native/d8d3e4e1473ce5f568d3c466558df42aa77de2f3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | 9 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /ipa-multipoint/ipa_multipoint_jni/Cargo.toml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright Besu Contributors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | # the License. You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | # specific language governing permissions and limitations under the License. 12 | # 13 | # SPDX-License-Identifier: Apache-2.0 14 | 15 | [package] 16 | name = "ipa_multipoint_jni" 17 | version = "0.1.0" 18 | description = "IPA Multipoint Crypto Library" 19 | license = "Apache-2.0" 20 | authors = ["Antoine Toulme "] 21 | repository = "https://github.com/hyperledger/besu-native" 22 | edition = "2018" 23 | 24 | [dependencies] 25 | ffi_interface = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83"} 26 | verkle-trie = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83"} 27 | ipa-multipoint = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83"} 28 | banderwagon = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83"} 29 | jni = { version = "0.19.0", features = [ 30 | "invocation", 31 | ] } # We use invocation in tests. 32 | hex = "0.4.3" 33 | num-bigint = "0.4.4" 34 | once_cell = "1.19.0" 35 | 36 | [lib] 37 | name = "ipa_multipoint_jni" 38 | crate-type = ["cdylib"] 39 | -------------------------------------------------------------------------------- /ipa-multipoint/ipa_multipoint_jni/src/parsers.rs: -------------------------------------------------------------------------------- 1 | use jni::JNIEnv; 2 | use jni::objects::ReleaseMode; 3 | use jni::sys::jbyteArray; 4 | 5 | use std::convert::TryFrom; 6 | 7 | use ffi_interface::CommitmentBytes; 8 | 9 | 10 | pub fn parse_scalars<'a>(env: &'a JNIEnv<'a>, values: jbyteArray) -> Result<&'a [u8], String> { 11 | let input_len = env.get_array_length(values).map_err(|_| "Cannot get array lenght".to_string())? as usize; 12 | if input_len % 32 != 0 { 13 | return Err("Wrong input size: should be a mulitple of 32 bytes".to_string()) 14 | }; 15 | let input_elements = env.get_primitive_array_critical(values, ReleaseMode::NoCopyBack).map_err(|_| "Cannot get array elements".to_string())?; 16 | let input_slice = unsafe { std::slice::from_raw_parts(input_elements.as_ptr() as *const u8, input_len) }; 17 | Ok(input_slice) 18 | } 19 | 20 | pub fn parse_indices(env: &JNIEnv, values: jbyteArray) -> Result, String> { 21 | let input_len = env.get_array_length(values).map_err(|_| "Cannot get array lenght".to_string())? as usize; 22 | let input_elements = env.get_primitive_array_critical(values, ReleaseMode::NoCopyBack).map_err(|_| "Cannot get array elements".to_string())?; 23 | let input_slice = unsafe { std::slice::from_raw_parts(input_elements.as_ptr() as *const u8, input_len) }; 24 | let result: Vec = input_slice.iter().map(|&x| x as usize).collect(); 25 | Ok(result) 26 | } 27 | 28 | pub fn parse_commitment(env: &JNIEnv, commitment: jbyteArray) -> Result { 29 | let input_len = env.get_array_length(commitment).map_err(|_| "Cannot get commitment lenght".to_string())? as usize; 30 | let input_elements = env.get_primitive_array_critical(commitment, ReleaseMode::NoCopyBack).map_err(|_| "Cannot get array elements".to_string())?; 31 | let input_slice = unsafe { std::slice::from_raw_parts(input_elements.as_ptr() as *const u8, input_len) }; 32 | let result: CommitmentBytes = CommitmentBytes::try_from(input_slice).map_err(|_| "Wrong commitment size: should be 64 bytes".to_string())?; 33 | Ok(result) 34 | } 35 | 36 | pub fn parse_commitments<'a>(env: &'a JNIEnv<'a>, commitment: jbyteArray) -> Result<&'a [u8], String> { 37 | let input_len = env.get_array_length(commitment).map_err(|_| "Cannot get commitment lenght".to_string())? as usize; 38 | if input_len % 64 != 0 { 39 | return Err("Wrong input size: should be a mulitple of 64 bytes".to_string()) 40 | }; 41 | let input_elements = env.get_primitive_array_critical(commitment, ReleaseMode::NoCopyBack).map_err(|_| "Cannot get array elements".to_string())?; 42 | let input_slice = unsafe { std::slice::from_raw_parts(input_elements.as_ptr() as *const u8, input_len) }; 43 | Ok(input_slice) 44 | } 45 | -------------------------------------------------------------------------------- /ipa-multipoint/src/test/java/org/hyperledger/besu/nativelib/ipa_multipoint/CommitRootTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.ipa_multipoint; 17 | 18 | import org.junit.jupiter.params.ParameterizedTest; 19 | import org.junit.jupiter.params.provider.MethodSource; 20 | import static org.assertj.core.api.Assertions.*; 21 | 22 | import com.fasterxml.jackson.core.type.TypeReference; 23 | import com.fasterxml.jackson.databind.ObjectMapper; 24 | 25 | import org.apache.tuweni.bytes.Bytes; 26 | import org.apache.tuweni.bytes.Bytes32; 27 | import org.hyperledger.besu.nativelib.ipamultipoint.LibIpaMultipoint; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | 34 | public class CommitRootTest { 35 | private static final ObjectMapper objectMapper = new ObjectMapper(); 36 | 37 | public static List JsonData() throws IOException { 38 | InputStream inputStream = PedersenCommitmentTest.class.getResourceAsStream("/commit_root_test.json"); 39 | return objectMapper.readValue(inputStream, new TypeReference>() { 40 | }); 41 | } 42 | 43 | static class TestData { 44 | public ArrayList frs; 45 | public String expected; 46 | } 47 | 48 | @ParameterizedTest 49 | @MethodSource("JsonData") 50 | public void TestPolynomialCommitments(TestData testData) { 51 | List FrBytes = new ArrayList<>(); 52 | for (int i = 0; i < 256; i++) { 53 | Bytes32 value = Bytes32.fromHexString(testData.frs.get(i)); 54 | FrBytes.add(value.reverse()); 55 | } 56 | byte[] input = Bytes.concatenate(FrBytes).toArray(); 57 | Bytes32 result = Bytes32.wrap(LibIpaMultipoint.commitAsCompressed(input)); 58 | Bytes32 expected = Bytes32.fromHexString(testData.expected); 59 | assertThat(result).isEqualTo(expected); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ipa-multipoint/src/test/java/org/hyperledger/besu/nativelib/ipa_multipoint/PedersenCommitmentTest.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.ipa_multipoint; 2 | 3 | import org.junit.jupiter.params.ParameterizedTest; 4 | import org.junit.jupiter.params.provider.MethodSource; 5 | import static org.assertj.core.api.Assertions.*; 6 | 7 | import com.fasterxml.jackson.core.type.TypeReference; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | 10 | import org.apache.tuweni.bytes.Bytes; 11 | import org.apache.tuweni.bytes.Bytes32; 12 | import org.hyperledger.besu.nativelib.ipamultipoint.LibIpaMultipoint; 13 | 14 | import java.io.IOException; 15 | import java.io.InputStream; 16 | import java.math.BigInteger; 17 | import java.nio.ByteOrder; 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | 22 | public class PedersenCommitmentTest { 23 | private static final ObjectMapper objectMapper = new ObjectMapper(); 24 | 25 | public static List JsonData() throws IOException { 26 | InputStream inputStream = PedersenCommitmentTest.class.getResourceAsStream("/pedersen_commitment_test.json"); 27 | return objectMapper.readValue(inputStream, new TypeReference>() {}); 28 | } 29 | 30 | static class TestData { 31 | public ArrayList frs; 32 | public String commitment; 33 | } 34 | 35 | @ParameterizedTest 36 | @MethodSource("JsonData") 37 | public void TestPolynomialCommitments(TestData testData) { 38 | List FrBytes = new ArrayList<>(); 39 | for (int i = 0 ; i < 256; i++ ) { 40 | Bytes32 value = Bytes32.fromHexString(testData.frs.get(i)); 41 | FrBytes.add(value); 42 | } 43 | byte[] input = Bytes.concatenate(FrBytes).toArray(); 44 | Bytes result = Bytes.wrap(LibIpaMultipoint.hash(LibIpaMultipoint.commit(input))); 45 | Bytes expected = Bytes.fromHexString(testData.commitment); 46 | assertThat(result).isEqualTo(expected); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ipa-multipoint/src/test/java/org/hyperledger/besu/nativelib/ipa_multipoint/proof/ExecutionWitnessData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Besu Contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | * 15 | */ 16 | package org.hyperledger.besu.nativelib.ipa_multipoint.proof; 17 | 18 | import com.fasterxml.jackson.annotation.JsonProperty; 19 | 20 | import java.util.List; 21 | 22 | 23 | public class ExecutionWitnessData { 24 | 25 | @JsonProperty("header") 26 | public Header header; 27 | @JsonProperty("executionWitness") 28 | public ExecutionWitness executionWitness; 29 | 30 | 31 | static class Header { 32 | 33 | @JsonProperty("blockNumber") 34 | public String blockNumber; 35 | @JsonProperty("parentHash") 36 | public String parentHash; 37 | @JsonProperty("stateRoot") 38 | public String stateRoot; 39 | 40 | } 41 | 42 | 43 | static class ExecutionWitness { 44 | 45 | @JsonProperty("stateDiff") 46 | public List stateDiff; 47 | @JsonProperty("verkleProof") 48 | public VerkleProof verkleProof; 49 | 50 | } 51 | 52 | 53 | static class StateDiff { 54 | 55 | @JsonProperty("stem") 56 | public String stem; 57 | @JsonProperty("suffixDiffs") 58 | public List suffixDiffs; 59 | 60 | } 61 | 62 | 63 | static class SuffixDiff { 64 | 65 | @JsonProperty("suffix") 66 | public int suffix; 67 | @JsonProperty("currentValue") 68 | public String currentValue; 69 | @JsonProperty("newValue") 70 | public String newValue; 71 | 72 | } 73 | 74 | 75 | static class VerkleProof { 76 | 77 | @JsonProperty("otherStems") 78 | public List otherStems; 79 | @JsonProperty("depthExtensionPresent") 80 | public String depthExtensionPresent; 81 | @JsonProperty("commitmentsByPath") 82 | public List commitmentsByPath; 83 | @JsonProperty("d") 84 | public String d; 85 | @JsonProperty("ipaProof") 86 | public IpaProof ipaProof; 87 | 88 | } 89 | 90 | 91 | static class IpaProof { 92 | 93 | @JsonProperty("cl") 94 | public List cl; 95 | @JsonProperty("cr") 96 | public List cr; 97 | @JsonProperty("finalEvaluation") 98 | public String finalEvaluation; 99 | 100 | } 101 | } -------------------------------------------------------------------------------- /ipa-multipoint/src/test/resources/pedersen_hash_test.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "addr": "ed3f9549040250ec5cdef31947e5213edee80ad2d5bba35c9e48246c5d9213d6", 4 | "treeIndex": "12799791566713128344129487910142437201762343781989895398135125439977717568113", 5 | "treeKey": "2e50716b7d8c6d13d6005ea248f63f5a11ed63318cad38010f4bcb9a9c2e8b01" 6 | }, 7 | { 8 | "addr": "1529bcd7ec766191f11c2bf72572aabff770befb7f7a838d970405cb80a5ca7f", 9 | "treeIndex": "103007063076699009359590897535458882830299574105063886589774568433909778869954", 10 | "treeKey": "11250c335f8ee945340b4ff14f1779e6e09b6b1f62f035ee5546d67f415e4901" 11 | }, 12 | { 13 | "addr": "29fae57a7c64d653572b7c2d123dc402a596ada158cf6b231d4fef6386e4bedb", 14 | "treeIndex": "62610570058181606183886372930629891919809392494824294375099646354644839675119", 15 | "treeKey": "08b7ae8b3357ab6a2b6c588ebccecb56dce0058aae14d12db9cea9e74eb0d701" 16 | }, 17 | { 18 | "addr": "dd88161404eb7f178366e5ff8605fd205a8d3b9f89d3d98642abdf27076f5278", 19 | "treeIndex": "52414537576753537551969298885771848714362836123978646629259839023424723308578", 20 | "treeKey": "82743d493789d524293bf3627a1b95dae0015ce9f48bba5e5a303a0aec5a2001" 21 | }, 22 | { 23 | "addr": "6e12d3931847bd94d021c1f2c9818b7fbe6c6d662de3c89b3832d2fa6877313d", 24 | "treeIndex": "27739012335572007254751379080924414410738052256657431900442388385091478656177", 25 | "treeKey": "e11aa52116c53c7b7e5b77ec302583522fb0f0879620754e747eae99cdfb1401" 26 | }, 27 | { 28 | "addr": "a7c1867f65c97d855d49fddeee16bce3c1ddb7495574710aacdc985d07128532", 29 | "treeIndex": "79640400043998737611326288161617750917752622095168616267031294044356311151338", 30 | "treeKey": "0024c0049fcb5f63baa1021774ba6ef67a5720d3daeb1f299e0125e097bb2701" 31 | }, 32 | { 33 | "addr": "fed06e7a12d266ae7a58bb877e76d4c5a773e0efe3f72e52cf432c6b8a84e208", 34 | "treeIndex": "30556744647865105944122581218901048352578130644348709186830610492128249742089", 35 | "treeKey": "62064c3225fc44573ba5da3f84bb2db1fd11aa0b67114555ad4777dc61541201" 36 | }, 37 | { 38 | "addr": "8a88a9efc36f1d77f2c4a0ccd22ab88e14f62cd6680831053fb33f388b85e400", 39 | "treeIndex": "69490879420084483102032188835940183622600405945239580775517469342395928901300", 40 | "treeKey": "9a46d9fbb99ecd7b6c086792426ba8c3a37070fa76cd38c6bf1372f071232401" 41 | }, 42 | { 43 | "addr": "a3701e282edbc94cc662a3e328fd427212c3437b6099dfb5a1e11d86a562a0b1", 44 | "treeIndex": "48301202651700369735659313467078927981009470772072580217889107807147208726885", 45 | "treeKey": "7f2ee0bd3e314716fff89b5bb5d8305696160afb8f7c5f2966483e3f9c287001" 46 | }, 47 | { 48 | "addr": "c6b00ea376447a139f3aff5f4f1773db7407a142062defee88c90f91c9f16c9c", 49 | "treeIndex": "109215306339304144489862568004048252592065523112397664885703099216524468075226", 50 | "treeKey": "85847ff304ec6c7b80b2ad61b9a22f9a3f030f4906d0425bf0b11d2bba276801" 51 | }, 52 | { "comment": "addr: bytes in hex\ntreeIndex: The big int number in decimal notation (base 10). It's a \"string\" because I can put such a big integer in a JSON.\ntreeKey: the result of the perdersen hash bytes" } 53 | ] -------------------------------------------------------------------------------- /ipa-multipoint/src/test/resources/valid_block_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "blockNumber": "0x1", 4 | "parentHash": "0x3fe165c03e7a77d1e3759362ebeeb16fd964cb411ce11fbe35c7032fab5b9a8a", 5 | "stateRoot": "0x5a65582e323fb83ed40438a0c33fa6ebfbc7f45e4c29d112b0142cfeb63f82af" 6 | }, 7 | "executionWitness": { 8 | "stateDiff": [ 9 | { 10 | "stem": "0x5b5fdfedd6a0e932da408ac7d772a36513d1eee9b9926e52620c43a433aad7", 11 | "suffixDiffs": [ 12 | { 13 | "suffix": 64, 14 | "currentValue": null, 15 | "newValue": "0x3fe165c03e7a77d1e3759362ebeeb16fd964cb411ce11fbe35c7032fab5b9a8a" 16 | } 17 | ] 18 | } 19 | ], 20 | "verkleProof": { 21 | "otherStems": [ 22 | "0x5bdf12f5e17d2911dac2d2b0fc9e64a3ddc1d1ea4fc2568fe7e741ff2daa18" 23 | ], 24 | "depthExtensionPresent": "0x09", 25 | "commitmentsByPath": [ 26 | "0x26715ff22c071fdd9d9c2c6b5f5bf9bb0d83a2087e1366deabcecdf2a1d3f82e" 27 | ], 28 | "d": "0x5af46ab3e8676b9d4de8ae0be9670c45e9afd43cc11524c7946728268652028a", 29 | "ipaProof": { 30 | "cl": [ 31 | "0x6e3104792843f10a7236b6648f0d32d9ede087d55a3c8705038ed5358e073904", 32 | "0x5eceadbf8532a2c626366356e9dd870a9e83bc0393ea088a32a8dc7452291cc3", 33 | "0x13bf721c1aa1cdf84ea69161114bbe0eda90f51173ac00dabdfc4e6aeed301a4", 34 | "0x21a7dfe85100ed2e0c6b1f07ff07ad9660711d25ff7ffdd7a7a02b3363089df9", 35 | "0x0abe44837167a603c0ab167071c7d01fab67d0b81b0f8c2c195445f6a0063301", 36 | "0x3f4e616c904c91bc4211dfb14f33528f498fe76c1acc85491ef253afd4ce2cbb", 37 | "0x08631ce02176c4dcf83dbd04c68adf17d70090f2a2d367085b35a733baadf991", 38 | "0x44b4f57ed5ea4fdb1cd97901aab184b9a3d743bc3732e3e9c3b1e29370eb24d8" 39 | ], 40 | "cr": [ 41 | "0x6206979e2aa815bff1c76c521d025229e5867ba2d67422bd54d993a471aebbf8", 42 | "0x11bbacadfad4a06e85a7509ac601693646d1dc6416fb06c14f0745276579d548", 43 | "0x6b34ee89647bf02642546d0c2438fc34f350dae628ba033efbce2d9efe5c714b", 44 | "0x2eaf5b365d0071a04b0bf880df7cc4fefb88bb7e42693fedff0b94f4a4faab18", 45 | "0x3506e34c2e7686856cd0f4485f51f965aa926f235ee2b4c632b2239ffd0c9ff1", 46 | "0x18fbb94e59a02d289cf2d886f365cce91b89416d43e0a44d548cc6fd790b8d06", 47 | "0x31e28a78851612861fede858f62f7bbbfa12d02a302fea0272e03e668f0cb5a9", 48 | "0x48585ea2484b2b902f38297e14491311d8c74002f3eaeca9ac43bf03cfc090b5" 49 | ], 50 | "finalEvaluation": "0x08a3079093df751fc850f3805e10cc898314688111df75aa20511c32198a93e3" 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /native-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | apt-get update 3 | DEBIAN_FRONTEND=non-interactive apt-get install -y autoconf build-essential libtool automake patchelf curl openjdk-21-jdk git wget cmake 4 | export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))) 5 | export PATH=$JAVA_HOME/bin:$PATH 6 | wget https://go.dev/dl/go1.24.1.linux-arm64.tar.gz 7 | echo "8df5750ffc0281017fb6070fba450f5d22b600a02081dceef47966ffaf36a3af go1.24.1.linux-arm64.tar.gz" | sha256sum -c || exit 1 8 | tar -xzf go1.24.1.linux-arm64.tar.gz -C $HOME 9 | export GOPATH=$HOME/.go 10 | mkdir -p $GOPATH 11 | export GOROOT="$HOME/go" 12 | export PATH="$GOROOT/bin":$PATH 13 | export CARGO_HOME="$HOME/.cargo" 14 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.75.0 15 | export PATH=$PATH:$CARGO_HOME/bin 16 | git config --global --add safe.directory /home/ubuntu/secp256r1/besu-native-ec 17 | git config --global --add safe.directory /home/ubuntu/secp256r1/besu-native-ec/openssl 18 | /home/ubuntu/build.sh 19 | -------------------------------------------------------------------------------- /secp256k1/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | plugins { 17 | id 'java-library' 18 | id 'maven-publish' 19 | id 'com.jfrog.artifactory' version '5.2.3' 20 | } 21 | 22 | dependencies { 23 | implementation project(':common') 24 | implementation 'net.java.dev.jna:jna:5.12.1' 25 | } 26 | 27 | task macArmLibCopy(type: Copy) { 28 | from 'build/darwin-aarch64/lib/libsecp256k1.dylib' 29 | into 'build/resources/main/lib/aarch64' 30 | } 31 | processResources.dependsOn macArmLibCopy 32 | 33 | task macLibCopy(type: Copy) { 34 | from 'build/darwin-x86-64/lib/libsecp256k1.dylib' 35 | into 'build/resources/main/lib/x86-64' 36 | } 37 | processResources.dependsOn macLibCopy 38 | 39 | task linuxLibCopy(type: Copy) { 40 | from 'build/linux-gnu-x86_64/lib/libsecp256k1.so' 41 | into 'build/resources/main/lib/x86-64' 42 | } 43 | processResources.dependsOn linuxLibCopy 44 | 45 | task linuxArm64LibCopy(type: Copy) { 46 | from 'build/linux-gnu-aarch64/lib/libsecp256k1.so' 47 | into 'build/resources/main/lib/aarch64' 48 | } 49 | processResources.dependsOn linuxArm64LibCopy 50 | 51 | task linuxRiscv64LibCopy(type: Copy) { 52 | from 'build/linux-gnu-riscv64/lib/libsecp256k1.so' 53 | into 'build/resources/main/lib/riscv64' 54 | } 55 | processResources.dependsOn linuxRiscv64LibCopy 56 | 57 | jar { 58 | archiveBaseName = 'besu-native-secp256k1' 59 | includeEmptyDirs = false 60 | manifest { 61 | attributes( 62 | 'Specification-Title': archiveBaseName, 63 | 'Specification-Version': project.version, 64 | 'Implementation-Title': archiveBaseName, 65 | 'Implementation-Version': project.version, 66 | 'Automatic-Module-Name': 'org.hyperledger.besu.nativelib.secp256k1' 67 | ) 68 | } 69 | } 70 | 71 | task sourcesJar(type: Jar, dependsOn: classes) { 72 | archiveBaseName = 'besu-native-secp256k1' 73 | archiveClassifier = 'sources' 74 | from sourceSets.main.allSource 75 | } 76 | 77 | task javadocJar(type: Jar, dependsOn: javadoc) { 78 | archiveBaseName = 'besu-native-secp256k1' 79 | archiveClassifier = 'javadoc' 80 | from javadoc.destinationDir 81 | } 82 | 83 | publishing { 84 | publications { 85 | mavenJava(MavenPublication) { 86 | groupId "org.hyperledger.besu" 87 | artifactId 'secp256k1' 88 | version "${project.version}" 89 | 90 | from components.java 91 | artifact sourcesJar 92 | artifact javadocJar 93 | 94 | pom { 95 | name = "Besu Native - ${project.name}" 96 | description = 'Adapter for native secp256k1 library' 97 | url = 'http://github.com/hyperledger/besu-native' 98 | licenses { 99 | license { 100 | name = 'The Apache License, Version 2.0' 101 | url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' 102 | } 103 | } 104 | scm { 105 | connection = 'scm:git:git://github.com/hyperledger/besu-native.git' 106 | developerConnection = 'scm:git:ssh://github.com/hyperledger/besu-native.git' 107 | url = 'https://github.com/hyperledger/besu-native' 108 | } 109 | } 110 | } 111 | } 112 | } 113 | 114 | def artifactoryUser = project.hasProperty('artifactoryUser') ? project.property('artifactoryUser') : System.getenv('ARTIFACTORY_USER') 115 | def artifactoryKey = project.hasProperty('artifactoryApiKey') ? project.property('artifactoryApiKey') : System.getenv('ARTIFACTORY_KEY') 116 | def artifactoryRepo = System.getenv('ARTIFACTORY_REPO') ?: 'besu-maven' 117 | def artifactoryOrg = System.getenv('ARTIFACTORY_ORG') ?: 'hyperledger' 118 | 119 | artifactory { 120 | contextUrl = "https://hyperledger.jfrog.io/${artifactoryOrg}" 121 | publish { 122 | repository { 123 | repoKey = artifactoryRepo 124 | username = artifactoryUser 125 | password = artifactoryKey 126 | } 127 | defaults { 128 | publications('mavenJava') 129 | publishArtifacts = true 130 | publishPom = true 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /secp256r1/src/main/java/org/hyperledger/besu/nativelib/secp256r1/Signature.java: -------------------------------------------------------------------------------- 1 | package org.hyperledger.besu.nativelib.secp256r1; 2 | 3 | import java.util.Arrays; 4 | import java.util.Objects; 5 | 6 | public class Signature { 7 | private final byte[] r; 8 | private final byte[] s; 9 | private final byte v; 10 | 11 | public Signature(byte[] r, byte[] s, byte v) { 12 | this.r = r; 13 | this.s = s; 14 | this.v = v; 15 | } 16 | 17 | public byte[] getR() { 18 | return r; 19 | } 20 | 21 | public byte[] getS() { 22 | return s; 23 | } 24 | 25 | public byte getV() { 26 | return v; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (this == o) return true; 32 | if (o == null || getClass() != o.getClass()) return false; 33 | Signature signature = (Signature) o; 34 | return v == signature.v && Arrays.equals(r, signature.r) && Arrays.equals(s, signature.s); 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | int result = Objects.hash(v); 40 | result = 31 * result + Arrays.hashCode(r); 41 | result = 31 * result + Arrays.hashCode(s); 42 | return result; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "Signature{" + 48 | "r=" + Arrays.toString(r) + 49 | ", s=" + Arrays.toString(s) + 50 | ", v=" + v + 51 | '}'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /secp256r1/src/main/java/org/hyperledger/besu/nativelib/secp256r1/besuNativeEC/BesuNativeEC.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | package org.hyperledger.besu.nativelib.secp256r1.besuNativeEC; 17 | 18 | import com.sun.jna.Library; 19 | import org.hyperledger.besu.nativelib.common.BesuNativeLibraryLoader; 20 | import org.hyperledger.besu.nativelib.secp256r1.besuNativeEC.KeyRecoveryResult.KeyRecoveryResultByValue; 21 | import org.hyperledger.besu.nativelib.secp256r1.besuNativeEC.SignResult.SignResultByValue; 22 | import org.hyperledger.besu.nativelib.secp256r1.besuNativeEC.VerifyResult.VerifyResultByValue; 23 | 24 | public class BesuNativeEC implements Library { 25 | public static final boolean ENABLED; 26 | 27 | static { 28 | boolean enabled; 29 | try { 30 | BesuNativeLibraryLoader.registerJNA(Library.class, "besu_native_ec_crypto"); 31 | BesuNativeLibraryLoader.registerJNA(BesuNativeEC.class, "besu_native_ec"); 32 | enabled = true; 33 | } catch (final Exception t) { 34 | enabled = false; 35 | } 36 | ENABLED = enabled; 37 | } 38 | 39 | /** 40 | * Original signature : key_recovery_result p256_key_recovery(const char[], const int, const char[], const char[], int)
41 | */ 42 | public static native KeyRecoveryResultByValue p256_key_recovery(byte[] data_hash, int data_hash_len, byte[] signature_r_hex, byte[] signature_s_hex, int signature_v); 43 | 44 | /** 45 | * Original signature : sign_result p256_sign(const char[], const int, const char[], const char[])
46 | */ 47 | public static native SignResultByValue p256_sign(byte[] data_hash, int data_hash_length, byte[] private_key_data, byte[] public_key_data); 48 | 49 | /** 50 | * Original signature : verify_result p256_verify(const char[], const int, const char[], const char[], const char[])
51 | */ 52 | public static native VerifyResultByValue p256_verify(byte[] data_hash, int data_hash_length, byte[] signature_r, byte[] signature_s, byte[] public_key_data); 53 | 54 | /** 55 | * Original signature : verify_result p256_verify_malleable_signature(const char[], const int, const char[], const char[], const char[])
56 | */ 57 | public static native VerifyResultByValue p256_verify_malleable_signature(byte[] data_hash, int data_hash_length, byte[] signature_r, byte[] signature_s, byte[] public_key_data); 58 | } 59 | -------------------------------------------------------------------------------- /secp256r1/src/main/java/org/hyperledger/besu/nativelib/secp256r1/besuNativeEC/KeyRecoveryResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | package org.hyperledger.besu.nativelib.secp256r1.besuNativeEC; 17 | 18 | import com.sun.jna.Structure; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | public class KeyRecoveryResult extends Structure { 23 | public byte[] public_key = new byte[131]; 24 | public byte[] error_message = new byte[256]; 25 | 26 | public KeyRecoveryResult() { 27 | super(); 28 | } 29 | 30 | @Override 31 | protected List getFieldOrder() { 32 | return Arrays.asList("public_key", "error_message"); 33 | } 34 | 35 | public static class KeyRecoveryResultByValue extends KeyRecoveryResult implements Structure.ByValue {} 36 | } 37 | -------------------------------------------------------------------------------- /secp256r1/src/main/java/org/hyperledger/besu/nativelib/secp256r1/besuNativeEC/SignResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | package org.hyperledger.besu.nativelib.secp256r1.besuNativeEC; 17 | 18 | import com.sun.jna.Structure; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | public class SignResult extends Structure { 23 | public byte[] signature_r = new byte[66]; 24 | public byte[] signature_s = new byte[66]; 25 | public byte signature_v; 26 | public byte[] error_message = new byte[256]; 27 | 28 | public SignResult() { 29 | super(); 30 | } 31 | 32 | protected List getFieldOrder() { 33 | return Arrays.asList("signature_r", "signature_s", "signature_v", "error_message"); 34 | } 35 | 36 | public static class SignResultByValue extends SignResult implements Structure.ByValue {} 37 | } 38 | -------------------------------------------------------------------------------- /secp256r1/src/main/java/org/hyperledger/besu/nativelib/secp256r1/besuNativeEC/VerifyResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | package org.hyperledger.besu.nativelib.secp256r1.besuNativeEC; 17 | 18 | import com.sun.jna.Structure; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | public class VerifyResult extends Structure { 23 | public int verified; 24 | public byte[] error_message = new byte[256]; 25 | 26 | public VerifyResult() { 27 | super(); 28 | } 29 | 30 | @Override 31 | protected List getFieldOrder() { 32 | return Arrays.asList("verified", "error_message"); 33 | } 34 | 35 | public static class VerifyResultByValue extends VerifyResult implements Structure.ByValue {} 36 | } 37 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Hyperledger Besu contributors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | * 13 | * SPDX-License-Identifier: Apache-2.0 14 | */ 15 | 16 | rootProject.name='besu-native' 17 | include 'common' 18 | include 'arithmetic' 19 | include 'blake2bf' 20 | include 'ipa-multipoint' 21 | include 'secp256k1' 22 | include 'secp256r1' 23 | include 'gnark' 24 | include 'constantine' 25 | include 'boringssl' 26 | --------------------------------------------------------------------------------