enforce that BlobTransactions have at least one blob (#5826)

* enforce that BlobTransactions have at least one blob

Signed-off-by: Stefan <stefan.pingel@consensys.net>
Signed-off-by: Stefan Pingel <16143240+pinges@users.noreply.github.com>
pull/5843/head
Stefan Pingel 1 year ago committed by GitHub
parent c16a3274b3
commit e3b01122f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobsWithCommitments.java
  2. 57
      datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java
  3. 2
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java
  4. 15
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java
  5. 2
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/TransactionBuilderTest.java
  6. 2
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RespondingEthPeer.java

@ -38,11 +38,15 @@ public class BlobsWithCommitments {
final List<Blob> blobs, final List<Blob> blobs,
final List<KZGProof> kzgProofs, final List<KZGProof> kzgProofs,
final List<VersionedHash> versionedHashes) { final List<VersionedHash> versionedHashes) {
if (blobs.size() == 0) {
throw new InvalidParameterException(
"There needs to be a minimum of one blob in a blob transaction with commitments");
}
if (blobs.size() != kzgCommitments.size() if (blobs.size() != kzgCommitments.size()
|| blobs.size() != kzgProofs.size() || blobs.size() != kzgProofs.size()
|| kzgCommitments.size() != versionedHashes.size()) { || blobs.size() != versionedHashes.size()) {
throw new InvalidParameterException( throw new InvalidParameterException(
"There must be an equal number of blobs, commitments and proofs"); "There must be an equal number of blobs, commitments, proofs, and versioned hashes");
} }
this.kzgCommitments = kzgCommitments; this.kzgCommitments = kzgCommitments;
this.blobs = blobs; this.blobs = blobs;

@ -22,19 +22,70 @@ import java.security.InvalidParameterException;
import java.util.List; import java.util.List;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class BlobsWithCommitmentsTest { public class BlobsWithCommitmentsTest {
@Test @Test
public void blobsWithCommitmentsMustHaveSameNumberOfElements() { public void blobsWithCommitmentsMustHaveAtLeastOneBlob() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() -> new BlobsWithCommitments(List.of(), List.of(), List.of(), List.of()))
.getMessage();
final String expectedMessage =
"There needs to be a minimum of one blob in a blob transaction with commitments";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
@Test
public void blobsWithCommitmentsMustHaveSameNumberOfElementsVersionedHashes() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.of(1))),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of()))
.getMessage();
final String expectedMessage =
"There must be an equal number of blobs, commitments, proofs, and versioned hashes";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
@Test
public void blobsWithCommitmentsMustHaveSameNumberOfElementsKZGCommitment() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of(new VersionedHash(Bytes32.rightPad(Bytes.fromHexString("0x01"))))))
.getMessage();
final String expectedMessage =
"There must be an equal number of blobs, commitments, proofs, and versioned hashes";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
@Test
public void blobsWithCommitmentsMustHaveSameNumberOfElementsKZGProof() {
String actualMessage = String actualMessage =
assertThrows( assertThrows(
InvalidParameterException.class, InvalidParameterException.class,
() -> () ->
new BlobsWithCommitments( new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.of(1))), List.of(), List.of(), List.of())) List.of(new KZGCommitment(Bytes.of(1))),
List.of(new Blob(Bytes.EMPTY)),
List.of(),
List.of(new VersionedHash(Bytes32.rightPad(Bytes.fromHexString("0x01"))))))
.getMessage(); .getMessage();
final String expectedMessage = "There must be an equal number of blobs, commitments and proofs"; final String expectedMessage =
"There must be an equal number of blobs, commitments, proofs, and versioned hashes";
assertThat(actualMessage).isEqualTo(expectedMessage); assertThat(actualMessage).isEqualTo(expectedMessage);
} }
} }

@ -209,7 +209,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
blockParam.getPrevRandao(), blockParam.getPrevRandao(),
0, 0,
maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null), maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null),
blockParam.getBlobGasUsed() == null ? null : blockParam.getBlobGasUsed(), blockParam.getBlobGasUsed(),
blockParam.getExcessBlobGas() == null blockParam.getExcessBlobGas() == null
? null ? null
: BlobGas.fromHexString(blockParam.getExcessBlobGas()), : BlobGas.fromHexString(blockParam.getExcessBlobGas()),

@ -189,14 +189,15 @@ public class Transaction
if (versionedHashes.isPresent() || maxFeePerBlobGas.isPresent()) { if (versionedHashes.isPresent() || maxFeePerBlobGas.isPresent()) {
checkArgument( checkArgument(
transactionType.supportsBlob(), transactionType.supportsBlob(),
"Must not specify blob versioned hashes of max fee per blob gas for transaction not supporting it"); "Must not specify blob versioned hashes or max fee per blob gas for transaction not supporting it");
} }
if (transactionType.supportsBlob()) { if (transactionType.supportsBlob()) {
checkArgument( checkArgument(
versionedHashes.isPresent(), "Must specify blob versioned hashes for blob transaction"); versionedHashes.isPresent(), "Must specify blob versioned hashes for blob transaction");
checkArgument( checkArgument(
!versionedHashes.get().isEmpty(), "Blob transaction must have at least one blob"); !versionedHashes.get().isEmpty(),
"Blob transaction must have at least one versioned hash");
checkArgument( checkArgument(
maxFeePerBlobGas.isPresent(), "Must specify max fee per blob gas for blob transaction"); maxFeePerBlobGas.isPresent(), "Must specify max fee per blob gas for blob transaction");
} }
@ -680,13 +681,13 @@ public class Transaction
if (transactionType.supportsBlob()) { if (transactionType.supportsBlob()) {
if (getBlobsWithCommitments().isPresent()) { if (getBlobsWithCommitments().isPresent()) {
size = TransactionEncoder.encodeOpaqueBytes(this).size(); size = bytes.size();
return;
} }
} else {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
TransactionEncoder.encodeForWire(transactionType, bytes, rlpOutput);
size = rlpOutput.encodedSize();
} }
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
TransactionEncoder.encodeForWire(transactionType, bytes, rlpOutput);
size = rlpOutput.encodedSize();
} }
/** /**

@ -73,7 +73,7 @@ public class TransactionBuilderTest {
.createTransaction(senderKeys); .createTransaction(senderKeys);
fail(); fail();
} catch (IllegalArgumentException iea) { } catch (IllegalArgumentException iea) {
assertThat(iea).hasMessage("Blob transaction must have at least one blob"); assertThat(iea).hasMessage("Blob transaction must have at least one versioned hash");
} }
} }
} }

@ -307,7 +307,7 @@ public class RespondingEthPeer {
final TransactionPool transactionPool, final TransactionPool transactionPool,
final ProtocolSchedule protocolSchedule, final ProtocolSchedule protocolSchedule,
final float portion) { final float portion) {
checkArgument(portion >= 0.0 && portion <= 1.0, "Portion is in the range [0.0..1.0]"); checkArgument(portion >= 0.0 && portion <= 1.0, "Portion is not in the range [0.0..1.0]");
final Responder fullResponder = final Responder fullResponder =
blockchainResponder(blockchain, worldStateArchive, transactionPool); blockchainResponder(blockchain, worldStateArchive, transactionPool);

Loading…
Cancel
Save