Skip to content

Commit

Permalink
Create MiscHelpersEip4844 (#6474)
Browse files Browse the repository at this point in the history
* Create MiscHelpersEip4844

* Add VersionedHash

* Add MiscHelpersEip4844 tests

* Remove BlobTransaction container and switch txPeekBlobVersionedHashes to magic offsets
  • Loading branch information
zilm13 authored Nov 22, 2022
1 parent 1736c6c commit bb0e75b
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 3 deletions.
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.bellatrix.helpers.MiscHelpersBellatrix;
import tech.pegasys.teku.spec.logic.versions.eip4844.types.VersionedHash;
import tech.pegasys.teku.spec.logic.versions.eip4844.util.KZGUtilEip4844;

public class MiscHelpersEip4844 extends MiscHelpersBellatrix {

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,
final List<KZGCommitment> expectedKZGCommitments,
final KZGProof kzgProof) {
// 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.

0 comments on commit bb0e75b

Please sign in to comment.