mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-13 02:11:34 +00:00
eth/protocols/eth: remove trimReceiptsRLP and simplify handler
This commit is contained in:
parent
130470832f
commit
682ed6c64e
3 changed files with 61 additions and 81 deletions
|
|
@ -269,33 +269,28 @@ func handleGetReceipts70(backend Backend, msg Decoder, peer *Peer) error {
|
|||
// It does not send the bloom filters for the receipts. It is exposed
|
||||
// to allow external packages to test protocol behavior.
|
||||
func ServiceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest) rlp.RawList[*ReceiptList] {
|
||||
// Gather state data until the fetch or network limits is reached
|
||||
var (
|
||||
bytes int
|
||||
receipts rlp.RawList[*ReceiptList]
|
||||
)
|
||||
for lookups, hash := range query {
|
||||
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe ||
|
||||
lookups >= 2*maxReceiptsServe {
|
||||
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe || lookups >= 2*maxReceiptsServe {
|
||||
break
|
||||
}
|
||||
|
||||
// Retrieve the requested block's receipts
|
||||
results := chain.GetReceiptsRLP(hash)
|
||||
if results == nil {
|
||||
if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
body := chain.GetBodyRLP(hash)
|
||||
if body == nil {
|
||||
continue
|
||||
}
|
||||
var err error
|
||||
results, err = blockReceiptsToNetwork(results, body)
|
||||
if err != nil {
|
||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||
continue
|
||||
}
|
||||
continue // Can't retrieve the receipts, so we just skip this block.
|
||||
}
|
||||
body := chain.GetBodyRLP(hash)
|
||||
if body == nil {
|
||||
continue // The block body is missing, we also have to skip.
|
||||
}
|
||||
results, _, err := blockReceiptsToNetwork(results, body, receiptQueryParams{})
|
||||
if err != nil {
|
||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||
continue
|
||||
}
|
||||
receipts.AppendRaw(results)
|
||||
bytes += len(results)
|
||||
|
|
@ -309,9 +304,8 @@ func ServiceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest)
|
|||
// are omitted from the first block receipt list.
|
||||
func serviceGetReceiptsQuery70(chain *core.BlockChain, query GetReceiptsRequest, firstBlockReceiptIndex uint64) (rlp.RawList[*ReceiptList], bool) {
|
||||
var (
|
||||
bytes int
|
||||
receipts rlp.RawList[*ReceiptList]
|
||||
lastBlockIncomplete bool
|
||||
bytes int
|
||||
receipts rlp.RawList[*ReceiptList]
|
||||
)
|
||||
for i, hash := range query {
|
||||
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe {
|
||||
|
|
@ -319,65 +313,28 @@ func serviceGetReceiptsQuery70(chain *core.BlockChain, query GetReceiptsRequest,
|
|||
}
|
||||
results := chain.GetReceiptsRLP(hash)
|
||||
if results == nil {
|
||||
if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
body := chain.GetBodyRLP(hash)
|
||||
if body == nil {
|
||||
continue
|
||||
}
|
||||
var err error
|
||||
results, err = blockReceiptsToNetwork(results, body)
|
||||
if err != nil {
|
||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||
continue
|
||||
}
|
||||
continue // Can't retrieve the receipts, so we just skip this block.
|
||||
}
|
||||
|
||||
if firstBlockReceiptIndex > 0 && i == 0 {
|
||||
results, lastBlockIncomplete = trimReceiptsRLP(results, int(firstBlockReceiptIndex), maxPacketSize)
|
||||
} else if bytes+len(results) > maxPacketSize {
|
||||
results, lastBlockIncomplete = trimReceiptsRLP(results, 0, maxPacketSize-bytes)
|
||||
body := chain.GetBodyRLP(hash)
|
||||
if body == nil {
|
||||
continue // The block body is missing, we also have to skip.
|
||||
}
|
||||
|
||||
receipts.AppendRaw(results)
|
||||
bytes += len(results)
|
||||
}
|
||||
|
||||
return receipts, lastBlockIncomplete
|
||||
}
|
||||
|
||||
// trimReceiptsRLP trims raw value from `from` index until it exceeds limit
|
||||
func trimReceiptsRLP(receiptsRLP rlp.RawValue, from int, limit int) (rlp.RawValue, bool) {
|
||||
var (
|
||||
out bytes.Buffer
|
||||
buffer = rlp.NewEncoderBuffer(&out)
|
||||
iter, _ = rlp.NewListIterator(receiptsRLP)
|
||||
index int
|
||||
bytes int
|
||||
overflow bool
|
||||
)
|
||||
|
||||
list := buffer.List()
|
||||
for iter.Next() {
|
||||
if index < from {
|
||||
index++
|
||||
q := receiptQueryParams{sizeLimit: uint64(maxPacketSize - bytes)}
|
||||
if i == 0 {
|
||||
q.firstIndex = firstBlockReceiptIndex
|
||||
}
|
||||
results, incomplete, err := blockReceiptsToNetwork(results, body, q)
|
||||
if err != nil {
|
||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||
continue
|
||||
}
|
||||
receipt := iter.Value()
|
||||
if bytes+len(receipt) > limit {
|
||||
overflow = true
|
||||
break
|
||||
receipts.AppendRaw(results)
|
||||
bytes += len(results)
|
||||
if incomplete {
|
||||
return receipts, true
|
||||
}
|
||||
buffer.Write(receipt)
|
||||
bytes += len(receipt)
|
||||
index++
|
||||
}
|
||||
buffer.ListEnd(list)
|
||||
buffer.Flush()
|
||||
|
||||
return out.Bytes(), overflow
|
||||
return receipts, false
|
||||
}
|
||||
|
||||
func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
|
||||
|
|
|
|||
|
|
@ -240,12 +240,17 @@ func (rl *ReceiptList) LogsSize() (uint64, error) {
|
|||
return size, nil
|
||||
}
|
||||
|
||||
// blockReceiptsToNetwork takes a slice of rlp-encoded receipts, and transactions,
|
||||
// and re-encodes them for the network protocol.
|
||||
func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, error) {
|
||||
type receiptQueryParams struct {
|
||||
firstIndex uint64
|
||||
sizeLimit uint64
|
||||
}
|
||||
|
||||
// blockReceiptsToNetwork takes a slice of rlp-encoded receipts (in the 'storage' encoding),
|
||||
// and an encoded block body, and re-encodes the receipts for the network protocol.
|
||||
func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue, q receiptQueryParams) (output []byte, incomplete bool, err error) {
|
||||
txTypesIter, err := txTypesInBody(blockBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid block body: %v", err)
|
||||
return nil, false, fmt.Errorf("invalid block body: %v", err)
|
||||
}
|
||||
nextTxType, stopTxTypes := iter.Pull(txTypesIter)
|
||||
defer stopTxTypes()
|
||||
|
|
@ -256,9 +261,24 @@ func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, erro
|
|||
it, _ = rlp.NewListIterator(blockReceipts)
|
||||
)
|
||||
outer := enc.List()
|
||||
for i := 0; it.Next(); i++ {
|
||||
txType, _ := nextTxType()
|
||||
for i := 0; it.Next() && !incomplete; i++ {
|
||||
txType, end := nextTxType()
|
||||
if end {
|
||||
return nil, false, fmt.Errorf("block has less txs than receipts (%d)", i)
|
||||
}
|
||||
// Skip receipts before the requested index.
|
||||
if uint64(i) < q.firstIndex {
|
||||
continue
|
||||
}
|
||||
content, _, _ := rlp.SplitList(it.Value())
|
||||
// Stop appending receipts when they would go over the size limit.
|
||||
// Note we rely on the assumption that the txType is encoded as a single byte,
|
||||
// which is always true because EIP-2718 does not allow tx types > 0x7f.
|
||||
size := rlp.ListSize(1 + uint64(len(content)))
|
||||
if q.sizeLimit > 0 && (uint64(enc.Size())+size) > q.sizeLimit {
|
||||
break
|
||||
}
|
||||
|
||||
receiptList := enc.List()
|
||||
enc.WriteUint64(uint64(txType))
|
||||
enc.Write(content)
|
||||
|
|
@ -266,7 +286,7 @@ func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, erro
|
|||
}
|
||||
enc.ListEnd(outer)
|
||||
enc.Flush()
|
||||
return out.Bytes(), nil
|
||||
return out.Bytes(), incomplete, nil
|
||||
}
|
||||
|
||||
// txTypesInBody parses the transactions list of an encoded block body, returning just the types.
|
||||
|
|
|
|||
|
|
@ -105,10 +105,13 @@ func TestReceiptList(t *testing.T) {
|
|||
canonBody, _ := rlp.EncodeToBytes(blockBody)
|
||||
|
||||
// convert from storage encoding to network encoding
|
||||
network, err := blockReceiptsToNetwork(canonDB, canonBody)
|
||||
network, incomplete, err := blockReceiptsToNetwork(canonDB, canonBody, receiptQueryParams{})
|
||||
if err != nil {
|
||||
t.Fatalf("test[%d]: blockReceiptsToNetwork error: %v", i, err)
|
||||
}
|
||||
if incomplete {
|
||||
t.Fatalf("test[%d]: blockReceiptsToNetwork returned incomplete == true", i)
|
||||
}
|
||||
|
||||
// parse as Receipts response list from network encoding
|
||||
var rl ReceiptList
|
||||
|
|
|
|||
Loading…
Reference in a new issue