Use existing Bytes48 for KZGCommitment and KZGProof (#5997)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
pull/6024/head
Fabio Di Fabio 1 year ago committed by GitHub
parent 9ec055caac
commit e946276d21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java
  2. 10
      datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java
  3. 9
      datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java
  4. 12
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java
  5. 5
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
  6. 52
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java
  7. 8
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlobTestFixture.java
  8. 5
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java
  9. 11
      ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/AbstractRLPInput.java
  10. 6
      ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/BytesValueRLPInput.java
  11. 11
      ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java

@ -17,18 +17,18 @@ package org.hyperledger.besu.datatypes;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes48;
/** This class contains the data for a KZG commitment. */
public class KZGCommitment {
final Bytes data;
final Bytes48 data;
/**
* Constructor for a KZG commitment.
*
* @param data The data for the KZG commitment.
*/
public KZGCommitment(final Bytes data) {
public KZGCommitment(final Bytes48 data) {
this.data = data;
}
@ -39,7 +39,7 @@ public class KZGCommitment {
* @return The KZG commitment.
*/
public static KZGCommitment readFrom(final RLPInput input) {
final Bytes bytes = input.readBytes();
final Bytes48 bytes = input.readBytes48();
return new KZGCommitment(bytes);
}
@ -57,7 +57,7 @@ public class KZGCommitment {
*
* @return The data for the KZG commitment.
*/
public Bytes getData() {
public Bytes48 getData() {
return data;
}
}

@ -17,18 +17,18 @@ package org.hyperledger.besu.datatypes;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes48;
/** This class contains the data for a KZG proof for a KZG commitment. */
public class KZGProof {
final Bytes data;
final Bytes48 data;
/**
* Constructor for a KZG proof.
*
* @param data The data for the KZG proof.
*/
public KZGProof(final Bytes data) {
public KZGProof(final Bytes48 data) {
this.data = data;
}
@ -39,7 +39,7 @@ public class KZGProof {
* @return The KZG proof.
*/
public static KZGProof readFrom(final RLPInput input) {
final Bytes bytes = input.readBytes();
final Bytes48 bytes = input.readBytes48();
return new KZGProof(bytes);
}
@ -57,7 +57,7 @@ public class KZGProof {
*
* @return The data for the KZG proof.
*/
public Bytes getData() {
public Bytes48 getData() {
return data;
}
}

@ -23,6 +23,7 @@ import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.Bytes48;
import org.junit.jupiter.api.Test;
public class BlobsWithCommitmentsTest {
@ -45,9 +46,9 @@ public class BlobsWithCommitmentsTest {
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.of(1))),
List.of(new KZGCommitment(Bytes48.fromHexStringLenient("1"))),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of(new KZGProof(Bytes48.ZERO)),
List.of()))
.getMessage();
final String expectedMessage =
@ -64,7 +65,7 @@ public class BlobsWithCommitmentsTest {
new BlobsWithCommitments(
List.of(),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of(new KZGProof(Bytes48.ZERO)),
List.of(new VersionedHash(Bytes32.rightPad(Bytes.fromHexString("0x01"))))))
.getMessage();
final String expectedMessage =
@ -79,7 +80,7 @@ public class BlobsWithCommitmentsTest {
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.of(1))),
List.of(new KZGCommitment(Bytes48.fromHexStringLenient("1"))),
List.of(new Blob(Bytes.EMPTY)),
List.of(),
List.of(new VersionedHash(Bytes32.rightPad(Bytes.fromHexString("0x01"))))))

@ -927,17 +927,19 @@ public class Transaction
sb.append("nonce=").append(getNonce()).append(", ");
getGasPrice()
.ifPresent(
gasPrice -> sb.append("gasPrice=").append(gasPrice.toShortHexString()).append(", "));
gasPrice ->
sb.append("gasPrice=").append(gasPrice.toHumanReadableString()).append(", "));
if (getMaxPriorityFeePerGas().isPresent() && getMaxFeePerGas().isPresent()) {
sb.append("maxPriorityFeePerGas=")
.append(getMaxPriorityFeePerGas().map(Wei::toShortHexString).get())
.append(getMaxPriorityFeePerGas().map(Wei::toHumanReadableString).get())
.append(", ");
sb.append("maxFeePerGas=")
.append(getMaxFeePerGas().map(Wei::toShortHexString).get())
.append(getMaxFeePerGas().map(Wei::toHumanReadableString).get())
.append(", ");
getMaxFeePerBlobGas()
.ifPresent(
wei -> sb.append("maxFeePerBlobGas=").append(wei.toShortHexString()).append(", "));
wei ->
sb.append("maxFeePerBlobGas=").append(wei.toHumanReadableString()).append(", "));
}
sb.append("gasLimit=").append(getGasLimit()).append(", ");
if (getTo().isPresent()) sb.append("to=").append(getTo().get()).append(", ");
@ -993,7 +995,7 @@ public class Transaction
}
sb.append("gl: ").append(getGasLimit()).append(", ");
sb.append("v: ").append(getValue().toHumanReadableString()).append(", ");
getTo().ifPresent(to -> sb.append(to));
getTo().ifPresent(to -> sb.append("to: ").append(to));
return sb.append("}").toString();
}

