github.com/palcoin-project/palcd@v1.0.0/wire/msggetheaders_test.go (about) 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. 4 5 package wire 6 7 import ( 8 "bytes" 9 "io" 10 "reflect" 11 "testing" 12 13 "github.com/davecgh/go-spew/spew" 14 "github.com/palcoin-project/palcd/chaincfg/chainhash" 15 ) 16 17 // TestGetHeaders tests the MsgGetHeader API. 18 func TestGetHeaders(t *testing.T) { 19 pver := ProtocolVersion 20 21 // Block 99500 hash. 22 hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0" 23 locatorHash, err := chainhash.NewHashFromStr(hashStr) 24 if err != nil { 25 t.Errorf("NewHashFromStr: %v", err) 26 } 27 28 // Ensure the command is expected value. 29 wantCmd := "getheaders" 30 msg := NewMsgGetHeaders() 31 if cmd := msg.Command(); cmd != wantCmd { 32 t.Errorf("NewMsgGetHeaders: wrong command - got %v want %v", 33 cmd, wantCmd) 34 } 35 36 // Ensure max payload is expected value for latest protocol version. 37 // Protocol version 4 bytes + num hashes (varInt) + max block locator 38 // hashes + hash stop. 39 wantPayload := uint32(16045) 40 maxPayload := msg.MaxPayloadLength(pver) 41 if maxPayload != wantPayload { 42 t.Errorf("MaxPayloadLength: wrong max payload length for "+ 43 "protocol version %d - got %v, want %v", pver, 44 maxPayload, wantPayload) 45 } 46 47 // Ensure block locator hashes are added properly. 48 err = msg.AddBlockLocatorHash(locatorHash) 49 if err != nil { 50 t.Errorf("AddBlockLocatorHash: %v", err) 51 } 52 if msg.BlockLocatorHashes[0] != locatorHash { 53 t.Errorf("AddBlockLocatorHash: wrong block locator added - "+ 54 "got %v, want %v", 55 spew.Sprint(msg.BlockLocatorHashes[0]), 56 spew.Sprint(locatorHash)) 57 } 58 59 // Ensure adding more than the max allowed block locator hashes per 60 // message returns an error. 61 for i := 0; i < MaxBlockLocatorsPerMsg; i++ { 62 err = msg.AddBlockLocatorHash(locatorHash) 63 } 64 if err == nil { 65 t.Errorf("AddBlockLocatorHash: expected error on too many " + 66 "block locator hashes not received") 67 } 68 } 69 70 // TestGetHeadersWire tests the MsgGetHeaders wire encode and decode for various 71 // numbers of block locator hashes and protocol versions. 72 func TestGetHeadersWire(t *testing.T) { 73 // Set protocol inside getheaders message. Use protocol version 60002 74 // specifically here instead of the latest because the test data is 75 // using bytes encoded with that protocol version. 76 pver := uint32(60002) 77 78 // Block 99499 hash. 79 hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535" 80 hashLocator, err := chainhash.NewHashFromStr(hashStr) 81 if err != nil { 82 t.Errorf("NewHashFromStr: %v", err) 83 } 84 85 // Block 99500 hash. 86 hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0" 87 hashLocator2, err := chainhash.NewHashFromStr(hashStr) 88 if err != nil { 89 t.Errorf("NewHashFromStr: %v", err) 90 } 91 92 // Block 100000 hash. 93 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" 94 hashStop, err := chainhash.NewHashFromStr(hashStr) 95 if err != nil { 96 t.Errorf("NewHashFromStr: %v", err) 97 } 98 99 // MsgGetHeaders message with no block locators or stop hash. 100 noLocators := NewMsgGetHeaders() 101 noLocators.ProtocolVersion = pver 102 noLocatorsEncoded := []byte{ 103 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 104 0x00, // Varint for number of block locator hashes 105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop 109 } 110 111 // MsgGetHeaders message with multiple block locators and a stop hash. 112 multiLocators := NewMsgGetHeaders() 113 multiLocators.ProtocolVersion = pver 114 multiLocators.HashStop = *hashStop 115 multiLocators.AddBlockLocatorHash(hashLocator2) 116 multiLocators.AddBlockLocatorHash(hashLocator) 117 multiLocatorsEncoded := []byte{ 118 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 119 0x02, // Varint for number of block locator hashes 120 0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63, 121 0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65, 122 0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b, 123 0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash 124 0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60, 125 0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9, 126 0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40, 127 0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash 128 0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39, 129 0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2, 130 0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa, 131 0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop 132 } 133 134 tests := []struct { 135 in *MsgGetHeaders // Message to encode 136 out *MsgGetHeaders // Expected decoded message 137 buf []byte // Wire encoding 138 pver uint32 // Protocol version for wire encoding 139 enc MessageEncoding // Message encoding format 140 }{ 141 // Latest protocol version with no block locators. 142 { 143 noLocators, 144 noLocators, 145 noLocatorsEncoded, 146 ProtocolVersion, 147 BaseEncoding, 148 }, 149 150 // Latest protocol version with multiple block locators. 151 { 152 multiLocators, 153 multiLocators, 154 multiLocatorsEncoded, 155 ProtocolVersion, 156 BaseEncoding, 157 }, 158 159 // Protocol version BIP0035Version with no block locators. 160 { 161 noLocators, 162 noLocators, 163 noLocatorsEncoded, 164 BIP0035Version, 165 BaseEncoding, 166 }, 167 168 // Protocol version BIP0035Version with multiple block locators. 169 { 170 multiLocators, 171 multiLocators, 172 multiLocatorsEncoded, 173 BIP0035Version, 174 BaseEncoding, 175 }, 176 177 // Protocol version BIP0031Version with no block locators. 178 { 179 noLocators, 180 noLocators, 181 noLocatorsEncoded, 182 BIP0031Version, 183 BaseEncoding, 184 }, 185 186 // Protocol version BIP0031Versionwith multiple block locators. 187 { 188 multiLocators, 189 multiLocators, 190 multiLocatorsEncoded, 191 BIP0031Version, 192 BaseEncoding, 193 }, 194 195 // Protocol version NetAddressTimeVersion with no block locators. 196 { 197 noLocators, 198 noLocators, 199 noLocatorsEncoded, 200 NetAddressTimeVersion, 201 BaseEncoding, 202 }, 203 204 // Protocol version NetAddressTimeVersion multiple block locators. 205 { 206 multiLocators, 207 multiLocators, 208 multiLocatorsEncoded, 209 NetAddressTimeVersion, 210 BaseEncoding, 211 }, 212 213 // Protocol version MultipleAddressVersion with no block locators. 214 { 215 noLocators, 216 noLocators, 217 noLocatorsEncoded, 218 MultipleAddressVersion, 219 BaseEncoding, 220 }, 221 222 // Protocol version MultipleAddressVersion multiple block locators. 223 { 224 multiLocators, 225 multiLocators, 226 multiLocatorsEncoded, 227 MultipleAddressVersion, 228 BaseEncoding, 229 }, 230 } 231 232 t.Logf("Running %d tests", len(tests)) 233 for i, test := range tests { 234 // Encode the message to wire format. 235 var buf bytes.Buffer 236 err := test.in.BtcEncode(&buf, test.pver, test.enc) 237 if err != nil { 238 t.Errorf("BtcEncode #%d error %v", i, err) 239 continue 240 } 241 if !bytes.Equal(buf.Bytes(), test.buf) { 242 t.Errorf("BtcEncode #%d\n got: %s want: %s", i, 243 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) 244 continue 245 } 246 247 // Decode the message from wire format. 248 var msg MsgGetHeaders 249 rbuf := bytes.NewReader(test.buf) 250 err = msg.BtcDecode(rbuf, test.pver, test.enc) 251 if err != nil { 252 t.Errorf("BtcDecode #%d error %v", i, err) 253 continue 254 } 255 if !reflect.DeepEqual(&msg, test.out) { 256 t.Errorf("BtcDecode #%d\n got: %s want: %s", i, 257 spew.Sdump(&msg), spew.Sdump(test.out)) 258 continue 259 } 260 } 261 } 262 263 // TestGetHeadersWireErrors performs negative tests against wire encode and 264 // decode of MsgGetHeaders to confirm error paths work correctly. 265 func TestGetHeadersWireErrors(t *testing.T) { 266 // Set protocol inside getheaders message. Use protocol version 60002 267 // specifically here instead of the latest because the test data is 268 // using bytes encoded with that protocol version. 269 pver := uint32(60002) 270 wireErr := &MessageError{} 271 272 // Block 99499 hash. 273 hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535" 274 hashLocator, err := chainhash.NewHashFromStr(hashStr) 275 if err != nil { 276 t.Errorf("NewHashFromStr: %v", err) 277 } 278 279 // Block 99500 hash. 280 hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0" 281 hashLocator2, err := chainhash.NewHashFromStr(hashStr) 282 if err != nil { 283 t.Errorf("NewHashFromStr: %v", err) 284 } 285 286 // Block 100000 hash. 287 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" 288 hashStop, err := chainhash.NewHashFromStr(hashStr) 289 if err != nil { 290 t.Errorf("NewHashFromStr: %v", err) 291 } 292 293 // MsgGetHeaders message with multiple block locators and a stop hash. 294 baseGetHeaders := NewMsgGetHeaders() 295 baseGetHeaders.ProtocolVersion = pver 296 baseGetHeaders.HashStop = *hashStop 297 baseGetHeaders.AddBlockLocatorHash(hashLocator2) 298 baseGetHeaders.AddBlockLocatorHash(hashLocator) 299 baseGetHeadersEncoded := []byte{ 300 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 301 0x02, // Varint for number of block locator hashes 302 0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63, 303 0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65, 304 0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b, 305 0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash 306 0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60, 307 0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9, 308 0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40, 309 0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash 310 0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39, 311 0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2, 312 0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa, 313 0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop 314 } 315 316 // Message that forces an error by having more than the max allowed 317 // block locator hashes. 318 maxGetHeaders := NewMsgGetHeaders() 319 for i := 0; i < MaxBlockLocatorsPerMsg; i++ { 320 maxGetHeaders.AddBlockLocatorHash(&mainNetGenesisHash) 321 } 322 maxGetHeaders.BlockLocatorHashes = append(maxGetHeaders.BlockLocatorHashes, 323 &mainNetGenesisHash) 324 maxGetHeadersEncoded := []byte{ 325 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 326 0xfd, 0xf5, 0x01, // Varint for number of block loc hashes (501) 327 } 328 329 tests := []struct { 330 in *MsgGetHeaders // Value to encode 331 buf []byte // Wire encoding 332 pver uint32 // Protocol version for wire encoding 333 enc MessageEncoding // Message encoding format 334 max int // Max size of fixed buffer to induce errors 335 writeErr error // Expected write error 336 readErr error // Expected read error 337 }{ 338 // Force error in protocol version. 339 {baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF}, 340 // Force error in block locator hash count. 341 {baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 4, io.ErrShortWrite, io.EOF}, 342 // Force error in block locator hashes. 343 {baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 5, io.ErrShortWrite, io.EOF}, 344 // Force error in stop hash. 345 {baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 69, io.ErrShortWrite, io.EOF}, 346 // Force error with greater than max block locator hashes. 347 {maxGetHeaders, maxGetHeadersEncoded, pver, BaseEncoding, 7, wireErr, wireErr}, 348 } 349 350 t.Logf("Running %d tests", len(tests)) 351 for i, test := range tests { 352 // Encode to wire format. 353 w := newFixedWriter(test.max) 354 err := test.in.BtcEncode(w, test.pver, test.enc) 355 if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) { 356 t.Errorf("BtcEncode #%d wrong error got: %v, want: %v", 357 i, err, test.writeErr) 358 continue 359 } 360 361 // For errors which are not of type MessageError, check them for 362 // equality. 363 if _, ok := err.(*MessageError); !ok { 364 if err != test.writeErr { 365 t.Errorf("BtcEncode #%d wrong error got: %v, "+ 366 "want: %v", i, err, test.writeErr) 367 continue 368 } 369 } 370 371 // Decode from wire format. 372 var msg MsgGetHeaders 373 r := newFixedReader(test.max, test.buf) 374 err = msg.BtcDecode(r, test.pver, test.enc) 375 if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) { 376 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v", 377 i, err, test.readErr) 378 continue 379 } 380 381 // For errors which are not of type MessageError, check them for 382 // equality. 383 if _, ok := err.(*MessageError); !ok { 384 if err != test.readErr { 385 t.Errorf("BtcDecode #%d wrong error got: %v, "+ 386 "want: %v", i, err, test.readErr) 387 continue 388 } 389 } 390 } 391 }