diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java index f64ebf5aea..de2195887b 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGCommitment.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; } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java index 3a7a2d0686..6410609e23 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/KZGProof.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 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; } } diff --git a/datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java b/datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java index 9816288e82..a3eb7bbe0f 100644 --- a/datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java +++ b/datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java @@ -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")))))) diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index 020c8e4adc..cc54415ff5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -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(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 927e4cd8a2..cdeec19b11 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -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 contextVariablesBuilder = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java index cfcd411bf5..b7bea07007 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java @@ -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)); } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlobTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlobTestFixture.java index 55500f0603..d22d20023a 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlobTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlobTestFixture.java @@ -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)), diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java index 536a93957a..5ab351c2ef 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java @@ -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); diff --git a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/AbstractRLPInput.java b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/AbstractRLPInput.java index 43413d7995..93a0bcebdf 100644 --- a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/AbstractRLPInput.java +++ b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/AbstractRLPInput.java @@ -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 readBytes(final Function mapper) { final Bytes res = readBytes(); diff --git a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/BytesValueRLPInput.java b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/BytesValueRLPInput.java index 73eee23856..ac8ac8d6f4 100644 --- a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/BytesValueRLPInput.java +++ b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/BytesValueRLPInput.java @@ -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); diff --git a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java index e8f966ed1b..808c8f74d5 100644 --- a/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java +++ b/ethereum/rlp/src/main/java/org/hyperledger/besu/ethereum/rlp/RLPInput.java @@ -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.