diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index d8d5cda567..c05421c408 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -263,24 +263,19 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) { blobs := eth.ServiceGetReceiptsQuery(dlp.chain, hashes) - receipts := make([]*eth.ReceiptList, len(blobs)) + receipts := make([]types.Receipts, len(blobs)) for i, blob := range blobs { rlp.DecodeBytes(blob, &receipts[i]) } hasher := trie.NewStackTrie(nil) hashes = make([]common.Hash, len(receipts)) for i, receipt := range receipts { - hashes[i] = types.DeriveSha(receipt.Derivable(), hasher) + hashes[i] = types.DeriveSha(receipt, hasher) } req := ð.Request{ Peer: dlp.id, } - var resp eth.ReceiptsRLPResponse - for i := range receipts { - rs, _ := receipts[i].EncodeForStorage() - resp = append(resp, rs) - } - + resp := eth.ReceiptsRLPResponse(types.EncodeBlockReceiptLists(receipts)) res := ð.Response{ Req: req, Res: &resp, diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index 710db9af94..61da6ba0ae 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -435,6 +435,16 @@ func writeTxForHash(tx []byte, buf *bytes.Buffer) { } } +// writeReceiptForHash returns a write function that encode receipts for hash derivation. +func writeReceiptForHash(bloomBuf *[6]byte) func([]byte, *bytes.Buffer) { + return func(data []byte, outbuf *bytes.Buffer) { + var r Receipt + if rlp.DecodeBytes(data, &r) == nil { + r.encodeForHash(bloomBuf, outbuf) + } + } +} + func handleReceipts(backend Backend, msg Decoder, peer *Peer) error { // A batch of receipts arrived to one of our previous requests res := new(ReceiptsPacket) @@ -447,22 +457,19 @@ func handleReceipts(backend Backend, msg Decoder, peer *Peer) error { return fmt.Errorf("Receipts: %w", err) } - // Assign temporary hashing buffer to each list item, the same buffer is shared - // between all receipt list instances. receiptLists, err := res.List.Items() if err != nil { return fmt.Errorf("Receipts: %w", err) } - buffers := new(receiptListBuffers) - for i := range receiptLists { - receiptLists[i].setBuffers(buffers) - } + var bloomBuf [6]byte + writeReceipt := writeReceiptForHash(&bloomBuf) metadata := func() interface{} { hasher := trie.NewStackTrie(nil) hashes := make([]common.Hash, len(receiptLists)) for i := range receiptLists { - hashes[i] = types.DeriveSha(receiptLists[i].Derivable(), hasher) + receipts := newDerivableRawList(&receiptLists[i].items, writeReceipt) + hashes[i] = types.DeriveSha(receipts, hasher) } return hashes } diff --git a/eth/protocols/eth/receipt.go b/eth/protocols/eth/receipt.go index 9ea2172ebe..6ea793b99f 100644 --- a/eth/protocols/eth/receipt.go +++ b/eth/protocols/eth/receipt.go @@ -47,18 +47,17 @@ func newReceipt(tr *types.Receipt) Receipt { } // encodeForHash encodes a receipt for the block receiptsRoot derivation. -func (r *Receipt) encodeForHash(buf *receiptListBuffers, out *bytes.Buffer) { +func (r *Receipt) encodeForHash(bloomBuf *[6]byte, out *bytes.Buffer) { // For typed receipts, add the tx type. if r.TxType != 0 { out.WriteByte(r.TxType) } // Encode list = [postStateOrStatus, gasUsed, bloom, logs]. - w := &buf.enc - w.Reset(out) + w := rlp.NewEncoderBuffer(out) l := w.List() w.WriteBytes(r.PostStateOrStatus) w.WriteUint64(r.GasUsed) - bloom := r.bloom(&buf.bloom) + bloom := r.bloom(bloomBuf) w.WriteBytes(bloom[:]) w.Write(r.Logs) w.ListEnd(l) @@ -91,26 +90,19 @@ func (r *Receipt) bloom(buffer *[6]byte) types.Bloom { return b } -type receiptListBuffers struct { - enc rlp.EncoderBuffer - bloom [6]byte +// ReceiptList is the block receipt list as downloaded by eth/69. +type ReceiptList struct { + items rlp.RawList[Receipt] } -func initBuffers(buf **receiptListBuffers) { - if *buf == nil { - *buf = new(receiptListBuffers) - } -} - -// encodeForStorage encodes a list of receipts for the database. +// EncodeForStorage encodes a list of receipts for the database. // It only strips the first element (TxType) from each receipt's // raw RLP without the actual decoding and re-encoding. -func (buf *receiptListBuffers) encodeForStorage(rs rlp.RawList[Receipt]) (rlp.RawValue, error) { +func (rl *ReceiptList) EncodeForStorage() (rlp.RawValue, error) { var out bytes.Buffer - w := &buf.enc - w.Reset(&out) + w := rlp.NewEncoderBuffer(&out) outer := w.List() - it := rs.ContentIterator() + it := rl.items.ContentIterator() for it.Next() { content, _, err := rlp.SplitList(it.Value()) if err != nil { @@ -132,13 +124,6 @@ func (buf *receiptListBuffers) encodeForStorage(rs rlp.RawList[Receipt]) (rlp.Ra return out.Bytes(), nil } -// ReceiptList is the block receipt list as downloaded by eth/69. -// This implements types.DerivableList for validation purposes. -type ReceiptList struct { - buf *receiptListBuffers - items rlp.RawList[Receipt] -} - // NewReceiptList creates a receipt list. // This is slow, and exists for testing purposes. func NewReceiptList(trs []*types.Receipt) *ReceiptList { @@ -151,28 +136,6 @@ func NewReceiptList(trs []*types.Receipt) *ReceiptList { return rl } -// setBuffers assigns buffers to the receipt list -func (rl *ReceiptList) setBuffers(buf *receiptListBuffers) { - rl.buf = buf -} - -// EncodeForStorage encodes the receipts for storage into the database. -func (rl *ReceiptList) EncodeForStorage() (rlp.RawValue, error) { - initBuffers(&rl.buf) - return rl.buf.encodeForStorage(rl.items) -} - -// Derivable turns the receipts into a list that can derive the root hash. -func (rl *ReceiptList) Derivable() types.DerivableList { - initBuffers(&rl.buf) - return newDerivableRawList(&rl.items, func(data []byte, outbuf *bytes.Buffer) { - var r Receipt - if rlp.DecodeBytes(data, &r) == nil { - r.encodeForHash(rl.buf, outbuf) - } - }) -} - // DecodeRLP decodes a list receipts from the network format. func (rl *ReceiptList) DecodeRLP(s *rlp.Stream) error { return rl.items.DecodeRLP(s) diff --git a/eth/protocols/eth/receipt_test.go b/eth/protocols/eth/receipt_test.go index 92d46f1a2b..c7be70eed3 100644 --- a/eth/protocols/eth/receipt_test.go +++ b/eth/protocols/eth/receipt_test.go @@ -128,7 +128,10 @@ func TestReceiptList(t *testing.T) { } // compute root hash from ReceiptList and compare. - responseHash := types.DeriveSha(rl.Derivable(), trie.NewStackTrie(nil)) + var bloomBuf [6]byte + writeReceipt := writeReceiptForHash(&bloomBuf) + receipts := newDerivableRawList(&rl.items, writeReceipt) + responseHash := types.DeriveSha(receipts, trie.NewStackTrie(nil)) if responseHash != test.root { t.Fatalf("test[%d]: wrong root hash from ReceiptList\nhave: %v\nwant: %v", i, responseHash, test.root) }