1 // Copyright (c) 2013-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
13 "github.com/btcsuite/btcd/chaincfg/chainhash"
14 "github.com/davecgh/go-spew/spew"
17 // TestGetData tests the MsgGetData API.
18 func TestGetData(t *testing.T) {
19 pver := ProtocolVersion
21 // Ensure the command is expected value.
23 msg := NewMsgGetData()
24 if cmd := msg.Command(); cmd != wantCmd {
25 t.Errorf("NewMsgGetData: wrong command - got %v want %v",
29 // Ensure max payload is expected value for latest protocol version.
30 // Num inventory vectors (varInt) + max allowed inventory vectors.
31 wantPayload := uint32(1800009)
32 maxPayload := msg.MaxPayloadLength(pver)
33 if maxPayload != wantPayload {
34 t.Errorf("MaxPayloadLength: wrong max payload length for "+
35 "protocol version %d - got %v, want %v", pver,
36 maxPayload, wantPayload)
39 // Ensure inventory vectors are added properly.
40 hash := chainhash.Hash{}
41 iv := NewInvVect(InvTypeBlock, &hash)
42 err := msg.AddInvVect(iv)
44 t.Errorf("AddInvVect: %v", err)
46 if msg.InvList[0] != iv {
47 t.Errorf("AddInvVect: wrong invvect added - got %v, want %v",
48 spew.Sprint(msg.InvList[0]), spew.Sprint(iv))
51 // Ensure adding more than the max allowed inventory vectors per
52 // message returns an error.
53 for i := 0; i < MaxInvPerMsg; i++ {
54 err = msg.AddInvVect(iv)
57 t.Errorf("AddInvVect: expected error on too many inventory " +
58 "vectors not received")
61 // Ensure creating the message with a size hint larger than the max
63 msg = NewMsgGetDataSizeHint(MaxInvPerMsg + 1)
64 wantCap := MaxInvPerMsg
65 if cap(msg.InvList) != wantCap {
66 t.Errorf("NewMsgGetDataSizeHint: wrong cap for size hint - "+
67 "got %v, want %v", cap(msg.InvList), wantCap)
71 // TestGetDataWire tests the MsgGetData wire encode and decode for various
72 // numbers of inventory vectors and protocol versions.
73 func TestGetDataWire(t *testing.T) {
75 hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
76 blockHash, err := chainhash.NewHashFromStr(hashStr)
78 t.Errorf("NewHashFromStr: %v", err)
81 // Transation 1 of Block 203707 hash.
82 hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
83 txHash, err := chainhash.NewHashFromStr(hashStr)
85 t.Errorf("NewHashFromStr: %v", err)
88 iv := NewInvVect(InvTypeBlock, blockHash)
89 iv2 := NewInvVect(InvTypeTx, txHash)
91 // Empty MsgGetData message.
92 NoInv := NewMsgGetData()
93 NoInvEncoded := []byte{
94 0x00, // Varint for number of inventory vectors
97 // MsgGetData message with multiple inventory vectors.
98 MultiInv := NewMsgGetData()
99 MultiInv.AddInvVect(iv)
100 MultiInv.AddInvVect(iv2)
101 MultiInvEncoded := []byte{
102 0x02, // Varint for number of inv vectors
103 0x02, 0x00, 0x00, 0x00, // InvTypeBlock
104 0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
105 0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
106 0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
107 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
108 0x01, 0x00, 0x00, 0x00, // InvTypeTx
109 0xf0, 0xfa, 0xcc, 0x7a, 0x48, 0x1b, 0xe7, 0xcf,
110 0x42, 0xbd, 0x7f, 0xe5, 0x4f, 0x2c, 0x2a, 0xf8,
111 0xef, 0x81, 0x9a, 0xdd, 0x93, 0xee, 0x55, 0x98,
112 0x0a, 0xf0, 0x2b, 0x39, 0xc7, 0x3d, 0x8a, 0xd2, // Tx 1 of block 203707 hash
116 in *MsgGetData // Message to encode
117 out *MsgGetData // Expected decoded message
118 buf []byte // Wire encoding
119 pver uint32 // Protocol version for wire encoding
120 enc MessageEncoding // Message encoding format
122 // Latest protocol version with no inv vectors.
131 // Latest protocol version with multiple inv vectors.
140 // Protocol version BIP0035Version no inv vectors.
149 // Protocol version BIP0035Version with multiple inv vectors.
158 // Protocol version BIP0031Version no inv vectors.
167 // Protocol version BIP0031Version with multiple inv vectors.
176 // Protocol version NetAddressTimeVersion no inv vectors.
181 NetAddressTimeVersion,
185 // Protocol version NetAddressTimeVersion with multiple inv vectors.
190 NetAddressTimeVersion,
194 // Protocol version MultipleAddressVersion no inv vectors.
199 MultipleAddressVersion,
203 // Protocol version MultipleAddressVersion with multiple inv vectors.
208 MultipleAddressVersion,
213 t.Logf("Running %d tests", len(tests))
214 for i, test := range tests {
215 // Encode the message to wire format.
217 err := test.in.BtcEncode(&buf, test.pver, test.enc)
219 t.Errorf("BtcEncode #%d error %v", i, err)
222 if !bytes.Equal(buf.Bytes(), test.buf) {
223 t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
224 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
228 // Decode the message from wire format.
230 rbuf := bytes.NewReader(test.buf)
231 err = msg.BtcDecode(rbuf, test.pver, test.enc)
233 t.Errorf("BtcDecode #%d error %v", i, err)
236 if !reflect.DeepEqual(&msg, test.out) {
237 t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
238 spew.Sdump(msg), spew.Sdump(test.out))
244 // TestGetDataWireErrors performs negative tests against wire encode and decode
245 // of MsgGetData to confirm error paths work correctly.
246 func TestGetDataWireErrors(t *testing.T) {
247 pver := ProtocolVersion
248 wireErr := &MessageError{}
250 // Block 203707 hash.
251 hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
252 blockHash, err := chainhash.NewHashFromStr(hashStr)
254 t.Errorf("NewHashFromStr: %v", err)
257 iv := NewInvVect(InvTypeBlock, blockHash)
259 // Base message used to induce errors.
260 baseGetData := NewMsgGetData()
261 baseGetData.AddInvVect(iv)
262 baseGetDataEncoded := []byte{
263 0x02, // Varint for number of inv vectors
264 0x02, 0x00, 0x00, 0x00, // InvTypeBlock
265 0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
266 0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
267 0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
268 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
271 // Message that forces an error by having more than the max allowed inv
273 maxGetData := NewMsgGetData()
274 for i := 0; i < MaxInvPerMsg; i++ {
275 maxGetData.AddInvVect(iv)
277 maxGetData.InvList = append(maxGetData.InvList, iv)
278 maxGetDataEncoded := []byte{
279 0xfd, 0x51, 0xc3, // Varint for number of inv vectors (50001)
283 in *MsgGetData // Value to encode
284 buf []byte // Wire encoding
285 pver uint32 // Protocol version for wire encoding
286 enc MessageEncoding // Message encoding format
287 max int // Max size of fixed buffer to induce errors
288 writeErr error // Expected write error
289 readErr error // Expected read error
291 // Latest protocol version with intentional read/write errors.
292 // Force error in inventory vector count
293 {baseGetData, baseGetDataEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
294 // Force error in inventory list.
295 {baseGetData, baseGetDataEncoded, pver, BaseEncoding, 1, io.ErrShortWrite, io.EOF},
296 // Force error with greater than max inventory vectors.
297 {maxGetData, maxGetDataEncoded, pver, BaseEncoding, 3, wireErr, wireErr},
300 t.Logf("Running %d tests", len(tests))
301 for i, test := range tests {
302 // Encode to wire format.
303 w := newFixedWriter(test.max)
304 err := test.in.BtcEncode(w, test.pver, test.enc)
305 if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
306 t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
307 i, err, test.writeErr)
311 // For errors which are not of type MessageError, check them for
313 if _, ok := err.(*MessageError); !ok {
314 if err != test.writeErr {
315 t.Errorf("BtcEncode #%d wrong error got: %v, "+
316 "want: %v", i, err, test.writeErr)
321 // Decode from wire format.
323 r := newFixedReader(test.max, test.buf)
324 err = msg.BtcDecode(r, test.pver, test.enc)
325 if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
326 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
327 i, err, test.readErr)
331 // For errors which are not of type MessageError, check them for
333 if _, ok := err.(*MessageError); !ok {
334 if err != test.readErr {
335 t.Errorf("BtcDecode #%d wrong error got: %v, "+
336 "want: %v", i, err, test.readErr)