mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-18 21:01:38 +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
|
// It does not send the bloom filters for the receipts. It is exposed
|
||||||
// to allow external packages to test protocol behavior.
|
// to allow external packages to test protocol behavior.
|
||||||
func ServiceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest) rlp.RawList[*ReceiptList] {
|
func ServiceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest) rlp.RawList[*ReceiptList] {
|
||||||
// Gather state data until the fetch or network limits is reached
|
|
||||||
var (
|
var (
|
||||||
bytes int
|
bytes int
|
||||||
receipts rlp.RawList[*ReceiptList]
|
receipts rlp.RawList[*ReceiptList]
|
||||||
)
|
)
|
||||||
for lookups, hash := range query {
|
for lookups, hash := range query {
|
||||||
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe ||
|
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe || lookups >= 2*maxReceiptsServe {
|
||||||
lookups >= 2*maxReceiptsServe {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the requested block's receipts
|
// Retrieve the requested block's receipts
|
||||||
results := chain.GetReceiptsRLP(hash)
|
results := chain.GetReceiptsRLP(hash)
|
||||||
if results == nil {
|
if results == nil {
|
||||||
if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
|
continue // Can't retrieve the receipts, so we just skip this block.
|
||||||
continue
|
}
|
||||||
}
|
body := chain.GetBodyRLP(hash)
|
||||||
} else {
|
if body == nil {
|
||||||
body := chain.GetBodyRLP(hash)
|
continue // The block body is missing, we also have to skip.
|
||||||
if body == nil {
|
}
|
||||||
continue
|
results, _, err := blockReceiptsToNetwork(results, body, receiptQueryParams{})
|
||||||
}
|
if err != nil {
|
||||||
var err error
|
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||||
results, err = blockReceiptsToNetwork(results, body)
|
continue
|
||||||
if err != nil {
|
|
||||||
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
receipts.AppendRaw(results)
|
receipts.AppendRaw(results)
|
||||||
bytes += len(results)
|
bytes += len(results)
|
||||||
|
|
@ -309,9 +304,8 @@ func ServiceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest)
|
||||||
// are omitted from the first block receipt list.
|
// are omitted from the first block receipt list.
|
||||||
func serviceGetReceiptsQuery70(chain *core.BlockChain, query GetReceiptsRequest, firstBlockReceiptIndex uint64) (rlp.RawList[*ReceiptList], bool) {
|
func serviceGetReceiptsQuery70(chain *core.BlockChain, query GetReceiptsRequest, firstBlockReceiptIndex uint64) (rlp.RawList[*ReceiptList], bool) {
|
||||||
var (
|
var (
|
||||||
bytes int
|
bytes int
|
||||||
receipts rlp.RawList[*ReceiptList]
|
receipts rlp.RawList[*ReceiptList]
|
||||||
lastBlockIncomplete bool
|
|
||||||
)
|
)
|
||||||
for i, hash := range query {
|
for i, hash := range query {
|
||||||
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe {
|
if bytes >= softResponseLimit || receipts.Len() >= maxReceiptsServe {
|
||||||
|
|
@ -319,65 +313,28 @@ func serviceGetReceiptsQuery70(chain *core.BlockChain, query GetReceiptsRequest,
|
||||||
}
|
}
|
||||||
results := chain.GetReceiptsRLP(hash)
|
results := chain.GetReceiptsRLP(hash)
|
||||||
if results == nil {
|
if results == nil {
|
||||||
if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash {
|
continue // Can't retrieve the receipts, so we just skip this block.
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
body := chain.GetBodyRLP(hash)
|
||||||
if firstBlockReceiptIndex > 0 && i == 0 {
|
if body == nil {
|
||||||
results, lastBlockIncomplete = trimReceiptsRLP(results, int(firstBlockReceiptIndex), maxPacketSize)
|
continue // The block body is missing, we also have to skip.
|
||||||
} else if bytes+len(results) > maxPacketSize {
|
|
||||||
results, lastBlockIncomplete = trimReceiptsRLP(results, 0, maxPacketSize-bytes)
|
|
||||||
}
|
}
|
||||||
|
q := receiptQueryParams{sizeLimit: uint64(maxPacketSize - bytes)}
|
||||||
receipts.AppendRaw(results)
|
if i == 0 {
|
||||||
bytes += len(results)
|
q.firstIndex = firstBlockReceiptIndex
|
||||||
}
|
}
|
||||||
|
results, incomplete, err := blockReceiptsToNetwork(results, body, q)
|
||||||
return receipts, lastBlockIncomplete
|
if err != nil {
|
||||||
}
|
log.Error("Error in block receipts conversion", "hash", hash, "err", err)
|
||||||
|
|
||||||
// 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++
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
receipt := iter.Value()
|
receipts.AppendRaw(results)
|
||||||
if bytes+len(receipt) > limit {
|
bytes += len(results)
|
||||||
overflow = true
|
if incomplete {
|
||||||
break
|
return receipts, true
|
||||||
}
|
}
|
||||||
buffer.Write(receipt)
|
|
||||||
bytes += len(receipt)
|
|
||||||
index++
|
|
||||||
}
|
}
|
||||||
buffer.ListEnd(list)
|
return receipts, false
|
||||||
buffer.Flush()
|
|
||||||
|
|
||||||
return out.Bytes(), overflow
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
|
func handleBlockHeaders(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
|
|
|
||||||
|
|
@ -240,12 +240,17 @@ func (rl *ReceiptList) LogsSize() (uint64, error) {
|
||||||
return size, nil
|
return size, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// blockReceiptsToNetwork takes a slice of rlp-encoded receipts, and transactions,
|
type receiptQueryParams struct {
|
||||||
// and re-encodes them for the network protocol.
|
firstIndex uint64
|
||||||
func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, error) {
|
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)
|
txTypesIter, err := txTypesInBody(blockBody)
|
||||||
if err != nil {
|
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)
|
nextTxType, stopTxTypes := iter.Pull(txTypesIter)
|
||||||
defer stopTxTypes()
|
defer stopTxTypes()
|
||||||
|
|
@ -256,9 +261,24 @@ func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, erro
|
||||||
it, _ = rlp.NewListIterator(blockReceipts)
|
it, _ = rlp.NewListIterator(blockReceipts)
|
||||||
)
|
)
|
||||||
outer := enc.List()
|
outer := enc.List()
|
||||||
for i := 0; it.Next(); i++ {
|
for i := 0; it.Next() && !incomplete; i++ {
|
||||||
txType, _ := nextTxType()
|
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())
|
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()
|
receiptList := enc.List()
|
||||||
enc.WriteUint64(uint64(txType))
|
enc.WriteUint64(uint64(txType))
|
||||||
enc.Write(content)
|
enc.Write(content)
|
||||||
|
|
@ -266,7 +286,7 @@ func blockReceiptsToNetwork(blockReceipts, blockBody rlp.RawValue) ([]byte, erro
|
||||||
}
|
}
|
||||||
enc.ListEnd(outer)
|
enc.ListEnd(outer)
|
||||||
enc.Flush()
|
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.
|
// 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)
|
canonBody, _ := rlp.EncodeToBytes(blockBody)
|
||||||
|
|
||||||
// convert from storage encoding to network encoding
|
// convert from storage encoding to network encoding
|
||||||
network, err := blockReceiptsToNetwork(canonDB, canonBody)
|
network, incomplete, err := blockReceiptsToNetwork(canonDB, canonBody, receiptQueryParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("test[%d]: blockReceiptsToNetwork error: %v", i, err)
|
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
|
// parse as Receipts response list from network encoding
|
||||||
var rl ReceiptList
|
var rl ReceiptList
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue