mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
WIP
This commit is contained in:
parent
d86f0547cf
commit
08b6d495a9
6 changed files with 269 additions and 140 deletions
|
|
@ -59,11 +59,12 @@ func (b *Bloom) SetBytes(d []byte) {
|
||||||
|
|
||||||
// Add adds d to the filter. Future calls of Test(d) will return true.
|
// Add adds d to the filter. Future calls of Test(d) will return true.
|
||||||
func (b *Bloom) Add(d []byte) {
|
func (b *Bloom) Add(d []byte) {
|
||||||
b.add(d, make([]byte, 6))
|
var buf [6]byte
|
||||||
|
b.AddWithBuffer(d, &buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add is internal version of Add, which takes a scratch buffer for reuse (needs to be at least 6 bytes)
|
// add is internal version of Add, which takes a scratch buffer for reuse (needs to be at least 6 bytes)
|
||||||
func (b *Bloom) add(d []byte, buf []byte) {
|
func (b *Bloom) AddWithBuffer(d []byte, buf *[6]byte) {
|
||||||
i1, v1, i2, v2, i3, v3 := bloomValues(d, buf)
|
i1, v1, i2, v2, i3, v3 := bloomValues(d, buf)
|
||||||
b[i1] |= v1
|
b[i1] |= v1
|
||||||
b[i2] |= v2
|
b[i2] |= v2
|
||||||
|
|
@ -84,7 +85,8 @@ func (b Bloom) Bytes() []byte {
|
||||||
|
|
||||||
// Test checks if the given topic is present in the bloom filter
|
// Test checks if the given topic is present in the bloom filter
|
||||||
func (b Bloom) Test(topic []byte) bool {
|
func (b Bloom) Test(topic []byte) bool {
|
||||||
i1, v1, i2, v2, i3, v3 := bloomValues(topic, make([]byte, 6))
|
var buf [6]byte
|
||||||
|
i1, v1, i2, v2, i3, v3 := bloomValues(topic, &buf)
|
||||||
return v1 == v1&b[i1] &&
|
return v1 == v1&b[i1] &&
|
||||||
v2 == v2&b[i2] &&
|
v2 == v2&b[i2] &&
|
||||||
v3 == v3&b[i3]
|
v3 == v3&b[i3]
|
||||||
|
|
@ -107,9 +109,9 @@ func CreateBloom(receipt *Receipt) Bloom {
|
||||||
buf = make([]byte, 6)
|
buf = make([]byte, 6)
|
||||||
)
|
)
|
||||||
for _, log := range receipt.Logs {
|
for _, log := range receipt.Logs {
|
||||||
bin.add(log.Address.Bytes(), buf)
|
bin.AddWithBuffer(log.Address.Bytes(), buf)
|
||||||
for _, b := range log.Topics {
|
for _, b := range log.Topics {
|
||||||
bin.add(b[:], buf)
|
bin.AddWithBuffer(b[:], buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bin
|
return bin
|
||||||
|
|
@ -139,21 +141,20 @@ func Bloom9(data []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// bloomValues returns the bytes (index-value pairs) to set for the given data
|
// bloomValues returns the bytes (index-value pairs) to set for the given data
|
||||||
func bloomValues(data []byte, hashbuf []byte) (uint, byte, uint, byte, uint, byte) {
|
func bloomValues(data []byte, hashbuf *[6]byte) (uint, byte, uint, byte, uint, byte) {
|
||||||
sha := hasherPool.Get().(crypto.KeccakState)
|
sha := hasherPool.Get().(crypto.KeccakState)
|
||||||
sha.Reset()
|
sha.Reset()
|
||||||
sha.Write(data)
|
sha.Write(data)
|
||||||
sha.Read(hashbuf)
|
sha.Read(hashbuf[:])
|
||||||
hasherPool.Put(sha)
|
hasherPool.Put(sha)
|
||||||
// The actual bits to flip
|
// The actual bits to flip
|
||||||
v1 := byte(1 << (hashbuf[1] & 0x7))
|
v1 := byte(1 << (hashbuf[1] & 0x7))
|
||||||
v2 := byte(1 << (hashbuf[3] & 0x7))
|
v2 := byte(1 << (hashbuf[3] & 0x7))
|
||||||
v3 := byte(1 << (hashbuf[5] & 0x7))
|
v3 := byte(1 << (hashbuf[5] & 0x7))
|
||||||
// The indices for the bytes to OR in
|
// The indices for the bytes to OR in
|
||||||
i1 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf)&0x7ff)>>3) - 1
|
i1 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[0:])&0x7ff)>>3) - 1
|
||||||
i2 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[2:])&0x7ff)>>3) - 1
|
i2 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[2:])&0x7ff)>>3) - 1
|
||||||
i3 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[4:])&0x7ff)>>3) - 1
|
i3 := BloomByteLength - uint((binary.BigEndian.Uint16(hashbuf[4:])&0x7ff)>>3) - 1
|
||||||
|
|
||||||
return i1, v1, i2, v2, i3, v3
|
return i1, v1, i2, v2, i3, v3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -699,41 +699,3 @@ func testGetPooledTransaction(t *testing.T, blobTx bool) {
|
||||||
t.Errorf("pooled transaction mismatch: %v", err)
|
t.Errorf("pooled transaction mismatch: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransformReceipts(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input []types.ReceiptForStorage
|
|
||||||
txs []*types.Transaction
|
|
||||||
output []receiptForNetwork
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: nil}},
|
|
||||||
txs: []*types.Transaction{types.NewTx(&types.LegacyTx{})},
|
|
||||||
output: []receiptForNetwork{{GasUsed: 123, Status: 1, Logs: nil}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: nil}},
|
|
||||||
txs: []*types.Transaction{types.NewTx(&types.DynamicFeeTx{})},
|
|
||||||
output: []receiptForNetwork{{GasUsed: 123, Status: 1, Logs: nil, Type: 2}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: nil}},
|
|
||||||
txs: []*types.Transaction{types.NewTx(&types.AccessListTx{})},
|
|
||||||
output: []receiptForNetwork{{GasUsed: 123, Status: 1, Logs: nil, Type: 1}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: []*types.Log{{Address: common.Address{1}, Topics: []common.Hash{{1}}}}}},
|
|
||||||
txs: []*types.Transaction{types.NewTx(&types.AccessListTx{})},
|
|
||||||
output: []receiptForNetwork{{GasUsed: 123, Status: 1, Logs: []*types.Log{{Address: common.Address{1}, Topics: []common.Hash{{1}}}}, Type: 1}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
in, _ := rlp.EncodeToBytes(test.input)
|
|
||||||
have := transformReceipts(in, test.txs)
|
|
||||||
out, _ := rlp.EncodeToBytes(test.output)
|
|
||||||
if !bytes.Equal(have, out) {
|
|
||||||
t.Fatalf("transforming receipt mismatch, test %v: want %v have %v", i, out, have)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -319,7 +318,7 @@ func serviceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest)
|
||||||
if header.ReceiptHash != types.EmptyReceiptsHash {
|
if header.ReceiptHash != types.EmptyReceiptsHash {
|
||||||
body := new(types.Body)
|
body := new(types.Body)
|
||||||
if err := rlp.DecodeBytes(chain.GetBodyRLP(hash), &body); err == nil {
|
if err := rlp.DecodeBytes(chain.GetBodyRLP(hash), &body); err == nil {
|
||||||
results = transformReceipts(results, body.Transactions)
|
results = blockReceiptsToNetwork(results, body.Transactions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -329,33 +328,6 @@ func serviceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest)
|
||||||
return receipts
|
return receipts
|
||||||
}
|
}
|
||||||
|
|
||||||
// transformReceipts takes a slice of rlp-encoded receipts, and transactions,
|
|
||||||
// and applies the type-encoding on the receipts (for non-legacy receipts).
|
|
||||||
// e.g. for non-legacy receipts: receipt-data -> {tx-type || receipt-data}
|
|
||||||
func transformReceipts(blockReceipts []byte, txs []*types.Transaction) []byte {
|
|
||||||
var (
|
|
||||||
out bytes.Buffer
|
|
||||||
enc = rlp.NewEncoderBuffer(&out)
|
|
||||||
it, _ = rlp.NewListIterator(blockReceipts)
|
|
||||||
)
|
|
||||||
outer := enc.List()
|
|
||||||
for i := 0; it.Next(); i++ {
|
|
||||||
if txs[i].Type() == types.LegacyTxType {
|
|
||||||
enc.Write(it.Value())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
content, _, _ := rlp.SplitList(it.Value())
|
|
||||||
receiptList := enc.List()
|
|
||||||
enc.Write([]byte{txs[i].Type()})
|
|
||||||
enc.Write(content)
|
|
||||||
enc.ListEnd(receiptList)
|
|
||||||
}
|
|
||||||
enc.ListEnd(outer)
|
|
||||||
enc.Flush()
|
|
||||||
|
|
||||||
return out.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleNewBlockhashes(backend Backend, msg Decoder, peer *Peer) error {
|
func handleNewBlockhashes(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
return errors.New("block announcements disallowed") // We dropped support for non-merge networks
|
return errors.New("block announcements disallowed") // We dropped support for non-merge networks
|
||||||
}
|
}
|
||||||
|
|
@ -440,32 +412,23 @@ func handleReceipts69(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
if err := msg.Decode(res); err != nil {
|
if err := msg.Decode(res); err != nil {
|
||||||
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
|
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
|
||||||
}
|
}
|
||||||
var response ReceiptsResponse
|
buffers := new(receiptListBuffers)
|
||||||
// calculate the bloom filter before dispatching
|
for _, rl := range res.List {
|
||||||
for _, receipts := range res.ReceiptsResponse69 {
|
rl.buf = buffers
|
||||||
var rec []*types.Receipt
|
// WIP
|
||||||
for _, receipt := range receipts {
|
|
||||||
receipt.Bloom = types.CreateBloom((*types.Receipt)(receipt))
|
|
||||||
rec = append(rec, (*types.Receipt)(receipt))
|
|
||||||
}
|
|
||||||
response = append(response, rec)
|
|
||||||
}
|
}
|
||||||
metadata := func() interface{} {
|
metadata := func() interface{} {
|
||||||
hasher := trie.NewStackTrie(nil)
|
hasher := trie.NewStackTrie(nil)
|
||||||
hashes := make([]common.Hash, len(response))
|
hashes := make([]common.Hash, len(res.List))
|
||||||
for i, receipts := range response {
|
for i, rl := range res.List {
|
||||||
var r []*types.Receipt
|
hashes[i] = types.DeriveSha(&rl, hasher)
|
||||||
for _, receipt := range receipts {
|
|
||||||
r = append(r, (*types.Receipt)(receipt))
|
|
||||||
}
|
|
||||||
hashes[i] = types.DeriveSha(types.Receipts(r), hasher)
|
|
||||||
}
|
}
|
||||||
return hashes
|
return hashes
|
||||||
}
|
}
|
||||||
return peer.dispatchResponse(&Response{
|
return peer.dispatchResponse(&Response{
|
||||||
id: res.RequestId,
|
id: res.RequestId,
|
||||||
code: ReceiptsMsg,
|
code: ReceiptsMsg,
|
||||||
Res: &response,
|
Res: &res,
|
||||||
}, metadata)
|
}, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -260,14 +260,11 @@ type ReceiptsPacket struct {
|
||||||
ReceiptsResponse
|
ReceiptsResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiptsResponse is the network packet for block receipts distribution.
|
|
||||||
type ReceiptsResponse69 [][]*receiptForNetwork
|
|
||||||
|
|
||||||
// ReceiptsPacket is the network packet for block receipts distribution with
|
// ReceiptsPacket is the network packet for block receipts distribution with
|
||||||
// request ID wrapping.
|
// request ID wrapping.
|
||||||
type ReceiptsPacket69 struct {
|
type ReceiptsPacket69 struct {
|
||||||
RequestId uint64
|
RequestId uint64
|
||||||
ReceiptsResponse69
|
List []ReceiptList69
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiptsRLPResponse is used for receipts, when we already have it encoded
|
// ReceiptsRLPResponse is used for receipts, when we already have it encoded
|
||||||
|
|
|
||||||
|
|
@ -17,64 +17,206 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type receiptForNetwork types.Receipt
|
// Receipt is the eth/69 network encoding of a receipt.
|
||||||
|
type Receipt struct {
|
||||||
func (r *receiptForNetwork) DecodeRLP(s *rlp.Stream) error {
|
TxType byte
|
||||||
kind, size, err := s.Kind()
|
PostStateOrStatus []byte
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if kind != rlp.List {
|
|
||||||
return errors.New("invalid receipt")
|
|
||||||
}
|
|
||||||
if size == 4 {
|
|
||||||
var rec = new(struct {
|
|
||||||
Type byte
|
|
||||||
Status uint64
|
|
||||||
GasUsed uint64
|
GasUsed uint64
|
||||||
Logs []*types.Log
|
Logs rlp.RawValue
|
||||||
})
|
}
|
||||||
if err := s.Decode(rec); err != nil {
|
|
||||||
|
func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
|
||||||
|
if _, err := s.List(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.Type = rec.Type
|
txtype, err := s.Uint8()
|
||||||
r.Status = rec.Status
|
if err != nil {
|
||||||
r.GasUsed = rec.GasUsed
|
return fmt.Errorf("invalid txType: %w", err)
|
||||||
r.Logs = rec.Logs
|
}
|
||||||
} else {
|
postStateOrStatus, err := s.Bytes()
|
||||||
s.Decode(&r)
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid postStateOrStatus: %w", err)
|
||||||
|
}
|
||||||
|
gasUsed, err := s.Uint64()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid gasUsed: %w", err)
|
||||||
|
}
|
||||||
|
logs, err := s.Raw()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid logs: %w", err)
|
||||||
|
}
|
||||||
|
*r = Receipt{
|
||||||
|
TxType: txtype,
|
||||||
|
PostStateOrStatus: postStateOrStatus,
|
||||||
|
GasUsed: gasUsed,
|
||||||
|
Logs: logs,
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *receiptForNetwork) EncodeRLP(_w io.Writer) error {
|
func (r *Receipt) EncodeRLP(_w io.Writer) error {
|
||||||
data := &types.ReceiptForStorage{Status: r.Status, CumulativeGasUsed: r.GasUsed, Logs: r.Logs}
|
|
||||||
if r.Type == types.LegacyTxType {
|
|
||||||
return rlp.Encode(_w, data)
|
|
||||||
}
|
|
||||||
w := rlp.NewEncoderBuffer(_w)
|
w := rlp.NewEncoderBuffer(_w)
|
||||||
outerList := w.List()
|
list := w.List()
|
||||||
w.Write([]byte{r.Type})
|
w.WriteUint64(uint64(r.TxType))
|
||||||
if r.Status == types.ReceiptStatusSuccessful {
|
w.WriteBytes(r.PostStateOrStatus)
|
||||||
w.Write([]byte{0x01})
|
|
||||||
} else {
|
|
||||||
w.Write([]byte{0x00})
|
|
||||||
}
|
|
||||||
w.WriteUint64(r.GasUsed)
|
w.WriteUint64(r.GasUsed)
|
||||||
logList := w.List()
|
w.Write(r.Logs)
|
||||||
for _, log := range r.Logs {
|
w.ListEnd(list)
|
||||||
if err := log.EncodeRLP(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.ListEnd(logList)
|
|
||||||
w.ListEnd(outerList)
|
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bloom computes the bloom filter of the receipt.
|
||||||
|
// Note this doesn't check the validity of encoding, and will produce an invalid filter
|
||||||
|
// for invalid input. This is acceptable for the purpose of this function, which is
|
||||||
|
// recomputing the receipt hash.
|
||||||
|
func (r *Receipt) bloom(buffer *[6]byte) types.Bloom {
|
||||||
|
var b types.Bloom
|
||||||
|
logsIter, err := rlp.NewListIterator(r.Logs)
|
||||||
|
if err != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
for logsIter.Next() {
|
||||||
|
log := logsIter.Value()
|
||||||
|
address, log, _ := rlp.SplitString(log)
|
||||||
|
b.AddWithBuffer(address, buffer)
|
||||||
|
topicsIter, err := rlp.NewListIterator(log)
|
||||||
|
if err != nil {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
for topicsIter.Next() {
|
||||||
|
b.AddWithBuffer(topicsIter.Value(), buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReceiptList69 is the block receipt list as downloaded by eth/69.
|
||||||
|
// This implements types.DerivableList for validation purposes.
|
||||||
|
type ReceiptList69 struct {
|
||||||
|
buf *receiptListBuffers
|
||||||
|
items []Receipt
|
||||||
|
}
|
||||||
|
|
||||||
|
type receiptListBuffers struct {
|
||||||
|
enc rlp.EncoderBuffer
|
||||||
|
bloom [6]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length of the list.
|
||||||
|
func (rl *ReceiptList69) Len() int {
|
||||||
|
return len(rl.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeIndex implements types.DerivableList.
|
||||||
|
func (rl *ReceiptList69) EncodeIndex(i int, b *bytes.Buffer) {
|
||||||
|
if rl.buf == nil {
|
||||||
|
rl.buf = new(receiptListBuffers)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
r = &rl.items[i]
|
||||||
|
bloom = r.bloom(&rl.buf.bloom)
|
||||||
|
w = &rl.buf.enc
|
||||||
|
)
|
||||||
|
// encode receipt list: [postStateOrStatus, gasUsed, bloom, logs]
|
||||||
|
w.Reset(b)
|
||||||
|
l := w.List()
|
||||||
|
w.WriteBytes(r.PostStateOrStatus)
|
||||||
|
w.WriteUint64(r.GasUsed)
|
||||||
|
w.WriteBytes(bloom[:])
|
||||||
|
w.Write(r.Logs)
|
||||||
|
w.ListEnd(l)
|
||||||
|
if err := w.Flush(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if this is a legacy transaction receipt, we are done.
|
||||||
|
if r.TxType == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Otherwise it's a typed transaction receipt, which has the type prefix and
|
||||||
|
// the inner list as a byte-array: tx-type || rlp(list).
|
||||||
|
// Since b contains the correct inner list, we can reuse its content.
|
||||||
|
w.Reset(b)
|
||||||
|
w.WriteUint64(uint64(r.TxType))
|
||||||
|
w.WriteBytes(b.Bytes())
|
||||||
|
w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeForDatabase
|
||||||
|
func (rl *ReceiptList69) EncodeForDatabase() []byte {
|
||||||
|
if rl.buf == nil {
|
||||||
|
rl.buf = new(receiptListBuffers)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
r = &rl.items[i]
|
||||||
|
bloom = r.bloom(&rl.buf.bloom)
|
||||||
|
w = &rl.buf.enc
|
||||||
|
)
|
||||||
|
// encode receipt list: [postStateOrStatus, gasUsed, bloom, logs]
|
||||||
|
w.Reset(b)
|
||||||
|
l := w.List()
|
||||||
|
w.WriteBytes(r.PostStateOrStatus)
|
||||||
|
w.WriteUint64(r.GasUsed)
|
||||||
|
w.WriteBytes(bloom[:])
|
||||||
|
w.Write(r.Logs)
|
||||||
|
w.ListEnd(l)
|
||||||
|
if err := w.Flush(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// if this is a legacy transaction receipt, we are done.
|
||||||
|
if r.TxType == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Otherwise it's a typed transaction receipt, which has the type prefix and
|
||||||
|
// the inner list as a byte-array: tx-type || rlp(list).
|
||||||
|
// Since b contains the correct inner list, we can reuse its content.
|
||||||
|
w.Reset(b)
|
||||||
|
w.WriteUint64(uint64(r.TxType))
|
||||||
|
w.WriteBytes(b.Bytes())
|
||||||
|
w.Flush()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rl *ReceiptList69) toReceipts() []*types.Receipt {
|
||||||
|
list := make([]*types.Receipt, len(rl.items))
|
||||||
|
for i, r := range rl.items {
|
||||||
|
list[i] = &types.Receipt{
|
||||||
|
Type: r.TxType,
|
||||||
|
PostState: r.PostStateOrStatus,
|
||||||
|
CumulativeGasUsed: r.GasUsed,
|
||||||
|
}
|
||||||
|
rlp.DecodeBytes(r.Logs, &list[i].Logs)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// blockReceiptsToNetwork takes a slice of rlp-encoded receipts, and transactions,
|
||||||
|
// and applies the type-encoding on the receipts (for non-legacy receipts).
|
||||||
|
// e.g. for non-legacy receipts: receipt-data -> {tx-type || receipt-data}
|
||||||
|
func blockReceiptsToNetwork(blockReceipts []byte, txs []*types.Transaction) []byte {
|
||||||
|
var (
|
||||||
|
out bytes.Buffer
|
||||||
|
enc = rlp.NewEncoderBuffer(&out)
|
||||||
|
it, _ = rlp.NewListIterator(blockReceipts)
|
||||||
|
)
|
||||||
|
outer := enc.List()
|
||||||
|
for i := 0; it.Next(); i++ {
|
||||||
|
content, _, _ := rlp.SplitList(it.Value())
|
||||||
|
receiptList := enc.List()
|
||||||
|
enc.Write([]byte{txs[i].Type()})
|
||||||
|
enc.Write(content)
|
||||||
|
enc.ListEnd(receiptList)
|
||||||
|
}
|
||||||
|
enc.ListEnd(outer)
|
||||||
|
enc.Flush()
|
||||||
|
return out.Bytes()
|
||||||
|
}
|
||||||
|
|
|
||||||
64
eth/protocols/eth/receipt_test.go
Normal file
64
eth/protocols/eth/receipt_test.go
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright 2024 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package eth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTransformReceipts(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input []types.ReceiptForStorage
|
||||||
|
txs []*types.Transaction
|
||||||
|
output []Receipt
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: nil}},
|
||||||
|
txs: []*types.Transaction{types.NewTx(&types.LegacyTx{})},
|
||||||
|
output: []Receipt{{GasUsed: 123, PostStateOrStatus: []byte{1}, Logs: nil}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: nil}},
|
||||||
|
txs: []*types.Transaction{types.NewTx(&types.DynamicFeeTx{})},
|
||||||
|
output: []Receipt{{GasUsed: 123, PostStateOrStatus: []byte{1}, Logs: nil, TxType: 2}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: nil}},
|
||||||
|
txs: []*types.Transaction{types.NewTx(&types.AccessListTx{})},
|
||||||
|
output: []Receipt{{GasUsed: 123, PostStateOrStatus: []byte{1}, Logs: nil, TxType: 1}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: []types.ReceiptForStorage{{CumulativeGasUsed: 123, Status: 1, Logs: []*types.Log{{Address: common.Address{1}, Topics: []common.Hash{{1}}}}}},
|
||||||
|
txs: []*types.Transaction{types.NewTx(&types.AccessListTx{})},
|
||||||
|
output: []Receipt{{GasUsed: 123, PostStateOrStatus: []byte{1}, Logs: []*types.Log{{Address: common.Address{1}, Topics: []common.Hash{{1}}}}, Type: 1}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
in, _ := rlp.EncodeToBytes(test.input)
|
||||||
|
have := blockReceiptsToNetwork(in, test.txs)
|
||||||
|
out, _ := rlp.EncodeToBytes(test.output)
|
||||||
|
if !bytes.Equal(have, out) {
|
||||||
|
t.Fatalf("transforming receipt mismatch, test %v: want %v have %v", i, out, have)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue