diff --git a/msggetheaders_test.go b/msggetheaders_test.go index 86a0f8f5..063ad2d4 100644 --- a/msggetheaders_test.go +++ b/msggetheaders_test.go @@ -8,6 +8,7 @@ import ( "bytes" "github.com/conformal/btcwire" "github.com/davecgh/go-spew/spew" + "io" "reflect" "testing" ) @@ -70,7 +71,9 @@ func TestGetHeaders(t *testing.T) { // TestGetHeadersWire tests the MsgGetHeaders wire encode and decode for various // numbers of block locator hashes and protocol versions. func TestGetHeadersWire(t *testing.T) { - // Set protocol inside getheaders message. + // Set protocol inside getheaders message. Use protocol version 60002 + // specifically here instead of the latest because the test data is + // using bytes encoded with that protocol version. pver := uint32(60002) // Block 99499 hash. @@ -95,9 +98,9 @@ func TestGetHeadersWire(t *testing.T) { } // MsgGetHeaders message with no block locators or stop hash. - NoLocators := btcwire.NewMsgGetHeaders() - NoLocators.ProtocolVersion = pver - NoLocatorsEncoded := []byte{ + noLocators := btcwire.NewMsgGetHeaders() + noLocators.ProtocolVersion = pver + noLocatorsEncoded := []byte{ 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 0x00, // Varint for number of block locator hashes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -107,12 +110,12 @@ func TestGetHeadersWire(t *testing.T) { } // MsgGetHeaders message with multiple block locators and a stop hash. - MultiLocators := btcwire.NewMsgGetHeaders() - MultiLocators.ProtocolVersion = pver - MultiLocators.HashStop = *hashStop - MultiLocators.AddBlockLocatorHash(hashLocator2) - MultiLocators.AddBlockLocatorHash(hashLocator) - MultiLocatorsEncoded := []byte{ + multiLocators := btcwire.NewMsgGetHeaders() + multiLocators.ProtocolVersion = pver + multiLocators.HashStop = *hashStop + multiLocators.AddBlockLocatorHash(hashLocator2) + multiLocators.AddBlockLocatorHash(hashLocator) + multiLocatorsEncoded := []byte{ 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 0x02, // Varint for number of block locator hashes 0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63, @@ -137,81 +140,81 @@ func TestGetHeadersWire(t *testing.T) { }{ // Latest protocol version with no block locators. { - NoLocators, - NoLocators, - NoLocatorsEncoded, + noLocators, + noLocators, + noLocatorsEncoded, btcwire.ProtocolVersion, }, // Latest protocol version with multiple block locators. { - MultiLocators, - MultiLocators, - MultiLocatorsEncoded, + multiLocators, + multiLocators, + multiLocatorsEncoded, btcwire.ProtocolVersion, }, // Protocol version BIP0035Version with no block locators. { - NoLocators, - NoLocators, - NoLocatorsEncoded, + noLocators, + noLocators, + noLocatorsEncoded, btcwire.BIP0035Version, }, // Protocol version BIP0035Version with multiple block locators. { - MultiLocators, - MultiLocators, - MultiLocatorsEncoded, + multiLocators, + multiLocators, + multiLocatorsEncoded, btcwire.BIP0035Version, }, // Protocol version BIP0031Version with no block locators. { - NoLocators, - NoLocators, - NoLocatorsEncoded, + noLocators, + noLocators, + noLocatorsEncoded, btcwire.BIP0031Version, }, // Protocol version BIP0031Versionwith multiple block locators. { - MultiLocators, - MultiLocators, - MultiLocatorsEncoded, + multiLocators, + multiLocators, + multiLocatorsEncoded, btcwire.BIP0031Version, }, // Protocol version NetAddressTimeVersion with no block locators. { - NoLocators, - NoLocators, - NoLocatorsEncoded, + noLocators, + noLocators, + noLocatorsEncoded, btcwire.NetAddressTimeVersion, }, // Protocol version NetAddressTimeVersion multiple block locators. { - MultiLocators, - MultiLocators, - MultiLocatorsEncoded, + multiLocators, + multiLocators, + multiLocatorsEncoded, btcwire.NetAddressTimeVersion, }, // Protocol version MultipleAddressVersion with no block locators. { - NoLocators, - NoLocators, - NoLocatorsEncoded, + noLocators, + noLocators, + noLocatorsEncoded, btcwire.MultipleAddressVersion, }, // Protocol version MultipleAddressVersion multiple block locators. { - MultiLocators, - MultiLocators, - MultiLocatorsEncoded, + multiLocators, + multiLocators, + multiLocatorsEncoded, btcwire.MultipleAddressVersion, }, } @@ -246,3 +249,133 @@ func TestGetHeadersWire(t *testing.T) { } } } + +// TestGetHeadersWireErrors performs negative tests against wire encode and +// decode of MsgGetHeaders to confirm error paths work correctly. +func TestGetHeadersWireErrors(t *testing.T) { + // Set protocol inside getheaders message. Use protocol version 60002 + // specifically here instead of the latest because the test data is + // using bytes encoded with that protocol version. + pver := uint32(60002) + btcwireErr := &btcwire.MessageError{} + + // Block 99499 hash. + hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535" + hashLocator, err := btcwire.NewShaHashFromStr(hashStr) + if err != nil { + t.Errorf("NewShaHashFromStr: %v", err) + } + + // Block 99500 hash. + hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0" + hashLocator2, err := btcwire.NewShaHashFromStr(hashStr) + if err != nil { + t.Errorf("NewShaHashFromStr: %v", err) + } + + // Block 100000 hash. + hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" + hashStop, err := btcwire.NewShaHashFromStr(hashStr) + if err != nil { + t.Errorf("NewShaHashFromStr: %v", err) + } + + // MsgGetHeaders message with multiple block locators and a stop hash. + baseGetHeaders := btcwire.NewMsgGetHeaders() + baseGetHeaders.ProtocolVersion = pver + baseGetHeaders.HashStop = *hashStop + baseGetHeaders.AddBlockLocatorHash(hashLocator2) + baseGetHeaders.AddBlockLocatorHash(hashLocator) + baseGetHeadersEncoded := []byte{ + 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 + 0x02, // Varint for number of block locator hashes + 0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63, + 0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65, + 0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b, + 0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash + 0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60, + 0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9, + 0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40, + 0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash + 0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39, + 0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2, + 0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa, + 0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop + } + + // Message that forces an error by having more than the max allowed + // block locator hashes. + maxGetHeaders := btcwire.NewMsgGetHeaders() + for i := 0; i < btcwire.MaxBlockLocatorsPerMsg; i++ { + maxGetHeaders.AddBlockLocatorHash(&btcwire.GenesisHash) + } + maxGetHeaders.BlockLocatorHashes = append(maxGetHeaders.BlockLocatorHashes, + &btcwire.GenesisHash) + //maxGetHeaders.InvList = append(maxGetData.InvList, iv) + maxGetHeadersEncoded := []byte{ + 0x62, 0xea, 0x00, 0x00, // Protocol version 60002 + 0xfd, 0xf5, 0x01, // Varint for number of block loc hashes (501) + } + + tests := []struct { + in *btcwire.MsgGetHeaders // Value to encode + buf []byte // Wire encoding + pver uint32 // Protocol version for wire encoding + max int // Max size of fixed buffer to induce errors + writeErr error // Expected write error + readErr error // Expected read error + }{ + // Force error in protocol version. + {baseGetHeaders, baseGetHeadersEncoded, pver, 0, io.ErrShortWrite, io.EOF}, + // Force error in block locator hash count. + {baseGetHeaders, baseGetHeadersEncoded, pver, 4, io.ErrShortWrite, io.EOF}, + // Force error in block locator hashes. + {baseGetHeaders, baseGetHeadersEncoded, pver, 5, io.ErrShortWrite, io.EOF}, + // Force error in stop hash. + {baseGetHeaders, baseGetHeadersEncoded, pver, 69, io.ErrShortWrite, io.EOF}, + // Force error with greater than max block locator hashes. + {maxGetHeaders, maxGetHeadersEncoded, pver, 7, btcwireErr, btcwireErr}, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + // Encode to wire format. + w := newFixedWriter(test.max) + err := test.in.BtcEncode(w, test.pver) + if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) { + t.Errorf("BtcEncode #%d wrong error got: %v, want: %v", + i, err, test.writeErr) + continue + } + + // For errors which are not of type btcwire.MessageError, check + // them for equality. + if _, ok := err.(*btcwire.MessageError); !ok { + if err != test.writeErr { + t.Errorf("BtcEncode #%d wrong error got: %v, "+ + "want: %v", i, err, test.writeErr) + continue + } + } + + // Decode from wire format. + var msg btcwire.MsgGetHeaders + r := newFixedReader(test.max, test.buf) + err = msg.BtcDecode(r, test.pver) + if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) { + t.Errorf("BtcDecode #%d wrong error got: %v, want: %v", + i, err, test.readErr) + continue + } + + // For errors which are not of type btcwire.MessageError, check + // them for equality. + if _, ok := err.(*btcwire.MessageError); !ok { + if err != test.readErr { + t.Errorf("BtcEncode #%d wrong error got: %v, "+ + "want: %v", i, err, test.readErr) + continue + } + } + } +}