eth/protocols/eth/protocol_pow.go — Version Comparison
|
v1.17.3 |
v1.17.4 |
| Branch |
etc/v1.17.3-full-node |
etc/v1.17.4-full-node |
| Delta |
+123 -0 |
+196 -0 |
Diff between branches
diff --git a/eth/protocols/eth/protocol_pow.go b/eth/protocols/eth/protocol_pow.go
index 5597790d8..ac0e0d5c0 100644
--- a/eth/protocols/eth/protocol_pow.go
+++ b/eth/protocols/eth/protocol_pow.go
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
)
const ETH68 = 68
@@ -88,15 +89,65 @@ func (p *NewBlockHashesPacket) Unpack() ([]common.Hash, []uint64) {
func (*NewBlockHashesPacket) Name() string { return "NewBlockHashes" }
func (*NewBlockHashesPacket) Kind() byte { return NewBlockHashesMsg }
-// NewBlockPacket is the network packet for the block propagation message.
+// maxBlockAnnouncements bounds the hashes a single announcement message may
+// carry. Past maxKnownBlocks the message defeats itself: every hash is fed into
+// the peer's known-blocks cache, which evicts at that size, so the tail of an
+// oversized message pushes out its own head. It also sits well above the block
+// fetcher's hashLimit, the number of announcements from one peer it tracks at a
+// time, in the same arrangement upstream uses for transactions, where the
+// protocol-level maxTransactionAnnouncements sits above the fetcher-level
+// maxTxAnnounces. For scale, our own side sends one hash per message.
+const maxBlockAnnouncements = maxKnownBlocks
+
+// maxBlockTransactions bounds the number of transactions a propagated block may
+// carry before it is rejected without being decoded. A block cannot hold more
+// transactions than its gas limit admits at the 21000 gas floor of a plain
+// transfer, which puts ETC's current 8M limit at a few hundred; this is set far
+// above that so it keeps holding for any plausible future gas limit, and equals
+// the figure upstream uses for the analogous cap on transaction broadcasts
+// (maxTransactionAnnouncements). Computing it from the announced gas limit
+// instead would be self-defeating: on this message that field is attacker
+// controlled.
+const maxBlockTransactions = 5000
+
+// maxBlockUncles is the maximum number of uncles a block can contain, per the
+// ethash/etchash consensus rules. Blocks announcing more cannot be valid.
+const maxBlockUncles = 2
+
+// NewBlockPacket is the network packet for the block propagation message. It is
+// what the sending side encodes and what the backend consumes; inbound messages
+// are decoded into rawNewBlockPacket first and assembled into this afterwards.
type NewBlockPacket struct {
Block *types.Block
TD *big.Int
}
+func (*NewBlockPacket) Name() string { return "NewBlock" }
+func (*NewBlockPacket) Kind() byte { return NewBlockMsg }
+
+// rawNewBlockPacket is the receiving side's view of NewBlockMsg, holding the
+// block body encoded so that its item counts can be checked, and the body
+// verified against the header, before any of it is materialized. A broadcast
+// carries no request id, so there is nothing to match it against: the counts
+// are all that stands between the message size limit and the heap.
+type rawNewBlockPacket struct {
+ Block rawBlock
+ TD *big.Int
+}
+
+// rawBlock mirrors the block encoding, [header, txs, uncles], keeping the two
+// lists encoded in the manner of BlockBody. Withdrawals are deliberately absent:
+// a PoW block carries none, so a message that includes them is rejected as
+// having too many elements.
+type rawBlock struct {
+ Header *types.Header
+ Transactions rlp.RawList[*types.Transaction]
+ Uncles rlp.RawList[*types.Header]
+}
+
// sanityCheck verifies that the values are reasonable, as a DoS protection
-func (request *NewBlockPacket) sanityCheck() error {
- if err := request.Block.SanityCheck(); err != nil {
+func (request *rawNewBlockPacket) sanityCheck() error {
+ if err := request.Block.Header.SanityCheck(); err != nil {
return err
}
//TD at mainnet block #7753254 is 76 bits. If it becomes 100 million times
@@ -107,8 +158,30 @@ func (request *NewBlockPacket) sanityCheck() error {
return nil
}
-func (*NewBlockPacket) Name() string { return "NewBlock" }
-func (*NewBlockPacket) Kind() byte { return NewBlockMsg }
+// body returns the encoded body parts in the shape the shared hashing helpers
+// consume.
+func (b *rawBlock) body() BlockBody {
+ return BlockBody{Transactions: b.Transactions, Uncles: b.Uncles}
+}
+
+// GetReceiptsPacket represents a block receipts query with request ID wrapping.
+type GetReceiptsPacket struct {
+ RequestId uint64
+ GetReceiptsRequest
+}
+
+// ReceiptsPacket68 is the network packet for block receipts distribution with
+// request ID wrapping.
+type ReceiptsPacket68 struct {
+ RequestId uint64
+ List rlp.RawList[*ReceiptList68]
+}
+
+// ReceiptsRLPPacket is ReceiptsRLPResponse with request ID wrapping.
+type ReceiptsRLPPacket struct {
+ RequestId uint64
+ ReceiptsRLPResponse
+}
// Unpack retrieves the transactions and uncles from each block body in the response.
// This is needed for PoW block fetcher which processes bodies differently.
← Back to Version Comparison