@ -339,12 +339,11 @@ public class MainnetTransactionProcessor {
gasCalculator.accessListGasCost(accessListEntries.size(), accessListStorageCount);
final long gasAvailable = transaction.getGasLimit() - intrinsicGas - accessListGas;
LOG.trace(
"Gas available for execution {} = {} - {} - {} - {} (limit - intrinsic - accessList - data)",
"Gas available for execution {} = {} - {} - {} (limit - intrinsic - accessList)",
gasAvailable,
transaction.getGasLimit(),
intrinsicGas,
accessListGas,
blobGas);
accessListGas);
final WorldUpdater worldUpdater = worldState.updater();
final ImmutableMap.Builder<String, Object> contextVariablesBuilder =

@ -22,7 +22,6 @@ import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.KZGCommitment;
import org.hyperledger.besu.datatypes.KZGProof;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
@ -51,8 +50,6 @@ import org.bouncycastle.crypto.digests.SHA256Digest;
*/
public class MainnetTransactionValidator implements TransactionValidator {
private static final byte BLOB_COMMITMENT_VERSION_KZG = 0x01;
private final GasCalculator gasCalculator;
private final GasLimitCalculator gasLimitCalculator;
private final FeeMarket feeMarket;
@ -336,11 +333,11 @@ public class MainnetTransactionValidator implements TransactionValidator {
final KZGCommitment commitment = blobsWithCommitments.getKzgCommitments().get(i);
final VersionedHash versionedHash = versionedHashes.get(i);
if (versionedHash.getVersionId() != BLOB_COMMITMENT_VERSION_KZG) {
if (versionedHash.getVersionId() != VersionedHash.SHA256_VERSION_ID) {
return ValidationResult.invalid(
TransactionInvalidReason.INVALID_BLOBS,
"transaction blobs commitment version is not supported. Expected "
+ BLOB_COMMITMENT_VERSION_KZG
+ VersionedHash.SHA256_VERSION_ID
+ ", found "
+ versionedHash.getVersionId());
}
@ -353,30 +350,27 @@ public class MainnetTransactionValidator implements TransactionValidator {
}
}
final Bytes blobs =
blobsWithCommitments.getBlobs().stream()
.map(Blob::getData)
.reduce(Bytes::concatenate)
.orElseThrow();
final byte[] blobs =
Bytes.wrap(blobsWithCommitments.getBlobs().stream().map(Blob::getData).toList())
.toArrayUnsafe();
final Bytes kzgCommitments =
blobsWithCommitments.getKzgCommitments().stream()
.map(KZGCommitment::getData)
.reduce(Bytes::concatenate)
.orElseThrow();
final byte[] kzgCommitments =
Bytes.wrap(
blobsWithCommitments.getKzgCommitments().stream()
.map(kc -> (Bytes) kc.getData())
.toList())
.toArrayUnsafe();
final Bytes kzgProofs =
blobsWithCommitments.getKzgProofs().stream()
.map(KZGProof::getData)
.reduce(Bytes::concatenate)
.orElseThrow();
final byte[] kzgProofs =
Bytes.wrap(
blobsWithCommitments.getKzgProofs().stream()
.map(kp -> (Bytes) kp.getData())
.toList())
.toArrayUnsafe();
final boolean kzgVerification =
CKZG4844JNI.verifyBlobKzgProofBatch(
blobs.toArrayUnsafe(),
kzgCommitments.toArrayUnsafe(),
kzgProofs.toArrayUnsafe(),
blobsWithCommitments.getBlobs().size());
blobs, kzgCommitments, kzgProofs, blobsWithCommitments.getBlobs().size());
if (!kzgVerification) {
return ValidationResult.invalid(
@ -387,14 +381,6 @@ public class MainnetTransactionValidator implements TransactionValidator {
return ValidationResult.valid();
}
/*
private VersionedHash hashCommitment(final Bytes32 commitment) {
return new VersionedHash(
VersionedHash.SHA256_VERSION_ID, Sha256Hash.hash(commitment));
}
*/
private VersionedHash hashCommitment(final KZGCommitment commitment) {
final SHA256Digest digest = new SHA256Digest();
digest.update(commitment.getData().toArrayUnsafe(), 0, commitment.getData().size());
@ -403,7 +389,7 @@ public class MainnetTransactionValidator implements TransactionValidator {
digest.doFinal(dig, 0);
dig[0] = BLOB_COMMITMENT_VERSION_KZG;
dig[0] = VersionedHash.SHA256_VERSION_ID;
return new VersionedHash(Bytes32.wrap(dig));
}
}

@ -15,7 +15,6 @@
package org.hyperledger.besu.ethereum.core;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import org.hyperledger.besu.datatypes.Blob;
@ -33,6 +32,7 @@ import java.util.List;
import ethereum.ckzg4844.CKZG4844JNI;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.Bytes48;
import org.bouncycastle.crypto.digests.SHA256Digest;
public class BlobTestFixture {
@ -68,10 +68,10 @@ public class BlobTestFixture {
fail("Failed to read blob file", e);
}
Bytes commitment = Bytes.wrap(CKZG4844JNI.blobToKzgCommitment(rawMaterial));
Bytes48 commitment = Bytes48.wrap(CKZG4844JNI.blobToKzgCommitment(rawMaterial));
assertThat(commitment.size()).isEqualTo(48);
Bytes proof = Bytes.wrap(CKZG4844JNI.computeBlobKzgProof(rawMaterial, commitment.toArray()));
Bytes48 proof =
Bytes48.wrap(CKZG4844JNI.computeBlobKzgProof(rawMaterial, commitment.toArray()));
VersionedHash versionedHash = hashCommitment(new KZGCommitment(commitment));
return new BlobTriplet(
new Blob(Bytes.wrap(rawMaterial)),

@ -57,6 +57,7 @@ import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes48;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
@ -503,9 +504,9 @@ public class MainnetTransactionValidatorTest {
.blobsWithCommitments(
Optional.of(
new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.EMPTY)),
List.of(new KZGCommitment(Bytes48.ZERO)),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of(new KZGProof(Bytes48.ZERO)),
List.of(VersionedHash.DEFAULT_VERSIONED_HASH))))
.versionedHashes(Optional.of(List.of(VersionedHash.DEFAULT_VERSIONED_HASH)))
.createTransaction(senderKeys);

@ -24,6 +24,7 @@ import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.Bytes48;
import org.apache.tuweni.bytes.MutableBytes;
import org.apache.tuweni.bytes.MutableBytes32;
import org.apache.tuweni.units.bigints.UInt256;
@ -98,6 +99,8 @@ abstract class AbstractRLPInput implements RLPInput {
protected abstract Bytes32 inputSlice32(long offset);
protected abstract Bytes48 inputSlice48(long offset);
protected abstract String inputHex(long offset, int length);
protected abstract BigInteger getUnsignedBigInteger(long offset, int length);
@ -426,6 +429,14 @@ abstract class AbstractRLPInput implements RLPInput {
return res;
}
@Override
public Bytes48 readBytes48() {
checkElt("48 bytes value", 48);
final Bytes48 res = inputSlice48(currentPayloadOffset);
setTo(nextItem());
return res;
}
@Override
public <T> T readBytes(final Function<Bytes, T> mapper) {
final Bytes res = readBytes();

@ -18,6 +18,7 @@ import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.Bytes48;
/** An {@link RLPInput} that reads RLP encoded data from a {@link Bytes}. */
public class BytesValueRLPInput extends AbstractRLPInput {
@ -51,6 +52,11 @@ public class BytesValueRLPInput extends AbstractRLPInput {
return Bytes32.wrap(inputSlice(offset, 32));
}
@Override
protected Bytes48 inputSlice48(final long offset) {
return Bytes48.wrap(inputSlice(offset, 48));
}
@Override
protected String inputHex(final long offset, final int length) {
return value.slice(Math.toIntExact(offset), length).toString().substring(2);

@ -22,6 +22,7 @@ import java.util.function.Function;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.bytes.Bytes48;
import org.apache.tuweni.units.bigints.UInt256;
import org.apache.tuweni.units.bigints.UInt64;
@ -300,6 +301,16 @@ public interface RLPInput {
*/
Bytes32 readBytes32();
/**
* Reads the next item of this input (assuming it is not a list) that must be exact 48 bytes.
*
* @return The next item read of this input.
* @throws RLPException if the next item to read is a list, the input is at the end of its current
* list (and {@link #leaveList()} hasn't been called) or the next element is not exactly 48
* bytes.
*/
Bytes48 readBytes48();
/**
* Reads the next item of this input (assuming it is not a list) and transforms it with the
* provided mapping function.

Loading…
Cancel
Save