diff --git a/cmd/devp2p/internal/ethtest/conn.go b/cmd/devp2p/internal/ethtest/conn.go index 8d1998c921..66924d8f54 100644 --- a/cmd/devp2p/internal/ethtest/conn.go +++ b/cmd/devp2p/internal/ethtest/conn.go @@ -66,9 +66,11 @@ func (s *Suite) dialAs(key *ecdsa.PrivateKey) (*Conn, error) { return nil, err } conn.caps = []p2p.Cap{ + {Name: "eth", Version: 72}, + {Name: "eth", Version: 70}, {Name: "eth", Version: 69}, } - conn.ourHighestProtoVersion = 69 + conn.ourHighestProtoVersion = 72 return &conn, nil } @@ -167,11 +169,15 @@ func (c *Conn) ReadEth() (any, error) { case eth.TransactionsMsg: msg = new(eth.TransactionsPacket) case eth.NewPooledTransactionHashesMsg: - msg = new(eth.NewPooledTransactionHashesPacket70) + msg = new(eth.NewPooledTransactionHashesPacket72) case eth.GetPooledTransactionsMsg: msg = new(eth.GetPooledTransactionsPacket) case eth.PooledTransactionsMsg: msg = new(eth.PooledTransactionsPacket) + case eth.GetCellsMsg: + msg = new(eth.GetCellsRequest) + case eth.CellsMsg: + msg = new(eth.CellsResponse) default: panic(fmt.Sprintf("unhandled eth msg code %d", code)) } diff --git a/cmd/devp2p/internal/ethtest/protocol.go b/cmd/devp2p/internal/ethtest/protocol.go index a21d1ca7a1..9da3142f5b 100644 --- a/cmd/devp2p/internal/ethtest/protocol.go +++ b/cmd/devp2p/internal/ethtest/protocol.go @@ -32,7 +32,7 @@ const ( // Unexported devp2p protocol lengths from p2p package. const ( baseProtoLen = 16 - ethProtoLen = 18 + ethProtoLen = 20 snapProtoLen = 8 ) diff --git a/cmd/devp2p/internal/ethtest/suite.go b/cmd/devp2p/internal/ethtest/suite.go index b21fedb96d..286872ff63 100644 --- a/cmd/devp2p/internal/ethtest/suite.go +++ b/cmd/devp2p/internal/ethtest/suite.go @@ -865,7 +865,7 @@ the transactions using a GetPooledTransactions request.`) } // Send announcement. - ann := eth.NewPooledTransactionHashesPacket70{Types: txTypes, Sizes: sizes, Hashes: hashes} + ann := eth.NewPooledTransactionHashesPacket72{Types: txTypes, Sizes: sizes, Hashes: hashes} err = conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann) if err != nil { t.Fatalf("failed to write to connection: %v", err) @@ -883,7 +883,7 @@ the transactions using a GetPooledTransactions request.`) t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest)) } return - case *eth.NewPooledTransactionHashesPacket70: + case *eth.NewPooledTransactionHashesPacket72: continue case *eth.TransactionsPacket: continue @@ -902,11 +902,11 @@ func makeSidecar(data ...byte) *types.BlobTxSidecar { for i := range blobs { blobs[i][0] = data[i] c, _ := kzg4844.BlobToCommitment(&blobs[i]) - p, _ := kzg4844.ComputeBlobProof(&blobs[i], c) + cellProofs, _ := kzg4844.ComputeCellProofs(&blobs[i]) commitments = append(commitments, c) - proofs = append(proofs, p) + proofs = append(proofs, cellProofs...) } - return types.NewBlobTxSidecar(types.BlobSidecarVersion0, blobs, commitments, proofs) + return types.NewBlobTxSidecar(types.BlobSidecarVersion1, blobs, commitments, proofs) } func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) { @@ -949,24 +949,26 @@ func (s *Suite) TestBlobViolations(t *utesting.T) { t2 = s.makeBlobTxs(2, 3, 0x2) ) for _, test := range []struct { - ann eth.NewPooledTransactionHashesPacket70 + ann eth.NewPooledTransactionHashesPacket72 resp eth.PooledTransactionsResponse }{ // Invalid tx size. { - ann: eth.NewPooledTransactionHashesPacket70{ + ann: eth.NewPooledTransactionHashesPacket72{ Types: []byte{types.BlobTxType, types.BlobTxType}, Sizes: []uint32{uint32(t1[0].Size()), uint32(t1[1].Size() + 10)}, Hashes: []common.Hash{t1[0].Hash(), t1[1].Hash()}, + Mask: *types.CustodyBitmapAll, }, resp: eth.PooledTransactionsResponse(t1), }, // Wrong tx type. { - ann: eth.NewPooledTransactionHashesPacket70{ + ann: eth.NewPooledTransactionHashesPacket72{ Types: []byte{types.DynamicFeeTxType, types.BlobTxType}, Sizes: []uint32{uint32(t2[0].Size()), uint32(t2[1].Size())}, Hashes: []common.Hash{t2[0].Hash(), t2[1].Hash()}, + Mask: *types.CustodyBitmapAll, }, resp: eth.PooledTransactionsResponse(t2), }, @@ -994,15 +996,21 @@ func (s *Suite) TestBlobViolations(t *utesting.T) { if code, _, err := conn.Read(); err != nil { t.Fatalf("expected disconnect on blob violation, got err: %v", err) } else if code != discMsg { - if code == protoOffset(ethProto)+eth.NewPooledTransactionHashesMsg { - // sometimes we'll get a blob transaction hashes announcement before the disconnect - // because blob transactions are scheduled to be fetched right away. - if code, _, err = conn.Read(); err != nil { - t.Fatalf("expected disconnect on blob violation, got err on second read: %v", err) + for { + code, _, err := conn.Read() + if err != nil { + t.Fatalf("expected disconnect on blob violation, got err: %v", err) + } + if code == discMsg { + break + } + switch code { + case protoOffset(ethProto) + eth.NewPooledTransactionHashesMsg, + protoOffset(ethProto) + eth.GetCellsMsg: + continue + default: + t.Fatalf("expected disconnect on blob violation, got msg code: %d", code) } - } - if code != discMsg { - t.Fatalf("expected disconnect on blob violation, got msg code: %d", code) } } conn.Close() @@ -1021,14 +1029,14 @@ func mangleSidecar(tx *types.Transaction) *types.Transaction { func (s *Suite) TestBlobTxWithoutSidecar(t *utesting.T) { t.Log(`This test checks that a blob transaction first advertised/transmitted without blobs will result in the sending peer being disconnected, and the full transaction should be successfully retrieved from another peer.`) - tx := s.makeBlobTxs(1, 2, 42)[0] + tx := s.makeBlobTxs(1, 2, 42)[0].WithoutBlob() badTx := tx.WithoutBlobTxSidecar() s.testBadBlobTx(t, tx, badTx) } func (s *Suite) TestBlobTxWithMismatchedSidecar(t *utesting.T) { t.Log(`This test checks that a blob transaction first advertised/transmitted without blobs, whose commitment don't correspond to the blob_versioned_hashes in the transaction, will result in the sending peer being disconnected, and the full transaction should be successfully retrieved from another peer.`) - tx := s.makeBlobTxs(1, 2, 43)[0] + tx := s.makeBlobTxs(1, 2, 43)[0].WithoutBlob() badTx := mangleSidecar(tx) s.testBadBlobTx(t, tx, badTx) } @@ -1092,10 +1100,11 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types return } - ann := eth.NewPooledTransactionHashesPacket70{ + ann := eth.NewPooledTransactionHashesPacket72{ Types: []byte{types.BlobTxType}, Sizes: []uint32{uint32(badTx.Size())}, Hashes: []common.Hash{badTx.Hash()}, + Mask: *types.CustodyBitmapAll, } if err := conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann); err != nil { @@ -1143,14 +1152,15 @@ func (s *Suite) testBadBlobTx(t *utesting.T, tx *types.Transaction, badTx *types return } - ann := eth.NewPooledTransactionHashesPacket70{ + ann := eth.NewPooledTransactionHashesPacket72{ Types: []byte{types.BlobTxType}, Sizes: []uint32{uint32(tx.Size())}, Hashes: []common.Hash{tx.Hash()}, + Mask: *types.CustodyBitmapAll, } if err := conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann); err != nil { - errc <- fmt.Errorf("sending announcement failed: %v", err) + errc <- fmt.Errorf("sending first announcement failed: %v", err) return } diff --git a/cmd/devp2p/internal/ethtest/transaction.go b/cmd/devp2p/internal/ethtest/transaction.go index 6cebfcea70..f9c2e304f3 100644 --- a/cmd/devp2p/internal/ethtest/transaction.go +++ b/cmd/devp2p/internal/ethtest/transaction.go @@ -74,7 +74,7 @@ func (s *Suite) sendTxs(t *utesting.T, txs []*types.Transaction) error { for _, tx := range txs { got[tx.Hash()] = true } - case *eth.NewPooledTransactionHashesPacket70: + case *eth.NewPooledTransactionHashesPacket72: for _, hash := range msg.Hashes { got[hash] = true } @@ -160,7 +160,7 @@ func (s *Suite) sendInvalidTxs(t *utesting.T, txs []*types.Transaction) error { return fmt.Errorf("received bad tx: %s", tx.Hash()) } } - case *eth.NewPooledTransactionHashesPacket70: + case *eth.NewPooledTransactionHashesPacket72: for _, hash := range msg.Hashes { if _, ok := invalids[hash]; ok { return fmt.Errorf("received bad tx: %s", hash) diff --git a/eth/handler_eth.go b/eth/handler_eth.go index 077d5de389..37573c3cbd 100644 --- a/eth/handler_eth.go +++ b/eth/handler_eth.go @@ -59,7 +59,7 @@ func (h *ethHandler) AcceptTxs() bool { func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error { // Consume any broadcasts and announces, forwarding the rest to the downloader switch packet := packet.(type) { - case *eth.NewPooledTransactionHashesPacket71: + case *eth.NewPooledTransactionHashesPacket72: hashes, err := h.txFetcher.Notify(peer.ID(), packet.Types, packet.Sizes, packet.Hashes) if err != nil { return err @@ -69,7 +69,7 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error { } return nil - case *eth.NewPooledTransactionHashesPacket70: + case *eth.NewPooledTransactionHashesPacket71: _, err := h.txFetcher.Notify(peer.ID(), packet.Types, packet.Sizes, packet.Hashes) return err @@ -113,17 +113,11 @@ func handleTransactions(peer *eth.Peer, list []*types.Transaction, directBroadca // If we receive any blob transactions missing sidecars, or with // sidecars that don't correspond to the versioned hashes reported // in the header, disconnect from the sending peer. - if peer.Version() >= eth.ETH72 { - if tx.BlobTxSidecar() != nil && len(tx.BlobTxSidecar().Blobs) != 0 { - return fmt.Errorf("not allowed to respond with full-blob transaction under eth72") - } - } else { - if tx.BlobTxSidecar() == nil { - return errors.New("received sidecar-less blob transaction") - } - if err := tx.BlobTxSidecar().ValidateBlobCommitmentHashes(tx.BlobHashes()); err != nil { - return err - } + if tx.BlobTxSidecar() == nil { + return errors.New("received sidecar-less blob transaction") + } + if err := tx.BlobTxSidecar().ValidateBlobCommitmentHashes(tx.BlobHashes()); err != nil { + return err } } } diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 3f219ded56..9d93de37e5 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -51,7 +51,7 @@ func (h *testEthHandler) PeerInfo(enode.ID) interface{} { panic("not used func (h *testEthHandler) Handle(peer *eth.Peer, packet eth.Packet) error { switch packet := packet.(type) { - case *eth.NewPooledTransactionHashesPacket70: + case *eth.NewPooledTransactionHashesPacket71: h.txAnnounces.Send(packet.Hashes) return nil diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index d349449044..0af04f87a0 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -483,7 +483,7 @@ func handleNewPooledTransactionHashes(backend Backend, msg Decoder, peer *Peer) if !backend.AcceptTxs() { return nil } - ann := new(NewPooledTransactionHashesPacket70) + ann := new(NewPooledTransactionHashesPacket71) if err := msg.Decode(ann); err != nil { return err } @@ -503,7 +503,7 @@ func handleNewPooledTransactionHashes71(backend Backend, msg Decoder, peer *Peer if !backend.AcceptTxs() { return nil } - ann := new(NewPooledTransactionHashesPacket71) + ann := new(NewPooledTransactionHashesPacket72) if err := msg.Decode(ann); err != nil { return err } diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index b63b43459d..183bf324c2 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -173,9 +173,9 @@ func (p *Peer) sendPooledTransactionHashes(hashes []common.Hash, types []byte, s // Mark all the transactions as known, but ensure we don't overflow our limits p.knownTxs.Add(hashes...) if p.version >= ETH72 { - return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket71{Types: types, Sizes: sizes, Hashes: hashes, Mask: cells}) + return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket72{Types: types, Sizes: sizes, Hashes: hashes, Mask: cells}) } - return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket70{Types: types, Sizes: sizes, Hashes: hashes}) + return p2p.Send(p.rw, NewPooledTransactionHashesMsg, NewPooledTransactionHashesPacket71{Types: types, Sizes: sizes, Hashes: hashes}) } // AsyncSendPooledTransactionHashes queues a list of transactions hashes to eventually diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 9ef1928b8f..7fd590efd1 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -234,16 +234,16 @@ type ReceiptsPacket struct { // ReceiptsRLPResponse is used for receipts, when we already have it encoded type ReceiptsRLPResponse []rlp.RawValue -// NewPooledTransactionHashesPacket70 represents a transaction announcement packet on eth/69. -type NewPooledTransactionHashesPacket70 struct { +// NewPooledTransactionHashesPacket71 represents a transaction announcement packet on eth/69. +type NewPooledTransactionHashesPacket71 struct { Types []byte Sizes []uint32 Hashes []common.Hash } -// NewPooledTransactionHashesPacket71 represents a transaction announcement packet on ETH/72 +// NewPooledTransactionHashesPacket72 represents a transaction announcement packet on ETH/72 // with an additional custody bitmap field for cell-based blob data availability. -type NewPooledTransactionHashesPacket71 struct { +type NewPooledTransactionHashesPacket72 struct { Types []byte Sizes []uint32 Hashes []common.Hash @@ -329,12 +329,12 @@ func (*GetBlockBodiesRequest) Kind() byte { return GetBlockBodiesMsg } func (*BlockBodiesResponse) Name() string { return "BlockBodies" } func (*BlockBodiesResponse) Kind() byte { return BlockBodiesMsg } -func (*NewPooledTransactionHashesPacket70) Name() string { return "NewPooledTransactionHashes" } -func (*NewPooledTransactionHashesPacket70) Kind() byte { return NewPooledTransactionHashesMsg } - func (*NewPooledTransactionHashesPacket71) Name() string { return "NewPooledTransactionHashes" } func (*NewPooledTransactionHashesPacket71) Kind() byte { return NewPooledTransactionHashesMsg } +func (*NewPooledTransactionHashesPacket72) Name() string { return "NewPooledTransactionHashes" } +func (*NewPooledTransactionHashesPacket72) Kind() byte { return NewPooledTransactionHashesMsg } + func (*GetPooledTransactionsRequest) Name() string { return "GetPooledTransactions" } func (*GetPooledTransactionsRequest) Kind() byte { return GetPooledTransactionsMsg }