eth/protocols/eth: unpack receipts correctly

pull/29158/head
Marius van der Wijden 2 months ago
parent 0a623896b1
commit 3ed070bc36
  1. 33
      eth/protocols/eth/handler_test.go
  2. 22
      eth/protocols/eth/handlers.go
  3. 10
      eth/protocols/eth/protocol.go
  4. 80
      eth/protocols/eth/receipt.go

@ -18,7 +18,6 @@ package eth
import (
"bytes"
"io"
"math"
"math/big"
"math/rand"
@ -578,38 +577,6 @@ func FuzzEthProtocolHandlers(f *testing.F) {
})
}
type receiptForNetwork struct {
Type byte
Status uint64
GasUsed uint64
Logs []*types.Log
}
func (r *receiptForNetwork) EncodeRLP(_w io.Writer) error {
data := &types.ReceiptForStorage{Status: r.Status, CumulativeGasUsed: r.GasUsed, Logs: r.Logs}
if r.Type == types.LegacyTxType {
return rlp.Encode(_w, data)
}
w := rlp.NewEncoderBuffer(_w)
outerList := w.List()
w.Write([]byte{r.Type})
if r.Status == types.ReceiptStatusSuccessful {
w.Write([]byte{0x01})
} else {
w.Write([]byte{0x00})
}
w.WriteUint64(r.GasUsed)
logList := w.List()
for _, log := range r.Logs {
if err := log.EncodeRLP(w); err != nil {
return err
}
}
w.ListEnd(logList)
w.ListEnd(outerList)
return w.Flush()
}
func TestTransformReceipts(t *testing.T) {
tests := []struct {
input []types.ReceiptForStorage

@ -429,28 +429,36 @@ func handleReceipts68(backend Backend, msg Decoder, peer *Peer) error {
func handleReceipts69(backend Backend, msg Decoder, peer *Peer) error {
// A batch of receipts arrived to one of our previous requests
res := new(ReceiptsPacket)
res := new(ReceiptsPacket69)
if err := msg.Decode(res); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
}
var response ReceiptsResponse
// calculate the bloom filter before dispatching
for _, receipts := range res.ReceiptsResponse {
for _, receipts := range res.ReceiptsResponse69 {
var rec []*types.Receipt
for _, receipt := range receipts {
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
receipt.Bloom = types.CreateBloom(types.Receipts{(*types.Receipt)(receipt)})
rec = append(rec, (*types.Receipt)(receipt))
}
response = append(response, rec)
}
metadata := func() interface{} {
hasher := trie.NewStackTrie(nil)
hashes := make([]common.Hash, len(res.ReceiptsResponse))
for i, receipt := range res.ReceiptsResponse {
hashes[i] = types.DeriveSha(types.Receipts(receipt), hasher)
hashes := make([]common.Hash, len(response))
for i, receipts := range response {
var r []*types.Receipt
for _, receipt := range receipts {
r = append(r, (*types.Receipt)(receipt))
}
hashes[i] = types.DeriveSha(types.Receipts(r), hasher)
}
return hashes
}
return peer.dispatchResponse(&Response{
id: res.RequestId,
code: ReceiptsMsg,
Res: &res.ReceiptsResponse,
Res: &response,
}, metadata)
}

@ -260,6 +260,16 @@ type ReceiptsPacket struct {
ReceiptsResponse
}
// ReceiptsResponse is the network packet for block receipts distribution.
type ReceiptsResponse69 [][]*receiptForNetwork
// ReceiptsPacket is the network packet for block receipts distribution with
// request ID wrapping.
type ReceiptsPacket69 struct {
RequestId uint64
ReceiptsResponse69
}
// ReceiptsRLPResponse is used for receipts, when we already have it encoded
type ReceiptsRLPResponse []rlp.RawValue

@ -0,0 +1,80 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package eth
import (
"errors"
"io"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
)
type receiptForNetwork types.Receipt
func (r *receiptForNetwork) DecodeRLP(s *rlp.Stream) error {
kind, size, err := s.Kind()
if err != nil {
return err
}
if kind != rlp.List {
return errors.New("invalid receipt")
}
if size == 4 {
var rec = new(struct {
Type byte
Status uint64
GasUsed uint64
Logs []*types.Log
})
if err := s.Decode(rec); err != nil {
return err
}
r.Type = rec.Type
r.Status = rec.Status
r.GasUsed = rec.GasUsed
r.Logs = rec.Logs
} else {
s.Decode(&r)
}
return nil
}
func (r *receiptForNetwork) EncodeRLP(_w io.Writer) error {
data := &types.ReceiptForStorage{Status: r.Status, CumulativeGasUsed: r.GasUsed, Logs: r.Logs}
if r.Type == types.LegacyTxType {
return rlp.Encode(_w, data)
}
w := rlp.NewEncoderBuffer(_w)
outerList := w.List()
w.Write([]byte{r.Type})
if r.Status == types.ReceiptStatusSuccessful {
w.Write([]byte{0x01})
} else {
w.Write([]byte{0x00})
}
w.WriteUint64(r.GasUsed)
logList := w.List()
for _, log := range r.Logs {
if err := log.EncodeRLP(w); err != nil {
return err
}
}
w.ListEnd(logList)
w.ListEnd(outerList)
return w.Flush()
}
Loading…
Cancel
Save