drop buffer

This commit is contained in:
healthykim 2026-02-17 14:30:18 -07:00 committed by Felix Lange
parent 5374a8e53d
commit b2ac1c8d8c
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) { func (dlp *downloadTesterPeer) RequestReceipts(hashes []common.Hash, sink chan *eth.Response) (*eth.Request, error) {
blobs := eth.ServiceGetReceiptsQuery(dlp.chain, hashes) blobs := eth.ServiceGetReceiptsQuery(dlp.chain, hashes)
receipts := make([]*eth.ReceiptList, len(blobs)) receipts := make([]types.Receipts, len(blobs))
for i, blob := range blobs { for i, blob := range blobs {
rlp.DecodeBytes(blob, &receipts[i]) rlp.DecodeBytes(blob, &receipts[i])
} }
hasher := trie.NewStackTrie(nil) hasher := trie.NewStackTrie(nil)
hashes = make([]common.Hash, len(receipts)) hashes = make([]common.Hash, len(receipts))
for i, receipt := range receipts { for i, receipt := range receipts {
hashes[i] = types.DeriveSha(receipt.Derivable(), hasher) hashes[i] = types.DeriveSha(receipt, hasher)
} }
req := &eth.Request{ req := &eth.Request{
Peer: dlp.id, Peer: dlp.id,
} }
var resp eth.ReceiptsRLPResponse resp := eth.ReceiptsRLPResponse(types.EncodeBlockReceiptLists(receipts))
for i := range receipts {
rs, _ := receipts[i].EncodeForStorage()
resp = append(resp, rs)
}
res := &eth.Response{ res := &eth.Response{
Req: req, Req: req,
Res: &resp, 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 { func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
// A batch of receipts arrived to one of our previous requests // A batch of receipts arrived to one of our previous requests
res := new(ReceiptsPacket) res := new(ReceiptsPacket)
@ -447,22 +457,19 @@ func handleReceipts(backend Backend, msg Decoder, peer *Peer) error {
return fmt.Errorf("Receipts: %w", err) 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() receiptLists, err := res.List.Items()
if err != nil { if err != nil {
return fmt.Errorf("Receipts: %w", err) 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{} { metadata := func() interface{} {
hasher := trie.NewStackTrie(nil) hasher := trie.NewStackTrie(nil)
hashes := make([]common.Hash, len(receiptLists)) hashes := make([]common.Hash, len(receiptLists))
for i := range 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 return hashes
} }

View file

@ -47,18 +47,17 @@ func newReceipt(tr *types.Receipt) Receipt {
} }
// encodeForHash encodes a receipt for the block receiptsRoot derivation. // 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. // For typed receipts, add the tx type.
if r.TxType != 0 { if r.TxType != 0 {
out.WriteByte(r.TxType) out.WriteByte(r.TxType)
} }
// Encode list = [postStateOrStatus, gasUsed, bloom, logs]. // Encode list = [postStateOrStatus, gasUsed, bloom, logs].
w := &buf.enc w := rlp.NewEncoderBuffer(out)
w.Reset(out)
l := w.List() l := w.List()
w.WriteBytes(r.PostStateOrStatus) w.WriteBytes(r.PostStateOrStatus)
w.WriteUint64(r.GasUsed) w.WriteUint64(r.GasUsed)
bloom := r.bloom(&buf.bloom) bloom := r.bloom(bloomBuf)
w.WriteBytes(bloom[:]) w.WriteBytes(bloom[:])
w.Write(r.Logs) w.Write(r.Logs)
w.ListEnd(l) w.ListEnd(l)
@ -91,26 +90,19 @@ func (r *Receipt) bloom(buffer *[6]byte) types.Bloom {
return b return b
} }
type receiptListBuffers struct { // ReceiptList is the block receipt list as downloaded by eth/69.
enc rlp.EncoderBuffer type ReceiptList struct {
bloom [6]byte items rlp.RawList[Receipt]
} }
func initBuffers(buf **receiptListBuffers) { // EncodeForStorage encodes a list of receipts for the database.
if *buf == nil {
*buf = new(receiptListBuffers)
}
}
// encodeForStorage encodes a list of receipts for the database.
// It only strips the first element (TxType) from each receipt's // It only strips the first element (TxType) from each receipt's
// raw RLP without the actual decoding and re-encoding. // 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 var out bytes.Buffer
w := &buf.enc w := rlp.NewEncoderBuffer(&out)
w.Reset(&out)
outer := w.List() outer := w.List()
it := rs.ContentIterator() it := rl.items.ContentIterator()
for it.Next() { for it.Next() {
content, _, err := rlp.SplitList(it.Value()) content, _, err := rlp.SplitList(it.Value())
if err != nil { if err != nil {
@ -132,13 +124,6 @@ func (buf *receiptListBuffers) encodeForStorage(rs rlp.RawList[Receipt]) (rlp.Ra
return out.Bytes(), nil 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. // NewReceiptList creates a receipt list.
// This is slow, and exists for testing purposes. // This is slow, and exists for testing purposes.
func NewReceiptList(trs []*types.Receipt) *ReceiptList { func NewReceiptList(trs []*types.Receipt) *ReceiptList {
@ -151,28 +136,6 @@ func NewReceiptList(trs []*types.Receipt) *ReceiptList {
return rl 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. // DecodeRLP decodes a list receipts from the network format.
func (rl *ReceiptList) DecodeRLP(s *rlp.Stream) error { func (rl *ReceiptList) DecodeRLP(s *rlp.Stream) error {
return rl.items.DecodeRLP(s) return rl.items.DecodeRLP(s)

View file

@ -128,7 +128,10 @@ func TestReceiptList(t *testing.T) {
} }
// compute root hash from ReceiptList and compare. // 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 { if responseHash != test.root {
t.Fatalf("test[%d]: wrong root hash from ReceiptList\nhave: %v\nwant: %v", i, responseHash, test.root) t.Fatalf("test[%d]: wrong root hash from ReceiptList\nhave: %v\nwant: %v", i, responseHash, test.root)
} }