mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-09 15:28:09 -05:00
Add test coverage for java precompiles (#7446)
For tests that have a native/java switch ensure that the java path gets the same tests native paths do. Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com> Signed-off-by: Danno Ferrin <danno@numisight.com>
This commit is contained in:
@@ -1503,7 +1503,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
|
||||
private void configureNativeLibs() {
|
||||
if (unstableNativeLibraryOptions.getNativeAltbn128()
|
||||
&& AbstractAltBnPrecompiledContract.isNative()) {
|
||||
&& AbstractAltBnPrecompiledContract.maybeEnableNative()) {
|
||||
logger.info("Using the native implementation of alt bn128");
|
||||
} else {
|
||||
AbstractAltBnPrecompiledContract.disableNative();
|
||||
@@ -1519,7 +1519,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
}
|
||||
|
||||
if (unstableNativeLibraryOptions.getNativeSecp()
|
||||
&& SignatureAlgorithmFactory.getInstance().isNative()) {
|
||||
&& SignatureAlgorithmFactory.getInstance().maybeEnableNative()) {
|
||||
logger.info("Using the native implementation of the signature algorithm");
|
||||
} else {
|
||||
SignatureAlgorithmFactory.getInstance().disableNative();
|
||||
|
||||
@@ -397,7 +397,9 @@ public abstract class AbstractSECP256 implements SignatureAlgorithm {
|
||||
final Bytes32 dataHash, final SECPSignature signature) {
|
||||
final BigInteger publicKeyBI =
|
||||
recoverFromSignature(signature.getRecId(), signature.getR(), signature.getS(), dataHash);
|
||||
return Optional.of(SECPPublicKey.create(publicKeyBI, ALGORITHM));
|
||||
return publicKeyBI == null
|
||||
? Optional.empty()
|
||||
: Optional.of(SECPPublicKey.create(publicKeyBI, ALGORITHM));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,9 +44,10 @@ public class Blake2bfMessageDigest extends BCMessageDigest implements Cloneable
|
||||
/**
|
||||
* Implementation of the `F` compression function of the Blake2b cryptographic hash function.
|
||||
*
|
||||
* <p>RFC - https://tools.ietf.org/html/rfc7693
|
||||
* <p>RFC - <a href="https://tools.ietf.org/html/rfc7693">...</a>
|
||||
*
|
||||
* <p>Adapted from - https://github.com/keep-network/blake2b/blob/master/compression/f.go
|
||||
* <p>Adapted from - <a
|
||||
* href="https://github.com/keep-network/blake2b/blob/master/compression/f.go">...</a>
|
||||
*
|
||||
* <p>Optimized for 64-bit platforms
|
||||
*/
|
||||
@@ -93,12 +94,7 @@ public class Blake2bfMessageDigest extends BCMessageDigest implements Cloneable
|
||||
private static boolean useNative;
|
||||
|
||||
static {
|
||||
try {
|
||||
useNative = LibBlake2bf.ENABLED;
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
LOG.info("blake2bf native precompile not available: {}", ule.getMessage());
|
||||
useNative = false;
|
||||
}
|
||||
maybeEnableNative();
|
||||
}
|
||||
|
||||
/** Instantiates a new Blake2bf digest. */
|
||||
@@ -130,6 +126,21 @@ public class Blake2bfMessageDigest extends BCMessageDigest implements Cloneable
|
||||
return cloned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to enable the native libreary
|
||||
*
|
||||
* @return true if the native library was successfully enabled.
|
||||
*/
|
||||
public static boolean maybeEnableNative() {
|
||||
try {
|
||||
useNative = LibBlake2bf.ENABLED;
|
||||
} catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
|
||||
LOG.info("blake2bf native precompile not available: {}", e.getMessage());
|
||||
useNative = false;
|
||||
}
|
||||
return useNative;
|
||||
}
|
||||
|
||||
/** Disable native. */
|
||||
public static void disableNative() {
|
||||
useNative = false;
|
||||
|
||||
@@ -72,6 +72,7 @@ public class SECP256K1 extends AbstractSECP256 {
|
||||
*
|
||||
* @return true if the native library was enabled.
|
||||
*/
|
||||
@Override
|
||||
public boolean maybeEnableNative() {
|
||||
try {
|
||||
useNative = LibSecp256k1.CONTEXT != null;
|
||||
|
||||
@@ -61,6 +61,22 @@ public class SECP256R1 extends AbstractSECP256 {
|
||||
return useNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to enable the native library for secp256r1
|
||||
*
|
||||
* @return true if the native library was enabled.
|
||||
*/
|
||||
@Override
|
||||
public boolean maybeEnableNative() {
|
||||
try {
|
||||
useNative = BesuNativeEC.INSTANCE != null;
|
||||
} catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
|
||||
LOG.info("Native secp256r1 not available - {}", e.getMessage());
|
||||
useNative = false;
|
||||
}
|
||||
return useNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* SECP256R1 is using the non-deterministic implementation of K calculation (standard)
|
||||
*
|
||||
|
||||
@@ -31,6 +31,13 @@ public interface SignatureAlgorithm {
|
||||
/** Disable native. */
|
||||
void disableNative();
|
||||
|
||||
/**
|
||||
* Attempt to enable the native library.
|
||||
*
|
||||
* @return true if the native library was enabled
|
||||
*/
|
||||
boolean maybeEnableNative();
|
||||
|
||||
/**
|
||||
* Is native enabled.
|
||||
*
|
||||
|
||||
@@ -127,7 +127,7 @@ public class SECP256R1Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverPublicKeyFromSignature() {
|
||||
void recoverPublicKeyFromSignature() {
|
||||
final SECPPrivateKey privateKey =
|
||||
secp256R1.createPrivateKey(
|
||||
new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
|
||||
@@ -139,20 +139,20 @@ public class SECP256R1Test {
|
||||
|
||||
final SECPPublicKey recoveredPublicKey =
|
||||
secp256R1.recoverPublicKeyFromSignature(dataHash, signature).get();
|
||||
assertThat(recoveredPublicKey.toString()).isEqualTo(keyPair.getPublicKey().toString());
|
||||
assertThat(recoveredPublicKey).hasToString(keyPair.getPublicKey().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void signatureGenerationVerificationAndPubKeyRecovery() {
|
||||
void signatureGenerationVerificationAndPubKeyRecovery() {
|
||||
signTestVectors.forEach(
|
||||
signTestVector -> {
|
||||
final SECPPrivateKey privateKey =
|
||||
secp256R1.createPrivateKey(new BigInteger(signTestVector.getPrivateKey(), 16));
|
||||
final BigInteger publicKeyBigInt = new BigInteger(signTestVector.getPublicKey(), 16);
|
||||
secp256R1.createPrivateKey(new BigInteger(signTestVector.privateKey(), 16));
|
||||
final BigInteger publicKeyBigInt = new BigInteger(signTestVector.publicKey(), 16);
|
||||
final SECPPublicKey publicKey = secp256R1.createPublicKey(publicKeyBigInt);
|
||||
final KeyPair keyPair = secp256R1.createKeyPair(privateKey);
|
||||
|
||||
final Bytes32 dataHash = keccak256(Bytes.wrap(signTestVector.getData().getBytes(UTF_8)));
|
||||
final Bytes32 dataHash = keccak256(Bytes.wrap(signTestVector.data().getBytes(UTF_8)));
|
||||
|
||||
final SECPSignature signature = secp256R1.sign(dataHash, keyPair);
|
||||
assertThat(secp256R1.verify(dataHash, signature, publicKey)).isTrue();
|
||||
@@ -165,44 +165,22 @@ public class SECP256R1Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidFileThrowsInvalidKeyPairException() throws Exception {
|
||||
void invalidFileThrowsInvalidKeyPairException() throws Exception {
|
||||
final File tempFile = Files.createTempFile(suiteName(), ".keypair").toFile();
|
||||
tempFile.deleteOnExit();
|
||||
Files.write(tempFile.toPath(), "not valid".getBytes(UTF_8));
|
||||
Files.writeString(tempFile.toPath(), "not valid");
|
||||
assertThatThrownBy(() -> KeyPairUtil.load(tempFile))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidMultiLineFileThrowsInvalidIdException() throws Exception {
|
||||
void invalidMultiLineFileThrowsInvalidIdException() throws Exception {
|
||||
final File tempFile = Files.createTempFile(suiteName(), ".keypair").toFile();
|
||||
tempFile.deleteOnExit();
|
||||
Files.write(tempFile.toPath(), "not\n\nvalid".getBytes(UTF_8));
|
||||
Files.writeString(tempFile.toPath(), "not\n\nvalid");
|
||||
assertThatThrownBy(() -> KeyPairUtil.load(tempFile))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
private static class SignTestVector {
|
||||
private final String privateKey;
|
||||
private final String publicKey;
|
||||
private final String data;
|
||||
|
||||
public SignTestVector(final String privateKey, final String publicKey, final String data) {
|
||||
this.privateKey = privateKey;
|
||||
this.publicKey = publicKey;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public String getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
private record SignTestVector(String privateKey, String publicKey, String data) {}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import org.hyperledger.besu.evm.gascalculator.GasCalculator;
|
||||
import org.apache.tuweni.bytes.Bytes;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@@ -36,8 +38,14 @@ class AltBN128PairingPrecompiledContractTest {
|
||||
private final AltBN128PairingPrecompiledContract istanbulContract =
|
||||
AltBN128PairingPrecompiledContract.istanbul(gasCalculator);
|
||||
|
||||
@Test
|
||||
void compute_validPoints() {
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
void compute_validPoints(final boolean useNative) {
|
||||
if (useNative) {
|
||||
AbstractAltBnPrecompiledContract.maybeEnableNative();
|
||||
} else {
|
||||
AbstractAltBnPrecompiledContract.disableNative();
|
||||
}
|
||||
final Bytes input = validPointBytes();
|
||||
final Bytes result = byzantiumContract.computePrecompile(input, messageFrame).getOutput();
|
||||
assertThat(result).isEqualTo(AltBN128PairingPrecompiledContract.TRUE);
|
||||
@@ -80,8 +88,14 @@ class AltBN128PairingPrecompiledContractTest {
|
||||
return Bytes.concatenate(g1Point0, g2Point0, g1Point1, g2Point1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void compute_invalidPointsOutsideSubgroupG2() {
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
void compute_invalidPointsOutsideSubgroupG2(final boolean useNative) {
|
||||
if (useNative) {
|
||||
AbstractAltBnPrecompiledContract.maybeEnableNative();
|
||||
} else {
|
||||
AbstractAltBnPrecompiledContract.disableNative();
|
||||
}
|
||||
final Bytes g1Point0 =
|
||||
Bytes.concatenate(
|
||||
Bytes.fromHexString(
|
||||
@@ -122,11 +136,13 @@ class AltBN128PairingPrecompiledContractTest {
|
||||
|
||||
@Test
|
||||
void gasPrice_byzantium() {
|
||||
// gas calculation is java only
|
||||
assertThat(byzantiumContract.gasRequirement(validPointBytes())).isEqualTo(260_000L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void gasPrice_istanbul() {
|
||||
// gas calculation is java only
|
||||
assertThat(istanbulContract.gasRequirement(validPointBytes())).isEqualTo(113_000L);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.hyperledger.besu.evm.precompile;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.hyperledger.besu.crypto.Blake2bfMessageDigest.Blake2bfDigest;
|
||||
import org.hyperledger.besu.evm.frame.MessageFrame;
|
||||
import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator;
|
||||
|
||||
@@ -67,9 +68,24 @@ class BLAKE2BFPrecompileContractTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parameters")
|
||||
void shouldRunFCompression(
|
||||
void shouldRunFCompressionNative(
|
||||
final String inputString, final String expectedResult, final long expectedGasUsed) {
|
||||
Blake2bfDigest.maybeEnableNative();
|
||||
|
||||
testFCompression(inputString, expectedResult, expectedGasUsed);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parameters")
|
||||
void shouldRunFCompressionJava(
|
||||
final String inputString, final String expectedResult, final long expectedGasUsed) {
|
||||
Blake2bfDigest.disableNative();
|
||||
|
||||
testFCompression(inputString, expectedResult, expectedGasUsed);
|
||||
}
|
||||
|
||||
private void testFCompression(
|
||||
final String inputString, final String expectedResult, final long expectedGasUsed) {
|
||||
final Bytes input = Bytes.fromHexString(inputString);
|
||||
final Bytes expectedComputation =
|
||||
expectedResult == null ? null : Bytes.fromHexString(expectedResult);
|
||||
|
||||
@@ -349,8 +349,18 @@ class ECRECPrecompiledContractTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parameters")
|
||||
void shouldRecoverAddress(final String inputString, final String expectedResult) {
|
||||
void shouldRecoverAddressNative(final String inputString, final String expectedResult) {
|
||||
contract.signatureAlgorithm.maybeEnableNative();
|
||||
final Bytes input = Bytes.fromHexString(inputString);
|
||||
final Bytes expected =
|
||||
expectedResult == null ? Bytes.EMPTY : Bytes32.fromHexString(expectedResult);
|
||||
assertThat(contract.computePrecompile(input, messageFrame).getOutput()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parameters")
|
||||
void shouldRecoverAddressJava(final String inputString, final String expectedResult) {
|
||||
contract.signatureAlgorithm.disableNative();
|
||||
final Bytes input = Bytes.fromHexString(inputString);
|
||||
final Bytes expected =
|
||||
expectedResult == null ? Bytes.EMPTY : Bytes32.fromHexString(expectedResult);
|
||||
|
||||
@@ -155,12 +155,27 @@ class MODEXPPrecompiledContractTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parameters")
|
||||
void testPrecompiledContract(
|
||||
void testPrecompiledContractNative(
|
||||
final String inputString,
|
||||
final String precompiledResult,
|
||||
final Long eip198Gas,
|
||||
final Long eip2565Gas) {
|
||||
BigIntegerModularExponentiationPrecompiledContract.maybeEnableNative();
|
||||
testComputation(inputString, precompiledResult);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("parameters")
|
||||
void testPrecompiledContractJava(
|
||||
final String inputString,
|
||||
final String precompiledResult,
|
||||
final Long eip198Gas,
|
||||
final Long eip2565Gas) {
|
||||
BigIntegerModularExponentiationPrecompiledContract.disableNative();
|
||||
testComputation(inputString, precompiledResult);
|
||||
}
|
||||
|
||||
private void testComputation(final String inputString, final String precompiledResult) {
|
||||
assumeThat(precompiledResult).isNotNull();
|
||||
final Bytes input = Bytes.fromHexString(inputString);
|
||||
final Bytes expected = Bytes.fromHexString(precompiledResult);
|
||||
|
||||
Reference in New Issue
Block a user