drop buffer

This commit is contained in:
healthykim 2026-02-17 14:30:18 -07:00
parent 7f0935504d
commit 2fa04e10f7
4 changed files with 31 additions and 63 deletions

View file

@ -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 := &eth.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 := &eth.Response{
Req: req,
Res: &resp,

View file

@ -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
}

View file

@ -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)

View file

@ -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)
}