core, eth/downloader, params: validate blob tx bodies (#27392)

This commit is contained in:
Péter Szilágyi 2023-05-31 11:12:26 +03:00 committed by GitHub
parent 1f9b69b36d
commit 495692c9db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 0 deletions

@ -84,7 +84,23 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Blob transactions may be present after the Cancun fork. // Blob transactions may be present after the Cancun fork.
var blobs int var blobs int
for _, tx := range block.Transactions() { for _, tx := range block.Transactions() {
// Count the number of blobs to validate against the header's dataGasUsed
blobs += len(tx.BlobHashes()) blobs += len(tx.BlobHashes())
// Validate the data blobs individually too
if tx.Type() == types.BlobTxType {
if tx.To() == nil {
return errors.New("contract creation attempt by blob transaction") // TODO(karalabe): Why not make the field non-nil-able
}
if len(tx.BlobHashes()) == 0 {
return errors.New("no-blob blob transaction present in block body")
}
for _, hash := range tx.BlobHashes() {
if hash[0] != params.BlobTxHashVersion {
return fmt.Errorf("blob hash version mismatch (have %d, supported %d)", hash[0], params.BlobTxHashVersion)
}
}
}
} }
if header.DataGasUsed != nil { if header.DataGasUsed != nil {
if want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated if want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated

@ -801,7 +801,23 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
// and zero before the Cancun hardfork // and zero before the Cancun hardfork
var blobs int var blobs int
for _, tx := range txLists[index] { for _, tx := range txLists[index] {
// Count the number of blobs to validate against the header's dataGasUsed
blobs += len(tx.BlobHashes()) blobs += len(tx.BlobHashes())
// Validate the data blobs individually too
if tx.Type() == types.BlobTxType {
if tx.To() == nil {
return errInvalidBody // TODO(karalabe): Why not make the field non-nil-able
}
if len(tx.BlobHashes()) == 0 {
return errInvalidBody
}
for _, hash := range tx.BlobHashes() {
if hash[0] != params.BlobTxHashVersion {
return errInvalidBody
}
}
}
} }
if header.DataGasUsed != nil { if header.DataGasUsed != nil {
if want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated if want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated

@ -160,6 +160,7 @@ const (
RefundQuotient uint64 = 2 RefundQuotient uint64 = 2
RefundQuotientEIP3529 uint64 = 5 RefundQuotientEIP3529 uint64 = 5
BlobTxHashVersion = 0x01 // Version byte of the commitment hash
BlobTxMaxDataGasPerBlock = 1 << 19 // Maximum consumable data gas for data blobs per block BlobTxMaxDataGasPerBlock = 1 << 19 // Maximum consumable data gas for data blobs per block
BlobTxTargetDataGasPerBlock = 1 << 18 // Target consumable data gas for data blobs per block (for 1559-like pricing) BlobTxTargetDataGasPerBlock = 1 << 18 // Target consumable data gas for data blobs per block (for 1559-like pricing)
BlobTxDataGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size) BlobTxDataGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)