Skip to content

Commit

Permalink
Optimize Blob Transaction Validation (ethereum#9)
Browse files Browse the repository at this point in the history
* remove debug println

* Optimize Blob Tx validation using KZG Proofs

Implementing the latest EIP-4844 changes for optimizing blob
transactions.

* fix eth tests

* compute aggregate proof without inverse fft

Benchmarks indicate this doesn't improve or worsen performance. But it's
one less dependency to worry about.

* Eval poly main loop using bls.Fr - less mem usage
  • Loading branch information
Inphi authored Jul 19, 2022
1 parent d43042a commit c76d2bd
Show file tree
Hide file tree
Showing 17 changed files with 606 additions and 100 deletions.
6 changes: 5 additions & 1 deletion accounts/external/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,14 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
case types.BlobTxType:
hashes, _, blobs := tx.BlobWrapData()
hashes, _, blobs, aggProof := tx.BlobWrapData()
if len(hashes) != len(blobs) {
return nil, fmt.Errorf("missing blobs data, expected %d blobs", len(hashes))
}
var z types.KZGProof
if aggProof == z {
return nil, fmt.Errorf("missing aggregated proof in blobs")
}
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
args.Blobs = blobs
Expand Down
12 changes: 8 additions & 4 deletions cmd/devp2p/internal/ethtest/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
return fmt.Errorf("peering failed: %v", err)
}
// Send the transaction
if err = sendConn.Write(&Transactions{tx}); err != nil {
if err = sendConn.Write(&Transactions{types.NewNetworkTransaction(tx)}); err != nil {
return fmt.Errorf("failed to write to connection: %v", err)
}
// peer receiving connection to node
Expand All @@ -82,7 +82,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
recTxs := *msg
// if you receive an old tx propagation, read from connection again
if len(recTxs) == 1 && prevTx != nil {
if recTxs[0] == prevTx {
if recTxs[0].Tx == prevTx {
continue
}
}
Expand Down Expand Up @@ -168,7 +168,7 @@ func sendMaliciousTx(s *Suite, tx *types.Transaction, isEth66 bool) error {
return fmt.Errorf("peering failed: %v", err)
}
// write malicious tx
if err = conn.Write(&Transactions{tx}); err != nil {
if err = conn.Write(&Transactions{types.NewNetworkTransaction(tx)}); err != nil {
return fmt.Errorf("failed to write to connection: %v", err)
}
return nil
Expand All @@ -179,7 +179,11 @@ var nonce = uint64(99)
// sendMultipleSuccessfulTxs sends the given transactions to the node and
// expects the node to accept and propagate them.
func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction) error {
txMsg := Transactions(txs)
ntxs := make([]*types.NetworkTransaction, len(txs))
for i := range txs {
ntxs[i] = types.NewNetworkTransaction(txs[i])
}
txMsg := Transactions(ntxs)
t.Logf("sending %d txs\n", len(txs))

sendConn, recvConn, err := s.createSendAndRecvConns(true)
Expand Down
15 changes: 11 additions & 4 deletions core/beacon/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package beacon

import (
"errors"
"fmt"
"math/big"

Expand All @@ -42,9 +43,10 @@ type payloadAttributesMarshaling struct {

// BlobsBundleV1 holds the blobs of an execution payload, to be retrieved separately
type BlobsBundleV1 struct {
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
KZGs []types.KZGCommitment `json:"kzgs" gencodec:"required"`
Blobs []types.Blob `json:"blobs" gencodec:"required"`
BlockHash common.Hash `json:"blockHash" gencodec:"required"`
KZGs []types.KZGCommitment `json:"kzgs" gencodec:"required"`
Blobs []types.Blob `json:"blobs" gencodec:"required"`
AggregatedProof types.KZGProof `json:"aggregatedProof" gencodec:"required"`
}

//go:generate go run github.com/fjl/gencodec -type ExecutableDataV1 -field-override executableDataMarshaling -out gen_ed.go
Expand Down Expand Up @@ -213,13 +215,18 @@ func BlockToBlobData(block *types.Block) (*BlobsBundleV1, error) {
blobsBundle := &BlobsBundleV1{BlockHash: blockHash}
for i, tx := range block.Transactions() {
if tx.Type() == types.BlobTxType {
versionedHashes, kzgs, blobs := tx.BlobWrapData()
versionedHashes, kzgs, blobs, aggProof := tx.BlobWrapData()
if len(versionedHashes) != len(kzgs) || len(versionedHashes) != len(blobs) {
return nil, fmt.Errorf("tx %d in block %s has inconsistent blobs (%d) / kzgs (%d)"+
" / versioned hashes (%d)", i, blockHash, len(blobs), len(kzgs), len(versionedHashes))
}
var zProof types.KZGProof
if zProof == aggProof {
return nil, errors.New("aggregated proof is not available in blobs")
}
blobsBundle.Blobs = append(blobsBundle.Blobs, blobs...)
blobsBundle.KZGs = append(blobsBundle.KZGs, kzgs...)
blobsBundle.AggregatedProof = aggProof
}
}
return blobsBundle, nil
Expand Down
20 changes: 2 additions & 18 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto/kzg"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
Expand Down Expand Up @@ -1012,24 +1011,9 @@ func (pool *TxPool) filterInvalidTxsLocked(txs []*types.Transaction, errs []erro

// filterInvalidBlobTxsLocked marks all blob txs (if any) with an error if the blobs or kzg commitments are invalid
func (pool *TxPool) filterInvalidBlobTxsLocked(txs []*types.Transaction, errs []error) {
// We batch multiple transactions together.
var batchVerify kzg.BlobsBatch
for i, tx := range txs {
if errs[i] != nil {
continue
}
errs[i] = tx.VerifyBlobsBatched(batchVerify.Join)
}
if err := batchVerify.Verify(); err != nil {
// we'll have to verify each individual blob tx (can still use batch per tx)
// to not throw away the good ones because of some bad tx.
for i, tx := range txs {
if errs[i] != nil {
continue
}
// all blobs within the tx can still be batched together
errs[i] = tx.VerifyBlobsBatched(kzg.VerifyBlobs)
}
// all blobs within the tx can still be batched together
errs[i] = tx.VerifyBlobs()
}
}

Expand Down
Loading

0 comments on commit c76d2bd

Please sign in to comment.