Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions core/block_validator.go
Expand Up @@ -84,7 +84,23 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Blob transactions may be present after the Cancun fork.
var blobs int
for _, tx := range block.Transactions() {
// Count the number of blobs to validate against the header's dataGasUsed
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 want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated
Expand Down
16 changes: 16 additions & 0 deletions eth/downloader/queue.go
Expand Up @@ -801,7 +801,23 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
// and zero before the Cancun hardfork
var blobs int
for _, tx := range txLists[index] {
// Count the number of blobs to validate against the header's dataGasUsed
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 want := *header.DataGasUsed / params.BlobTxDataGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated
Expand Down
1 change: 1 addition & 0 deletions params/protocol_params.go
Expand Up @@ -160,6 +160,7 @@ const (
RefundQuotient uint64 = 2
RefundQuotientEIP3529 uint64 = 5

BlobTxHashVersion = 0x01 // Version byte of the commitment hash
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)
BlobTxDataGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
Expand Down