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

Create MiscHelpersEip4844 #6474

Merged
merged 10 commits into from
Nov 22, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
import tech.pegasys.teku.spec.logic.versions.altair.util.AttestationUtilAltair;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BeaconStateMutatorsBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BellatrixTransitionHelpers;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.MiscHelpersBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.statetransition.epoch.EpochProcessorBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.util.BlindBlockUtilBellatrix;
import tech.pegasys.teku.spec.logic.versions.capella.block.BlockProcessorCapella;
import tech.pegasys.teku.spec.logic.versions.capella.forktransition.CapellaStateUpgrade;
import tech.pegasys.teku.spec.logic.versions.capella.helpers.MiscHelpersCapella;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsCapella;

public class SpecLogicCapella extends AbstractSpecLogic {
Expand All @@ -44,7 +44,7 @@ public class SpecLogicCapella extends AbstractSpecLogic {

private SpecLogicCapella(
final Predicates predicates,
final MiscHelpersBellatrix miscHelpers,
final MiscHelpersCapella miscHelpers,
final BeaconStateAccessorsAltair beaconStateAccessors,
final BeaconStateMutatorsBellatrix beaconStateMutators,
final OperationSignatureVerifier operationSignatureVerifier,
Expand Down Expand Up @@ -86,7 +86,7 @@ public static SpecLogicCapella create(
final SpecConfigCapella config, final SchemaDefinitionsCapella schemaDefinitions) {
// Helpers
final Predicates predicates = new Predicates(config);
final MiscHelpersBellatrix miscHelpers = new MiscHelpersBellatrix(config);
final MiscHelpersCapella miscHelpers = new MiscHelpersCapella(config);
zilm13 marked this conversation as resolved.
Show resolved Hide resolved
final BeaconStateAccessorsAltair beaconStateAccessors =
new BeaconStateAccessorsAltair(config, predicates, miscHelpers);
final BeaconStateMutatorsBellatrix beaconStateMutators =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.capella.helpers;

import tech.pegasys.teku.spec.config.SpecConfig;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.MiscHelpersBellatrix;

public class MiscHelpersCapella extends MiscHelpersBellatrix {

public MiscHelpersCapella(final SpecConfig specConfig) {
super(specConfig);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@
import tech.pegasys.teku.spec.logic.versions.altair.util.AttestationUtilAltair;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BeaconStateMutatorsBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BellatrixTransitionHelpers;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.MiscHelpersBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.statetransition.epoch.EpochProcessorBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.util.BlindBlockUtilBellatrix;
import tech.pegasys.teku.spec.logic.versions.capella.block.BlockProcessorCapella;
import tech.pegasys.teku.spec.logic.versions.eip4844.forktransition.Eip4844StateUpgrade;
import tech.pegasys.teku.spec.logic.versions.eip4844.helpers.MiscHelpersEip4844;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip4844;

public class SpecLogicEip4844 extends AbstractSpecLogic {
private final Optional<SyncCommitteeUtil> syncCommitteeUtil;

private SpecLogicEip4844(
final Predicates predicates,
final MiscHelpersBellatrix miscHelpers,
final MiscHelpersEip4844 miscHelpers,
final BeaconStateAccessorsAltair beaconStateAccessors,
final BeaconStateMutatorsBellatrix beaconStateMutators,
final OperationSignatureVerifier operationSignatureVerifier,
Expand Down Expand Up @@ -83,7 +83,7 @@ public static SpecLogicEip4844 create(
final SpecConfigEip4844 config, final SchemaDefinitionsEip4844 schemaDefinitions) {
// Helpers
final Predicates predicates = new Predicates(config);
final MiscHelpersBellatrix miscHelpers = new MiscHelpersBellatrix(config);
final MiscHelpersEip4844 miscHelpers = new MiscHelpersEip4844(config);
final BeaconStateAccessorsAltair beaconStateAccessors =
new BeaconStateAccessorsAltair(config, predicates, miscHelpers);
final BeaconStateMutatorsBellatrix beaconStateMutators =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* 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 com.google.common.base.Preconditions.checkArgument;
import static tech.pegasys.teku.spec.config.SpecConfigEip4844.BLOB_TX_TYPE;
import static tech.pegasys.teku.spec.config.SpecConfigEip4844.VERSIONED_HASH_VERSION_KZG;

import com.google.common.annotations.VisibleForTesting;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt32;
import tech.pegasys.teku.infrastructure.crypto.Hash;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.kzg.KZGCommitment;
import tech.pegasys.teku.spec.config.SpecConfig;
import tech.pegasys.teku.spec.datastructures.execution.Transaction;
import tech.pegasys.teku.spec.datastructures.execution.versions.eip4844.BlobsSidecar;
import tech.pegasys.teku.spec.logic.versions.capella.helpers.MiscHelpersCapella;
import tech.pegasys.teku.spec.logic.versions.eip4844.types.VersionedHash;
import tech.pegasys.teku.spec.logic.versions.eip4844.util.KZGUtilEip4844;

public class MiscHelpersEip4844 extends MiscHelpersCapella {

public MiscHelpersEip4844(final SpecConfig specConfig) {
super(specConfig);
}

public void validateBlobSidecar(
final UInt64 slot,
final Bytes32 beaconBlockRoot,
final List<KZGCommitment> kzgCommitments,
final BlobsSidecar blobsSidecar) {
checkArgument(
slot.equals(blobsSidecar.getBeaconBlockSlot()),
"Block slot should match blobsSidecar slot");
checkArgument(
beaconBlockRoot.equals(blobsSidecar.getBeaconBlockRoot()),
"Block root should match blobsSidecar beacon block root");
checkArgument(
kzgCommitments.size() == blobsSidecar.getBlobs().size(),
"Number of kzgCommitments should match number of blobs");
KZGUtilEip4844.verifyAggregateKZGProof(
blobsSidecar.getBlobs(), kzgCommitments, blobsSidecar.getKZGAggregatedProof());
}

public boolean isDataAvailable(
final UInt64 slot,
final Bytes32 beaconBlockRoot,
final List<KZGCommitment> kzgCommitments,
final BlobsSidecar blobsSidecar) {
validateBlobSidecar(slot, beaconBlockRoot, kzgCommitments, blobsSidecar);
return true;
}

@VisibleForTesting
public VersionedHash kzgCommitmentToVersionedHash(final KZGCommitment kzgCommitment) {
return VersionedHash.create(
VERSIONED_HASH_VERSION_KZG, Hash.sha256(kzgCommitment.getBytesCompressed()));
}

@VisibleForTesting
public List<VersionedHash> txPeekBlobVersionedHashes(final Transaction transaction) {
checkArgument(isBlobTransaction(transaction), "Transaction should be of BLOB type");
final Bytes txData = transaction.getBytes();
// 1st byte is transaction type, next goes ssz encoded SignedBlobTransaction
// Getting variable length BlobTransaction offset, which is the message of signed tx
final int messageOffset =
UInt32.fromBytes(txData.slice(1, 4), ByteOrder.LITTLE_ENDIAN).add(1).intValue();
// Getting blobVersionedHashes field offset in BlobTransaction
// field offset: 32 + 8 + 32 + 32 + 8 + 4 + 32 + 4 + 4 + 32 = 188
final int blobVersionedHashesOffset =
messageOffset
+ UInt32.fromBytes(txData.slice(messageOffset + 188, 4), ByteOrder.LITTLE_ENDIAN)
.intValue();
final List<VersionedHash> versionedHashes = new ArrayList<>();
for (int hashStartOffset = blobVersionedHashesOffset;
hashStartOffset < txData.size();
hashStartOffset += VersionedHash.SIZE) {
versionedHashes.add(
new VersionedHash(Bytes32.wrap(txData.slice(hashStartOffset, VersionedHash.SIZE))));
}

return versionedHashes;
}

private boolean isBlobTransaction(final Transaction transaction) {
return transaction.getBytes().get(0) == BLOB_TX_TYPE.get(0);
}

public boolean verifyKZGCommitmentsAgainstTransactions(
final List<Transaction> transactions, final List<KZGCommitment> kzgCommitments) {
final List<VersionedHash> transactionsVersionedHashes =
transactions.stream()
.filter(this::isBlobTransaction)
.map(this::txPeekBlobVersionedHashes)
.flatMap(List::stream)
.collect(Collectors.toList());
final List<VersionedHash> commitmentsVersionedHashes =
kzgCommitments.stream()
.map(this::kzgCommitmentToVersionedHash)
.collect(Collectors.toList());
return transactionsVersionedHashes.equals(commitmentsVersionedHashes);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.types;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Objects;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;

public class VersionedHash {

public static final int SIZE = 32;

final Bytes version;
final Bytes value;

private VersionedHash(Bytes version, Bytes value) {
this.version = version;
this.value = value;
}

public VersionedHash(final Bytes32 value) {
this.version = value.slice(0, 1);
this.value = value.slice(1);
}

public static VersionedHash create(final Bytes version, final Bytes32 hash) {
checkArgument(version.size() == 1, "Version is 1-byte flag");
return new VersionedHash(version, hash.slice(1));
}

public boolean isVersion(final Bytes version) {
return this.version.equals(version);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
VersionedHash that = (VersionedHash) o;
return Objects.equals(version, that.version) && Objects.equals(value, that.value);
}

@Override
public int hashCode() {
return Objects.hash(version, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.util;

import java.util.List;
import tech.pegasys.teku.kzg.KZGCommitment;
import tech.pegasys.teku.kzg.KZGProof;
import tech.pegasys.teku.spec.datastructures.execution.versions.eip4844.Blob;

public class KZGUtilEip4844 {

public static void verifyAggregateKZGProof(
final List<Blob> blobs,

Check notice

Code scanning / CodeQL

Useless parameter

The parameter 'blobs' is never used.
final List<KZGCommitment> expectedKZGCommitments,

Check notice

Code scanning / CodeQL

Useless parameter

The parameter 'expectedKZGCommitments' is never used.
final KZGProof kzgProof) {

Check notice

Code scanning / CodeQL

Useless parameter

The parameter 'kzgProof' is never used.
// TODO: implement
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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 static tech.pegasys.teku.spec.config.SpecConfigEip4844.BLOB_TX_TYPE;
import static tech.pegasys.teku.spec.config.SpecConfigEip4844.VERSIONED_HASH_VERSION_KZG;

import com.google.common.io.ByteSource;
import com.google.common.io.Resources;
import java.io.IOException;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.Test;
import tech.pegasys.teku.kzg.KZGCommitment;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.TestSpecFactory;
import tech.pegasys.teku.spec.datastructures.execution.Transaction;
import tech.pegasys.teku.spec.datastructures.execution.TransactionSchema;
import tech.pegasys.teku.spec.logic.versions.eip4844.types.VersionedHash;

class MiscHelpersEip4844Test {

private static final String SIGNED_BLOB_TX_LOCATION = "signed_blob_transaction.ssz";
private static final VersionedHash VERSIONED_HASH =
VersionedHash.create(
VERSIONED_HASH_VERSION_KZG,
Bytes32.fromHexString(
"0x391610cf24e7c540192b80ddcfea77b0d3912d94e922682f3b286eee041e6f76"));

private final Spec spec = TestSpecFactory.createMinimalEip4844();
private final MiscHelpersEip4844 miscHelpersEip4844 =
new MiscHelpersEip4844(spec.getGenesisSpecConfig());

@Test
public void versionedHash() {
final VersionedHash actual =
miscHelpersEip4844.kzgCommitmentToVersionedHash(
KZGCommitment.fromHexString(
"0x85d1edf1ee88f68260e750abb2c766398ad1125d4e94e1de04034075ccbd2bb79c5689b952ef15374fd03ca2b2475371"));
assertThat(actual).isEqualTo(VERSIONED_HASH);
}

@Test
public void txPeekBlobVersionedHashes() throws IOException {
final Bytes sszTx = loadData(SIGNED_BLOB_TX_LOCATION);
assertThat(sszTx.get(0)).isEqualTo(BLOB_TX_TYPE.get(0));
final TransactionSchema transactionSchema =
new TransactionSchema(spec.getGenesisSpecConfig().toVersionEip4844().orElseThrow());
final Transaction blobTx = transactionSchema.sszDeserialize(sszTx);
List<VersionedHash> versionedHashes = miscHelpersEip4844.txPeekBlobVersionedHashes(blobTx);
assertThat(versionedHashes.size()).isEqualTo(5);
assertThat(
versionedHashes.stream().allMatch(hash -> hash.isVersion(VERSIONED_HASH_VERSION_KZG)))
.isTrue();
assertThat(versionedHashes.stream().allMatch(hash -> hash.equals(VERSIONED_HASH))).isTrue();
}

private Bytes loadData(final String location) throws IOException {
final ByteSource binaryData =
Resources.asByteSource(Resources.getResource(MiscHelpersEip4844Test.class, location));
return Bytes.wrap(binaryData.read());
}
}
Binary file not shown.
2 changes: 1 addition & 1 deletion infrastructure/crypto/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dependencies {
api 'org.bouncycastle:bcprov-jdk15on'
api 'org.apache.tuweni:tuweni-bytes'

implementation 'commons-io:commons-io'
zilm13 marked this conversation as resolved.
Show resolved Hide resolved

jmhImplementation 'org.bouncycastle:bcprov-jdk15on'
jmhImplementation project(':infrastructure:crypto')
Expand Down