Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add some CKZG property tests #6596

Merged
merged 22 commits into from Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions ethereum/spec/build.gradle
Expand Up @@ -66,10 +66,12 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testImplementation 'org.junit.jupiter:junit-jupiter-params'
testImplementation 'org.mockito:mockito-core'
testImplementation 'tech.pegasys:jc-kzg-4844'
testImplementation testFixtures(project(':infrastructure:async'))
testImplementation testFixtures(project(':infrastructure:bls'))
testImplementation testFixtures(project(':infrastructure:bls'))
testImplementation testFixtures(project(':infrastructure:collections'))
testImplementation testFixtures(project(':infrastructure:json'))
testImplementation testFixtures(project(':infrastructure:kzg'))
testImplementation testFixtures(project(':infrastructure:ssz'))
}
Expand Up @@ -59,7 +59,7 @@ private static KZG initKZG(final SpecConfigEip4844 config) {
return kzg;
}

public void validateBlobSidecar(
private void validateBlobSidecar(
final UInt64 slot,
final Bytes32 beaconBlockRoot,
final List<KZGCommitment> kzgCommitments,
Expand Down
@@ -0,0 +1,66 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.logic.versions.eip4844.helpers;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;
import net.jqwik.api.ForAll;
import net.jqwik.api.From;
import net.jqwik.api.Property;
import net.jqwik.api.lifecycle.AddLifecycleHook;
import org.apache.tuweni.bytes.Bytes;
import tech.pegasys.teku.kzg.KZG;
import tech.pegasys.teku.kzg.KZGCommitment;
import tech.pegasys.teku.kzg.KZGException;
import tech.pegasys.teku.kzg.KZGProof;
import tech.pegasys.teku.spec.propertytest.suppliers.type.BytesSupplier;
import tech.pegasys.teku.spec.propertytest.suppliers.type.KZGCommitmentSupplier;
import tech.pegasys.teku.spec.propertytest.suppliers.type.KZGProofSupplier;

@AddLifecycleHook(KzgResolver.class)
public class CKZG4844PropertyTest {
@Property(tries = 100)
void fuzzComputeAggregateKzgProof(
final KZG kzg, @ForAll final List<@From(supplier = BytesSupplier.class) Bytes> blobs) {
try {
kzg.computeAggregateKzgProof(blobs);
} catch (Exception e) {
assertThat(e).isInstanceOf(KZGException.class);
}
}

@Property(tries = 100)
void fuzzVerifyAggregateKzgProof(
final KZG kzg,
@ForAll final List<@From(supplier = BytesSupplier.class) Bytes> blobs,
@ForAll final List<@From(supplier = KZGCommitmentSupplier.class) KZGCommitment> commitments,
@ForAll(supplier = KZGProofSupplier.class) final KZGProof proof) {
try {
kzg.verifyAggregateKzgProof(blobs, commitments, proof);
} catch (Exception e) {
assertThat(e).isInstanceOf(KZGException.class);
}
}

@Property(tries = 100)
void fuzzBlobToKzgCommitment(
final KZG kzg, @ForAll(supplier = BytesSupplier.class) final Bytes blob) {
try {
kzg.blobToKzgCommitment(blob);
} catch (Exception e) {
assertThat(e).isInstanceOf(KZGException.class);
}
}
}
@@ -0,0 +1,72 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.logic.versions.eip4844.helpers;

import com.google.common.io.Resources;
import ethereum.ckzg4844.CKZG4844JNI;
import java.util.Optional;
import net.jqwik.api.Tuple;
import net.jqwik.api.lifecycle.LifecycleContext;
import net.jqwik.api.lifecycle.Lifespan;
import net.jqwik.api.lifecycle.ParameterResolutionContext;
import net.jqwik.api.lifecycle.PropagationMode;
import net.jqwik.api.lifecycle.ResolveParameterHook;
import net.jqwik.api.lifecycle.Store;
import tech.pegasys.teku.kzg.KZG;
import tech.pegasys.teku.kzg.ckzg4844.CKZG4844;
import tech.pegasys.teku.kzg.trusted_setups.TrustedSetups;

/**
* This class provides a KZG instance with a loaded trusted setup that will automatically free the
* trusted setup when the property test is finished. It will re-use the same KZG instance for all
* iterations of the test, but it will create a new instance for each method. For a class with three
* property test methods, you can expect it to load/free three times.
*/
class KzgResolver implements ResolveParameterHook {
public static final Tuple.Tuple2<Class<KzgResolver.KzgAutoLoadFree>, String> STORE_IDENTIFIER =
Tuple.of(KzgResolver.KzgAutoLoadFree.class, "KZGs that automatically load & free");

@Override
public Optional<ParameterSupplier> resolve(
final ParameterResolutionContext parameterContext, final LifecycleContext lifecycleContext) {
return Optional.of(optionalTry -> getKzgWithTrustedSetup());
}

@Override
public PropagationMode propagateTo() {
return PropagationMode.ALL_DESCENDANTS;
}

private KZG getKzgWithTrustedSetup() {
final Store<KzgResolver.KzgAutoLoadFree> kzgStore =
Store.getOrCreate(STORE_IDENTIFIER, Lifespan.PROPERTY, KzgResolver.KzgAutoLoadFree::new);
return kzgStore.get().kzg;
}

private static class KzgAutoLoadFree implements Store.CloseOnReset {
private static final String TRUSTED_SETUP =
Resources.getResource(TrustedSetups.class, "mainnet/trusted_setup.txt").toExternalForm();
private final KZG kzg =
CKZG4844.createInstance(CKZG4844JNI.Preset.MAINNET.fieldElementsPerBlob);

private KzgAutoLoadFree() {
kzg.loadTrustedSetup(TRUSTED_SETUP);
}

@Override
public void close() {
kzg.freeTrustedSetup();
}
}
}
@@ -0,0 +1,92 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.logic.versions.eip4844.helpers;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;
import java.util.Objects;
import net.jqwik.api.ForAll;
import net.jqwik.api.From;
import net.jqwik.api.Property;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.kzg.KZGCommitment;
import tech.pegasys.teku.spec.config.SpecConfigEip4844;
import tech.pegasys.teku.spec.datastructures.execution.Transaction;
import tech.pegasys.teku.spec.datastructures.execution.versions.eip4844.BlobsSidecar;
import tech.pegasys.teku.spec.propertytest.suppliers.SpecSupplier;
import tech.pegasys.teku.spec.propertytest.suppliers.execution.TransactionSupplier;
import tech.pegasys.teku.spec.propertytest.suppliers.execution.versions.eip4844.BlobsSidecarSupplier;
import tech.pegasys.teku.spec.propertytest.suppliers.type.Bytes32Supplier;
import tech.pegasys.teku.spec.propertytest.suppliers.type.KZGCommitmentSupplier;
import tech.pegasys.teku.spec.propertytest.suppliers.type.UInt64Supplier;

public class MiscHelpersEip4844PropertyTest {
private final SpecConfigEip4844 specConfig =
Objects.requireNonNull(new SpecSupplier().get())
.sample()
.getGenesisSpecConfig()
.toVersionEip4844()
.orElseThrow();
private final MiscHelpersEip4844 miscHelpers = new MiscHelpersEip4844(specConfig);

@Property(tries = 100)
void fuzzIsDataAvailable(
@ForAll(supplier = UInt64Supplier.class) final UInt64 slot,
@ForAll(supplier = Bytes32Supplier.class) final Bytes32 beaconBlockRoot,
@ForAll final List<@From(supplier = KZGCommitmentSupplier.class) KZGCommitment> commitments,
@ForAll(supplier = BlobsSidecarSupplier.class) final BlobsSidecar blobsSidecar) {
try {
miscHelpers.isDataAvailable(slot, beaconBlockRoot, commitments, blobsSidecar);
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class);
}
}

@Property
void fuzzKzgCommitmentToVersionedHash(
@ForAll(supplier = KZGCommitmentSupplier.class) final KZGCommitment commitment) {
miscHelpers.kzgCommitmentToVersionedHash(commitment);
}

@Property(tries = 100)
void fuzzTxPeekBlobVersionedHashes(
@ForAll(supplier = TransactionSupplier.class) final Transaction transaction) {
try {
miscHelpers.txPeekBlobVersionedHashes(transaction);
} catch (Exception e) {
assertThat(e)
.isInstanceOfAny(
ArithmeticException.class,
IllegalArgumentException.class,
IndexOutOfBoundsException.class);
}
}

@Property(tries = 100)
void fuzzVerifyKZGCommitmentsAgainstTransactions(
@ForAll final List<@From(supplier = TransactionSupplier.class) Transaction> transactions,
@ForAll final List<@From(supplier = KZGCommitmentSupplier.class) KZGCommitment> commitments) {
try {
miscHelpers.verifyKZGCommitmentsAgainstTransactions(transactions, commitments);
} catch (Exception e) {
assertThat(e)
.isInstanceOfAny(
ArithmeticException.class,
IllegalArgumentException.class,
IndexOutOfBoundsException.class);
}
}
}
@@ -0,0 +1,26 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.propertytest.suppliers.type;

import net.jqwik.api.Arbitraries;
import net.jqwik.api.Arbitrary;
import net.jqwik.api.ArbitrarySupplier;
import org.apache.tuweni.bytes.Bytes32;

public class Bytes32Supplier implements ArbitrarySupplier<Bytes32> {
@Override
public Arbitrary<Bytes32> get() {
return Arbitraries.bytes().array(byte[].class).ofSize(32).map(Bytes32::wrap);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.propertytest.suppliers.type;

import net.jqwik.api.Arbitraries;
import net.jqwik.api.Arbitrary;
import net.jqwik.api.ArbitrarySupplier;
import org.apache.tuweni.bytes.Bytes;

public class BytesSupplier implements ArbitrarySupplier<Bytes> {
@Override
public Arbitrary<Bytes> get() {
return Arbitraries.bytes().array(byte[].class).map(Bytes::wrap);
}
}
@@ -0,0 +1,25 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.propertytest.suppliers.type;

import tech.pegasys.teku.kzg.KZGCommitment;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.propertytest.suppliers.DataStructureUtilSupplier;
import tech.pegasys.teku.spec.util.DataStructureUtil;

public class KZGCommitmentSupplier extends DataStructureUtilSupplier<KZGCommitment> {
public KZGCommitmentSupplier() {
super(DataStructureUtil::randomKZGCommitment, SpecMilestone.EIP4844);
}
}
@@ -0,0 +1,25 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.propertytest.suppliers.type;

import tech.pegasys.teku.kzg.KZGProof;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.propertytest.suppliers.DataStructureUtilSupplier;
import tech.pegasys.teku.spec.util.DataStructureUtil;

public class KZGProofSupplier extends DataStructureUtilSupplier<KZGProof> {
public KZGProofSupplier() {
super(DataStructureUtil::randomKZGProof, SpecMilestone.EIP4844);
}
}
@@ -0,0 +1,26 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.propertytest.suppliers.type;

import net.jqwik.api.Arbitraries;
import net.jqwik.api.Arbitrary;
import net.jqwik.api.ArbitrarySupplier;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;

public class UInt64Supplier implements ArbitrarySupplier<UInt64> {
@Override
public Arbitrary<UInt64> get() {
return Arbitraries.longs().map(UInt64::fromLongBits);
}
}