@@ -22,10 +22,12 @@ package eth
2222import (
2323 "crypto/rand"
2424 "testing"
25+ "time"
2526
2627 "github.com/ethereum/go-ethereum/common"
2728 "github.com/ethereum/go-ethereum/p2p"
2829 "github.com/ethereum/go-ethereum/p2p/enode"
30+ "github.com/ethereum/go-ethereum/rlp"
2931)
3032
3133// testPeer is a simulated peer to allow testing direct network calls.
@@ -88,3 +90,131 @@ func TestPeerSet(t *testing.T) {
8890 t .Fatalf ("bad size" )
8991 }
9092}
93+
94+ func TestPartialReceipt (t * testing.T ) {
95+ app , net := p2p .MsgPipe ()
96+ var id enode.ID
97+ if _ , err := rand .Read (id [:]); err != nil {
98+ t .Fatalf ("failed to create random peer: %v" , err )
99+ }
100+
101+ peer := NewPeer (ETH70 , p2p .NewPeer (id , "peer" , nil ), net , nil )
102+
103+ packetCh := make (chan * GetReceiptsPacket70 , 1 )
104+ go func () {
105+ for {
106+ msg , err := app .ReadMsg ()
107+ if err != nil {
108+ return
109+ }
110+ if msg .Code == GetReceiptsMsg {
111+ var pkt GetReceiptsPacket70
112+ if err := msg .Decode (& pkt ); err == nil {
113+ select {
114+ case packetCh <- & pkt :
115+ default :
116+ }
117+ }
118+ }
119+ msg .Discard ()
120+ }
121+ }()
122+
123+ hashes := []common.Hash {
124+ common .HexToHash ("0xaa" ),
125+ common .HexToHash ("0xbb" ),
126+ common .HexToHash ("0xcc" ),
127+ common .HexToHash ("0xdd" ),
128+ }
129+
130+ sink := make (chan * Response , 1 )
131+ req , err := peer .RequestReceipts (hashes , sink )
132+ if err != nil {
133+ t .Fatalf ("RequestReceipts failed: %v" , err )
134+ }
135+ select {
136+ case _ = <- packetCh :
137+ case <- time .After (2 * time .Second ):
138+ t .Fatalf ("timeout waiting for request packet" )
139+ }
140+
141+ delivery := & ReceiptsPacket70 {
142+ RequestId : req .id ,
143+ LastBlockIncomplete : true ,
144+ List : []* ReceiptList69 {
145+ {
146+ items : []Receipt {
147+ {GasUsed : 21_000 , Logs : rlp .RawValue (make ([]byte , 1 ))},
148+ },
149+ },
150+ {
151+ items : []Receipt {
152+ {GasUsed : 21_000 , Logs : rlp .RawValue (make ([]byte , 2 ))},
153+ },
154+ },
155+ },
156+ }
157+ if _ , err := peer .ReconstructReceiptsPacket (delivery ); err != nil {
158+ t .Fatalf ("first ReconstructReceiptsPacket failed: %v" , err )
159+ }
160+
161+ if err := peer .RequestPartialReceipts (req .id ); err != nil {
162+ t .Fatalf ("RequestPartialReceipts failed: %v" , err )
163+ }
164+
165+ var rereq * GetReceiptsPacket70
166+ select {
167+ case rereq = <- packetCh :
168+ case <- time .After (2 * time .Second ):
169+ t .Fatalf ("timeout waiting for re-request packet" )
170+ }
171+
172+ if _ , ok := peer .receiptBuffer [req .id ]; ok {
173+ t .Fatalf ("receiptBuffer has stale request id" )
174+ }
175+ if _ , ok := peer .requestedReceipts [req .id ]; ok {
176+ t .Fatalf ("requestedReceipts has stale request id" )
177+ }
178+
179+ buffer , ok := peer .receiptBuffer [rereq .RequestId ]
180+ if ! ok {
181+ t .Fatalf ("receiptBuffer should buffer incomplete receipts" )
182+ }
183+ if rereq .FirstBlockReceiptIndex != uint64 (len (buffer .list .items )) {
184+ t .Fatalf ("unexpected FirstBlockReceiptIndex, got %d want %d" , rereq .FirstBlockReceiptIndex , len (buffer .list .items ))
185+ }
186+ if _ , ok := peer .requestedReceipts [rereq .RequestId ]; ! ok {
187+ t .Fatalf ("requestedReceipts should buffer receipt hashes" )
188+ }
189+
190+ delivery = & ReceiptsPacket70 {
191+ RequestId : rereq .RequestId ,
192+ LastBlockIncomplete : false ,
193+ List : []* ReceiptList69 {
194+ {
195+ items : []Receipt {
196+ {GasUsed : 21_000 , Logs : rlp .RawValue (make ([]byte , 1 ))},
197+ },
198+ },
199+ {
200+ items : []Receipt {
201+ {GasUsed : 21_000 , Logs : rlp .RawValue (make ([]byte , 1 ))},
202+ },
203+ },
204+ {
205+ items : []Receipt {
206+ {GasUsed : 21_000 , Logs : rlp .RawValue (make ([]byte , 1 ))},
207+ },
208+ },
209+ },
210+ }
211+ if _ , err := peer .ReconstructReceiptsPacket (delivery ); err != nil {
212+ t .Fatalf ("second ReconstructReceiptsPacket failed: %v" , err )
213+ }
214+ if _ , ok := peer .receiptBuffer [rereq .RequestId ]; ok {
215+ t .Fatalf ("receiptBuffer should be cleared after delivery" )
216+ }
217+ if _ , ok := peer .requestedReceipts [rereq .RequestId ]; ok {
218+ t .Fatalf ("requestedReceipts should be cleared after delivery" )
219+ }
220+ }
0 commit comments