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. 11
      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<KZGProof> kzgProofs,
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()
|| blobs.size() != kzgProofs.size()
|| kzgCommitments.size() != versionedHashes.size()) {
|| blobs.size() != versionedHashes.size()) {
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.blobs = blobs;

@ -22,19 +22,70 @@ import java.security.InvalidParameterException;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.Test;
public class BlobsWithCommitmentsTest {
@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 =
assertThrows(
InvalidParameterException.class,
() ->
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();
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);
}
}

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

@ -189,14 +189,15 @@ public class Transaction
if (versionedHashes.isPresent() || maxFeePerBlobGas.isPresent()) {
checkArgument(
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()) {
checkArgument(
versionedHashes.isPresent(), "Must specify blob versioned hashes for blob transaction");
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(
maxFeePerBlobGas.isPresent(), "Must specify max fee per blob gas for blob transaction");
}
@ -680,14 +681,14 @@ public class Transaction
if (transactionType.supportsBlob()) {
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();
}
}
/**
* Returns whether the transaction is a contract creation

@ -73,7 +73,7 @@ public class TransactionBuilderTest {
.createTransaction(senderKeys);
fail();
} 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 ProtocolSchedule protocolSchedule,
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 =
blockchainResponder(blockchain, worldStateArchive, transactionPool);

Loading…
Cancel
Save