From bab06ce8fdb7ab263e90163f5a4bec6a726fdf07 Mon Sep 17 00:00:00 2001 From: Donald Adu-Poku Date: Fri, 14 Feb 2020 19:15:25 +0000 Subject: [PATCH] multi: define wire error types. This updates the wire error type by clearly defining package errors and updating call sites. --- wire/common.go | 30 +++--- wire/error.go | 213 +++++++++++++++++++++++++++++++++++++-- wire/error_test.go | 95 +++++++++++++++++ wire/fakemessage_test.go | 2 +- wire/message.go | 49 +++++---- wire/message_test.go | 21 +--- wire/msgaddr.go | 22 ++-- wire/msgblock.go | 20 ++-- wire/msgcfheaders.go | 32 +++--- wire/msgcfilter.go | 19 ++-- wire/msgcfilterv2.go | 30 +++--- wire/msgcftypes.go | 20 ++-- wire/msgfeefilter.go | 12 ++- wire/msggetblocks.go | 17 ++-- wire/msggetcfheaders.go | 25 +++-- wire/msggetcfilter.go | 12 ++- wire/msggetcfilterv2.go | 12 ++- wire/msggetcftypes.go | 12 ++- wire/msggetdata.go | 19 ++-- wire/msggetheaders.go | 18 ++-- wire/msgheaders.go | 24 +++-- wire/msginv.go | 19 ++-- wire/msgminingstate.go | 30 +++--- wire/msgnotfound.go | 17 ++-- wire/msgsendheaders.go | 12 ++- wire/msgtx.go | 52 +++++----- wire/msgversion.go | 11 +- 27 files changed, 583 insertions(+), 262 deletions(-) create mode 100644 wire/error_test.go diff --git a/wire/common.go b/wire/common.go index 91aaed06be..ae0c32d326 100644 --- a/wire/common.go +++ b/wire/common.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2016 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -174,8 +174,8 @@ var binarySerializer binaryFreeList = make(chan []byte, binaryFreeListMaxItems) // errNonCanonicalVarInt is the common format string used for non-canonically // encoded variable length integer errors. -var errNonCanonicalVarInt = "non-canonical varint %x - discriminant %x must " + - "encode a value greater than %x" +var nonCanonicalVarIntFormat = "non-canonical varint %x - discriminant " + + "%x must encode a value greater than %x" // uint32Time represents a unix timestamp encoded with a uint32. It is used as // a way to signal the readElement function how to decode a timestamp into a Go @@ -490,6 +490,7 @@ func writeElements(w io.Writer, elements ...interface{}) error { // ReadVarInt reads a variable length integer from r and returns it as a uint64. func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { + const op = "ReadVarInt" discriminant, err := binarySerializer.Uint8(r) if err != nil { return 0, err @@ -508,8 +509,8 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { // encoded using fewer bytes. min := uint64(0x100000000) if rv < min { - return 0, messageError("ReadVarInt", fmt.Sprintf( - errNonCanonicalVarInt, rv, discriminant, min)) + msg := fmt.Sprintf(nonCanonicalVarIntFormat, rv, discriminant, min) + return 0, messageError(op, ErrNonCanonicalVarInt, msg) } case 0xfe: @@ -523,8 +524,8 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { // encoded using fewer bytes. min := uint64(0x10000) if rv < min { - return 0, messageError("ReadVarInt", fmt.Sprintf( - errNonCanonicalVarInt, rv, discriminant, min)) + msg := fmt.Sprintf(nonCanonicalVarIntFormat, rv, discriminant, min) + return 0, messageError(op, ErrNonCanonicalVarInt, msg) } case 0xfd: @@ -538,8 +539,8 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { // encoded using fewer bytes. min := uint64(0xfd) if rv < min { - return 0, messageError("ReadVarInt", fmt.Sprintf( - errNonCanonicalVarInt, rv, discriminant, min)) + msg := fmt.Sprintf(nonCanonicalVarIntFormat, rv, discriminant, min) + return 0, messageError(op, ErrNonCanonicalVarInt, msg) } default: @@ -609,6 +610,7 @@ func VarIntSerializeSize(val uint64) int { // maximum block payload size since it helps protect against memory exhaustion // attacks and forced panics through malformed messages. func ReadVarString(r io.Reader, pver uint32) (string, error) { + const op = "ReadVarString" count, err := ReadVarInt(r, pver) if err != nil { return "", err @@ -618,9 +620,9 @@ func ReadVarString(r io.Reader, pver uint32) (string, error) { // message size. It would be possible to cause memory exhaustion and // panics without a sane upper bound on this count. if count > MaxMessagePayload { - str := fmt.Sprintf("variable length string is too long "+ + msg := fmt.Sprintf("variable length string is too long "+ "[count %d, max %d]", count, MaxMessagePayload) - return "", messageError("ReadVarString", str) + return "", messageError(op, ErrVarStringTooLong, msg) } buf := make([]byte, count) @@ -652,7 +654,7 @@ func WriteVarString(w io.Writer, pver uint32, str string) error { // the error. func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { - + const op = "ReadVarBytes" count, err := ReadVarInt(r, pver) if err != nil { return nil, err @@ -662,9 +664,9 @@ func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, // be possible to cause memory exhaustion and panics without a sane // upper bound on this count. if count > uint64(maxAllowed) { - str := fmt.Sprintf("%s is larger than the max allowed size "+ + msg := fmt.Sprintf("%s is larger than the max allowed size "+ "[count %d, max %d]", fieldName, count, maxAllowed) - return nil, messageError("ReadVarBytes", str) + return nil, messageError(op, ErrVarBytesTooLong, msg) } b := make([]byte, count) diff --git a/wire/error.go b/wire/error.go index 4d24e5e2c2..dd7336801d 100644 --- a/wire/error.go +++ b/wire/error.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2016 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -9,6 +9,174 @@ import ( "fmt" ) +// ErrorCode describes a kind of message error. +type ErrorCode int + +// These constants are used to identify a specific Error. +const ( + // ErrNonCanonicalVarInt is returned when a variable length integer is + // not canonically encoded. + ErrNonCanonicalVarInt ErrorCode = iota + 1 + + // ErrVarStringTooLong is returned when a variable string exceeds the + // maximum message size allowed. + ErrVarStringTooLong + + // ErrVarBytesTooLong is returned when a variable-length byte slice + // exceeds the maximum message size allowed. + ErrVarBytesTooLong + + // ErrCmdTooLong is returned when a command exceeds the maximum command + // size allowed. + ErrCmdTooLong + + // ErrPayloadTooLarge is returned when a payload exceeds the maximum + // payload size allowed. + ErrPayloadTooLarge + + // ErrWrongNetwork is returned when a message intended for a different + // network is received. + ErrWrongNetwork + + // ErrMalformedCmd is returned when a malformed command is received. + ErrMalformedCmd + + // ErrUnknownCmd is returned when an unknown command is received. + ErrUnknownCmd + + // ErrPayloadChecksum is returned when a message with an invalid checksum + // is received. + ErrPayloadChecksum + + // ErrTooManyAddrs is returned when an address list exceeds the maximum + // allowed. + ErrTooManyAddrs + + // ErrTooManyTxs is returned when a the number of transactions exceed the + // maximum allowed. + ErrTooManyTxs + + // ErrMsgInvalidForPVer is returned when a message is invalid for + // the expected protocol version. + ErrMsgInvalidForPVer + + // ErrFilterTooLarge is returned when a committed filter exceeds + // the maximum size allowed. + ErrFilterTooLarge + + // ErrTooManyProofs is returned when the numeber of proof hashes + // exceeds the maximum allowed. + ErrTooManyProofs + + // ErrTooManyFilterTypes is returned when the number of filter types + // exceeds the maximum allowed. + ErrTooManyFilterTypes + + // ErrTooManyLocators is returned when the number of block locators exceed + // the maximum allowed. + ErrTooManyLocators + + // ErrTooManyVectors is returned when the number of inventory vectors + // exceed the maximum allowed. + ErrTooManyVectors + + // ErrTooManyHeaders is returned when the number of block headers exceed + // the maximum allowed. + ErrTooManyHeaders + + // ErrHeaderContainsTxs is returned when a header's transactions + // count is greater than zero. + ErrHeaderContainsTxs + + // ErrTooManyVotes is returned when the number of vote hashes exceed the + // maximum allowed. + ErrTooManyVotes + + // ErrTooManyBlocks is returned when the number of block hashes exceed the + // maximum allowed. + ErrTooManyBlocks + + // ErrMismatchedWitnessCount returned when a transaction has unequal witness + // and prefix txin quantities. + ErrMismatchedWitnessCount + + // ErrUnknownTxType is returned when a transaction type is unknown. + ErrUnknownTxType + + // ErrReadInPrefixFromWitnessOnlyTx is returned when attempting to read a + // transaction input prefix from a witness only transaction. + ErrReadInPrefixFromWitnessOnlyTx + + // ErrInvalidMsg is returned when for an invalid message structure. + ErrInvalidMsg + + // ErrUserAgentTooLong is returned when the provided user agent exceeds + // the maximum allowed. + ErrUserAgentTooLong + + // ErrTooManyFilterHeaders is returned when the number of committed filter + // headers exceed the maximum allowed. + ErrTooManyFilterHeaders +) + +// Map of ErrorCode values back to their constant names for pretty printing. +var errorCodeStrings = map[ErrorCode]string{ + ErrNonCanonicalVarInt: "ErrNonCanonicalVarInt", + ErrVarStringTooLong: "ErrVarStringTooLong", + ErrVarBytesTooLong: "ErrVarBytesTooLong", + ErrCmdTooLong: "ErrCmdTooLong", + ErrPayloadTooLarge: "ErrPayloadTooLarge", + ErrWrongNetwork: "ErrWrongNetwork", + ErrMalformedCmd: "ErrMalformedCmd", + ErrUnknownCmd: "ErrUnknownCmd", + ErrPayloadChecksum: "ErrPayloadChecksum", + ErrTooManyAddrs: "ErrTooManyAddrs", + ErrTooManyTxs: "ErrTooManyTxs", + ErrMsgInvalidForPVer: "ErrMsgInvalidForPVer", + ErrFilterTooLarge: "ErrFilterTooLarge", + ErrTooManyProofs: "ErrTooManyProofs", + ErrTooManyFilterTypes: "ErrTooManyFilterTypes", + ErrTooManyLocators: "ErrTooManyLocators", + ErrTooManyVectors: "ErrTooManyVectors", + ErrTooManyHeaders: "ErrTooManyHeaders", + ErrHeaderContainsTxs: "ErrHeaderContainsTxs", + ErrTooManyVotes: "ErrTooManyVotes", + ErrTooManyBlocks: "ErrTooManyBlocks", + ErrMismatchedWitnessCount: "ErrMismatchedWitnessCount", + ErrUnknownTxType: "ErrUnknownTxType", + ErrReadInPrefixFromWitnessOnlyTx: "ErrReadInPrefixFromWitnessOnlyTx", + ErrInvalidMsg: "ErrInvalidMsg", + ErrUserAgentTooLong: "ErrUserAgentTooLong", + ErrTooManyFilterHeaders: "ErrTooManyFilterHeaders", +} + +// String returns the ErrorCode as a human-readable name. +func (e ErrorCode) String() string { + if s := errorCodeStrings[e]; s != "" { + return s + } + return fmt.Sprintf("Unknown ErrorCode (%d)", int(e)) +} + +// Error implements the error interface. +func (e ErrorCode) Error() string { + return e.String() +} + +// Is implements the interface to work with the standard library's errors.Is. +// It returns true if the error codes match for targets *MessageError and +// ErrorCode. Else, Is returns false. +func (e ErrorCode) Is(target error) bool { + switch target := target.(type) { + case *MessageError: + return e == target.ErrorCode + case ErrorCode: + return e == target + default: + return false + } +} + // MessageError describes an issue with a message. // An example of some potential issues are messages from the wrong decred // network, invalid commands, mismatched checksums, and exceeding max payloads. @@ -17,19 +185,44 @@ import ( // differentiate between general io errors such as io.EOF and issues that // resulted from malformed messages. type MessageError struct { - Func string // Function name - Description string // Human readable description of the issue + Func string // Function name + ErrorCode ErrorCode // Describes the kind of error + Description string // Human readable description of the issue } // Error satisfies the error interface and prints human-readable errors. -func (e *MessageError) Error() string { - if e.Func != "" { - return fmt.Sprintf("%v: %v", e.Func, e.Description) +func (m *MessageError) Error() string { + if m.Func != "" { + return fmt.Sprintf("%v: [%s] %v", m.Func, m.ErrorCode, m.Description) } - return e.Description + return fmt.Sprintf("%v: %v", m.ErrorCode, m.Description) } -// messageError creates an error for the given function and description. -func messageError(f string, desc string) *MessageError { - return &MessageError{Func: f, Description: desc} +// messageError creates an Error given a set of arguments. +func messageError(Func string, c ErrorCode, desc string) *MessageError { + return &MessageError{Func: Func, ErrorCode: c, Description: desc} +} + +// Is implements the interface to work with the standard library's errors.Is. +// If target is a *MessageError, Is returns true if the error codes match. +// If target is an ErrorCode, Is returns true if the error codes match. +// Else, Is returns false. +func (m *MessageError) Is(target error) bool { + switch target := target.(type) { + case *MessageError: + return m.ErrorCode != 0 && m.ErrorCode == target.ErrorCode + case ErrorCode: + return m.ErrorCode != 0 && target == m.ErrorCode + default: + return false + } +} + +// Unwrap returns the underlying wrapped error if it is not ErrOther. +// Unwrap returns the ErrorCode. Else, it returns nil. +func (m *MessageError) Unwrap() error { + if m.ErrorCode != 0 { + return m.ErrorCode + } + return nil } diff --git a/wire/error_test.go b/wire/error_test.go new file mode 100644 index 0000000000..c28655f209 --- /dev/null +++ b/wire/error_test.go @@ -0,0 +1,95 @@ +// Copyright (c) 2017 The btcsuite developers +// Copyright (c) 2015-2020 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "testing" +) + +// TestMessageErrorCodeStringer tests the stringized output for +// the ErrorCode type. +func TestMessageErrorCodeStringer(t *testing.T) { + t.Parallel() + + tests := []struct { + in ErrorCode + want string + }{ + {ErrNonCanonicalVarInt, "ErrNonCanonicalVarInt"}, + {ErrVarStringTooLong, "ErrVarStringTooLong"}, + {ErrVarBytesTooLong, "ErrVarBytesTooLong"}, + {ErrCmdTooLong, "ErrCmdTooLong"}, + {ErrPayloadTooLarge, "ErrPayloadTooLarge"}, + {ErrWrongNetwork, "ErrWrongNetwork"}, + {ErrMalformedCmd, "ErrMalformedCmd"}, + {ErrUnknownCmd, "ErrUnknownCmd"}, + {ErrPayloadChecksum, "ErrPayloadChecksum"}, + {ErrTooManyAddrs, "ErrTooManyAddrs"}, + {ErrTooManyTxs, "ErrTooManyTxs"}, + {ErrMsgInvalidForPVer, "ErrMsgInvalidForPVer"}, + {ErrFilterTooLarge, "ErrFilterTooLarge"}, + {ErrTooManyProofs, "ErrTooManyProofs"}, + {ErrTooManyFilterTypes, "ErrTooManyFilterTypes"}, + {ErrTooManyLocators, "ErrTooManyLocators"}, + {ErrTooManyVectors, "ErrTooManyVectors"}, + {ErrTooManyHeaders, "ErrTooManyHeaders"}, + {ErrHeaderContainsTxs, "ErrHeaderContainsTxs"}, + {ErrTooManyVotes, "ErrTooManyVotes"}, + {ErrTooManyBlocks, "ErrTooManyBlocks"}, + {ErrMismatchedWitnessCount, "ErrMismatchedWitnessCount"}, + {ErrUnknownTxType, "ErrUnknownTxType"}, + {ErrReadInPrefixFromWitnessOnlyTx, "ErrReadInPrefixFromWitnessOnlyTx"}, + {ErrInvalidMsg, "ErrInvalidMsg"}, + {ErrUserAgentTooLong, "ErrUserAgentTooLong"}, + {ErrTooManyFilterHeaders, "ErrTooManyFilterHeaders"}, + {0xffff, "Unknown ErrorCode (65535)"}, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + result := test.in.String() + if result != test.want { + t.Errorf("String #%d\n got: %s want: %s", i, result, + test.want) + continue + } + } +} + +// TestMessageError tests the error output for the MessageError type. +func TestMessageError(t *testing.T) { + t.Parallel() + + tests := []struct { + in MessageError + want string + }{{ + MessageError{Description: "some error"}, + "Unknown ErrorCode (0): some error", + }, { + MessageError{ErrorCode: ErrNonCanonicalVarInt, + Description: "human-readable error"}, + "ErrNonCanonicalVarInt: human-readable error", + }, { + MessageError{ErrorCode: ErrMsgInvalidForPVer, + Description: "something bad happened"}, + "ErrMsgInvalidForPVer: something bad happened", + }, { + MessageError{Func: "foo", ErrorCode: ErrMsgInvalidForPVer, + Description: "something bad happened"}, + "foo: [ErrMsgInvalidForPVer] something bad happened", + }} + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + result := test.in.Error() + if result != test.want { + t.Errorf("Error #%d\n got: %s want: %s", i, result, + test.want) + continue + } + } +} diff --git a/wire/fakemessage_test.go b/wire/fakemessage_test.go index a1abb92947..67f701d56d 100644 --- a/wire/fakemessage_test.go +++ b/wire/fakemessage_test.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2016 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. diff --git a/wire/message.go b/wire/message.go index b4af003cb4..deccade4f5 100644 --- a/wire/message.go +++ b/wire/message.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -221,15 +221,15 @@ func discardInput(r io.Reader, n uint32) { // information and returns the number of bytes written. This function is the // same as WriteMessage except it also returns the number of bytes written. func WriteMessageN(w io.Writer, msg Message, pver uint32, dcrnet CurrencyNet) (int, error) { + const op = "WriteMessage" totalBytes := 0 // Enforce max command size. var command [CommandSize]byte cmd := msg.Command() if len(cmd) > CommandSize { - str := fmt.Sprintf("command [%s] is too long [max %v]", - cmd, CommandSize) - return totalBytes, messageError("WriteMessage", str) + msg := fmt.Sprintf("command [%s] is too long [max %v]", cmd, CommandSize) + return totalBytes, messageError(op, ErrCmdTooLong, msg) } copy(command[:], []byte(cmd)) @@ -244,10 +244,10 @@ func WriteMessageN(w io.Writer, msg Message, pver uint32, dcrnet CurrencyNet) (i // Enforce maximum overall message payload. if lenp > MaxMessagePayload { - str := fmt.Sprintf("message payload is too large - encoded "+ + msg := fmt.Sprintf("message payload is too large - encoded "+ "%d bytes, but maximum message payload is %d bytes", lenp, MaxMessagePayload) - return totalBytes, messageError("WriteMessage", str) + return totalBytes, messageError(op, ErrPayloadTooLarge, msg) } // Enforce maximum message payload based on the message type. @@ -256,7 +256,7 @@ func WriteMessageN(w io.Writer, msg Message, pver uint32, dcrnet CurrencyNet) (i str := fmt.Sprintf("message payload is too large - encoded "+ "%d bytes, but maximum message payload size for "+ "messages of type [%s] is %d.", lenp, cmd, mpl) - return totalBytes, messageError("WriteMessage", str) + return totalBytes, messageError(op, ErrPayloadTooLarge, str) } // Create header for the message. @@ -301,6 +301,7 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, dcrnet CurrencyNet) err // message. This function is the same as ReadMessage except it also returns the // number of bytes read. func ReadMessageN(r io.Reader, pver uint32, dcrnet CurrencyNet) (int, Message, []byte, error) { + const op = "ReadMessage" totalBytes := 0 n, hdr, err := readMessageHeader(r) totalBytes += n @@ -310,33 +311,32 @@ func ReadMessageN(r io.Reader, pver uint32, dcrnet CurrencyNet) (int, Message, [ // Enforce maximum message payload. if hdr.length > MaxMessagePayload { - str := fmt.Sprintf("message payload is too large - header "+ - "indicates %d bytes, but max message payload is %d "+ - "bytes.", hdr.length, MaxMessagePayload) - return totalBytes, nil, nil, messageError("ReadMessage", str) + msg := fmt.Sprintf("message payload is too large - header "+ + "indicates %d bytes, but max message payload is %d bytes.", + hdr.length, MaxMessagePayload) + return totalBytes, nil, nil, messageError(op, ErrPayloadTooLarge, msg) } // Check for messages from the wrong Decred network. if hdr.magic != dcrnet { discardInput(r, hdr.length) - str := fmt.Sprintf("message from other network [%v]", hdr.magic) - return totalBytes, nil, nil, messageError("ReadMessage", str) + msg := fmt.Sprintf("message from other network [%v]", hdr.magic) + return totalBytes, nil, nil, messageError(op, ErrWrongNetwork, msg) } // Check for malformed commands. command := hdr.command if !utf8.ValidString(command) { discardInput(r, hdr.length) - str := fmt.Sprintf("invalid command %v", []byte(command)) - return totalBytes, nil, nil, messageError("ReadMessage", str) + msg := fmt.Sprintf("invalid command %v", []byte(command)) + return totalBytes, nil, nil, messageError(op, ErrMalformedCmd, msg) } // Create struct of appropriate message type based on the command. msg, err := makeEmptyMessage(command) if err != nil { discardInput(r, hdr.length) - return totalBytes, nil, nil, messageError("ReadMessage", - err.Error()) + return totalBytes, nil, nil, messageError(op, ErrUnknownCmd, err.Error()) } // Check for maximum length based on the message type as a malicious client @@ -345,10 +345,10 @@ func ReadMessageN(r io.Reader, pver uint32, dcrnet CurrencyNet) (int, Message, [ mpl := msg.MaxPayloadLength(pver) if hdr.length > mpl { discardInput(r, hdr.length) - str := fmt.Sprintf("payload exceeds max length - header "+ - "indicates %v bytes, but max payload size for "+ - "messages of type [%v] is %v.", hdr.length, command, mpl) - return totalBytes, nil, nil, messageError("ReadMessage", str) + msg := fmt.Sprintf("payload exceeds max length - header "+ + "indicates %v bytes, but max payload size for messages of "+ + "type [%v] is %v.", hdr.length, command, mpl) + return totalBytes, nil, nil, messageError(op, ErrPayloadTooLarge, msg) } // Read payload. @@ -362,10 +362,9 @@ func ReadMessageN(r io.Reader, pver uint32, dcrnet CurrencyNet) (int, Message, [ // Test checksum. checksum := chainhash.HashB(payload)[0:4] if !bytes.Equal(checksum, hdr.checksum[:]) { - str := fmt.Sprintf("payload checksum failed - header "+ - "indicates %v, but actual checksum is %v.", - hdr.checksum, checksum) - return totalBytes, nil, nil, messageError("ReadMessage", str) + msg := fmt.Sprintf("payload checksum failed - header indicates %v, "+ + "but actual checksum is %v.", hdr.checksum, checksum) + return totalBytes, nil, nil, messageError(op, ErrPayloadChecksum, msg) } // Unmarshal message. NOTE: This must be a *bytes.Buffer since the diff --git a/wire/message_test.go b/wire/message_test.go index 5a516aecb4..be3b2a0843 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2018 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -180,22 +180,6 @@ func TestReadMessageWireErrors(t *testing.T) { pver := ProtocolVersion dcrnet := MainNet - // Ensure message errors are as expected with no function specified. - wantErr := "something bad happened" - testErr := MessageError{Description: wantErr} - if testErr.Error() != wantErr { - t.Errorf("MessageError: wrong error - got %v, want %v", - testErr.Error(), wantErr) - } - - // Ensure message errors are as expected with a function specified. - wantFunc := "foo" - testErr = MessageError{Func: wantFunc, Description: wantErr} - if testErr.Error() != wantFunc+": "+wantErr { - t.Errorf("MessageError: wrong error - got %v, want %v", - testErr.Error(), wantErr) - } - // Wire encoded bytes for main and testnet networks magic identifiers. testNetBytes := makeHeader(TestNet3, "", 0, 0) @@ -446,8 +430,7 @@ func TestWriteMessageWireErrors(t *testing.T) { if _, ok := err.(*MessageError); !ok { if err != test.err { t.Errorf("ReadMessage #%d wrong error got: %v <%T>, "+ - "want: %v <%T>", i, err, err, - test.err, test.err) + "want: %v <%T>", i, err, err, test.err, test.err) continue } } diff --git a/wire/msgaddr.go b/wire/msgaddr.go index 91cfbdc432..0418a03ed2 100644 --- a/wire/msgaddr.go +++ b/wire/msgaddr.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -30,10 +30,10 @@ type MsgAddr struct { // AddAddress adds a known active peer to the message. func (msg *MsgAddr) AddAddress(na *NetAddress) error { + const op = "MsgAddr.AddAddress" if len(msg.AddrList)+1 > MaxAddrPerMsg { - str := fmt.Sprintf("too many addresses in message [max %v]", - MaxAddrPerMsg) - return messageError("MsgAddr.AddAddress", str) + msg := fmt.Sprintf("too many addresses in message [max %v]", MaxAddrPerMsg) + return messageError(op, ErrTooManyAddrs, msg) } msg.AddrList = append(msg.AddrList, na) @@ -59,6 +59,7 @@ func (msg *MsgAddr) ClearAddresses() { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgAddr) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgAddr.BtcDecode" count, err := ReadVarInt(r, pver) if err != nil { return err @@ -66,9 +67,9 @@ func (msg *MsgAddr) BtcDecode(r io.Reader, pver uint32) error { // Limit to max addresses per message. if count > MaxAddrPerMsg { - str := fmt.Sprintf("too many addresses for message "+ - "[count %v, max %v]", count, MaxAddrPerMsg) - return messageError("MsgAddr.BtcDecode", str) + msg := fmt.Sprintf("too many addresses for message [count %v, max %v]", + count, MaxAddrPerMsg) + return messageError(op, ErrTooManyAddrs, msg) } addrList := make([]NetAddress, count) @@ -87,13 +88,14 @@ func (msg *MsgAddr) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgAddr) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgAddr.BtcEncode" // Protocol versions before MultipleAddressVersion only allowed 1 address // per message. count := len(msg.AddrList) if count > MaxAddrPerMsg { - str := fmt.Sprintf("too many addresses for message "+ - "[count %v, max %v]", count, MaxAddrPerMsg) - return messageError("MsgAddr.BtcEncode", str) + msg := fmt.Sprintf("too many addresses for message [count %v, max %v]", + count, MaxAddrPerMsg) + return messageError(op, ErrTooManyAddrs, msg) } err := WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msgblock.go b/wire/msgblock.go index 5a3f31b17f..5952452813 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -83,6 +83,7 @@ func (msg *MsgBlock) ClearSTransactions() { // See Deserialize for decoding blocks stored to disk, such as in a database, as // opposed to decoding blocks from the wire. func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgBlock.BtcDecode" err := readBlockHeader(r, pver, &msg.Header) if err != nil { return err @@ -99,9 +100,9 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32) error { // a sane upper bound on this count. maxTxPerTree := MaxTxPerTxTree(pver) if txCount > maxTxPerTree { - str := fmt.Sprintf("too many transactions to fit into a block "+ + msg := fmt.Sprintf("too many transactions to fit into a block "+ "[count %d, max %d]", txCount, maxTxPerTree) - return messageError("MsgBlock.BtcDecode", str) + return messageError(op, ErrTooManyTxs, msg) } msg.Transactions = make([]*MsgTx, 0, txCount) @@ -123,9 +124,9 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32) error { return err } if stakeTxCount > maxTxPerTree { - str := fmt.Sprintf("too many stransactions to fit into a block "+ + msg := fmt.Sprintf("too many stransactions to fit into a block "+ "[count %d, max %d]", stakeTxCount, maxTxPerTree) - return messageError("MsgBlock.BtcDecode", str) + return messageError(op, ErrTooManyTxs, msg) } msg.STransactions = make([]*MsgTx, 0, stakeTxCount) @@ -168,6 +169,7 @@ func (msg *MsgBlock) FromBytes(b []byte) error { // start and length of each transaction within the raw data that is being // deserialized. func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, []TxLoc, error) { + const op = "MsgBlock.DeserializeTxLoc" fullLen := r.Len() // At the current time, there is no difference between the wire encoding @@ -190,9 +192,9 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, []TxLoc, error) // since it is in terms of the largest possible block size. maxTxPerTree := MaxTxPerTxTree(ProtocolVersion) if txCount > maxTxPerTree { - str := fmt.Sprintf("too many transactions to fit into a block "+ + msg := fmt.Sprintf("too many transactions to fit into a block "+ "[count %d, max %d]", txCount, maxTxPerTree) - return nil, nil, messageError("MsgBlock.DeserializeTxLoc", str) + return nil, nil, messageError(op, ErrTooManyTxs, msg) } // Deserialize each transaction while keeping track of its location @@ -222,9 +224,9 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, []TxLoc, error) // NOTE: This is using the constant for the latest protocol version // since it is in terms of the largest possible block size. if stakeTxCount > maxTxPerTree { - str := fmt.Sprintf("too many transactions to fit into a stake tx tree "+ + msg := fmt.Sprintf("too many transactions to fit into a stake tx tree "+ "[count %d, max %d]", stakeTxCount, maxTxPerTree) - return nil, nil, messageError("MsgBlock.DeserializeTxLoc", str) + return nil, nil, messageError(op, ErrTooManyTxs, msg) } // Deserialize each transaction while keeping track of its location diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 3f249834b1..cbf40f176a 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -1,6 +1,6 @@ // Copyright (c) 2017 The btcsuite developers // Copyright (c) 2017 The Lightning Network Developers -// Copyright (c) 2018-2019 The Decred developers +// Copyright (c) 2018-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -36,10 +36,11 @@ type MsgCFHeaders struct { // AddCFHeader adds a new committed filter header to the message. func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { + const op = "MsgCFHeaders.AddCFHeader" if len(msg.HeaderHashes)+1 > MaxCFHeadersPerMsg { - str := fmt.Sprintf("too many block headers in message [max %v]", + msg := fmt.Sprintf("too many block headers in message [max %v]", MaxBlockHeadersPerMsg) - return messageError("MsgCFHeaders.AddCFHeader", str) + return messageError(op, ErrTooManyHeaders, msg) } msg.HeaderHashes = append(msg.HeaderHashes, headerHash) @@ -49,10 +50,10 @@ func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { // BtcDecode decodes r using the wire protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgCFHeaders.BtcDecode" if pver < NodeCFVersion { - str := fmt.Sprintf("cfheaders message invalid for protocol "+ - "version %d", pver) - return messageError("MsgCFHeaders.BtcDecode", str) + msg := fmt.Sprintf("cfheaders message invalid for protocol version %d", pver) + return messageError(op, ErrMsgInvalidForPVer, msg) } // Read stop hash @@ -75,10 +76,9 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // Limit to max committed filter headers per message. if count > MaxCFHeadersPerMsg { - str := fmt.Sprintf("too many committed filter headers for "+ - "message [count %v, max %v]", count, - MaxBlockHeadersPerMsg) - return messageError("MsgCFHeaders.BtcDecode", str) + msg := fmt.Sprintf("too many committed filter headers for message "+ + "[count %v, max %v]", count, MaxBlockHeadersPerMsg) + return messageError(op, ErrTooManyFilterHeaders, msg) } // Create a contiguous slice of headers to deserialize into in order to @@ -99,10 +99,11 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the wire protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgCFHeaders.BtcEncode" if pver < NodeCFVersion { - str := fmt.Sprintf("cfheaders message invalid for protocol "+ + msg := fmt.Sprintf("cfheaders message invalid for protocol "+ "version %d", pver) - return messageError("MsgCFHeaders.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } // Write stop hash @@ -120,10 +121,9 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { // Limit to max committed headers per message. count := len(msg.HeaderHashes) if count > MaxCFHeadersPerMsg { - str := fmt.Sprintf("too many committed filter headers for "+ - "message [count %v, max %v]", count, - MaxBlockHeadersPerMsg) - return messageError("MsgCFHeaders.BtcEncode", str) + msg := fmt.Sprintf("too many committed filter headers for message "+ + "[count %v, max %v]", count, MaxBlockHeadersPerMsg) + return messageError(op, ErrTooManyFilterHeaders, msg) } err = WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index f2d95715a7..d54e2a4b72 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -1,6 +1,6 @@ // Copyright (c) 2017 The btcsuite developers // Copyright (c) 2017 The Lightning Network Developers -// Copyright (c) 2018 The Decred developers +// Copyright (c) 2018-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -31,10 +31,11 @@ type MsgCFilter struct { // BtcDecode decodes r using the wire protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgCFilter.BtcDecode" if pver < NodeCFVersion { - str := fmt.Sprintf("cfilter message invalid for protocol "+ + msg := fmt.Sprintf("cfilter message invalid for protocol "+ "version %d", pver) - return messageError("MsgCFilter.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } // Read the hash of the filter's block @@ -50,25 +51,25 @@ func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { } // Read filter data - msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, - "cfilter data") + msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, "cfilter data") return err } // BtcEncode encodes the receiver to w using the wire protocol encoding. This is // part of the Message interface implementation. func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgCFilter.BtcEncode" if pver < NodeCFVersion { - str := fmt.Sprintf("cfilter message invalid for protocol "+ + msg := fmt.Sprintf("cfilter message invalid for protocol "+ "version %d", pver) - return messageError("MsgCFilter.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } size := len(msg.Data) if size > MaxCFilterDataSize { - str := fmt.Sprintf("cfilter size too large for message "+ + msg := fmt.Sprintf("cfilter size too large for message "+ "[size %v, max %v]", size, MaxCFilterDataSize) - return messageError("MsgCFilter.BtcEncode", str) + return messageError(op, ErrFilterTooLarge, msg) } err := writeElement(w, &msg.BlockHash) diff --git a/wire/msgcfilterv2.go b/wire/msgcfilterv2.go index f5bbdf922e..1a2e9fcbeb 100644 --- a/wire/msgcfilterv2.go +++ b/wire/msgcfilterv2.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 The Decred developers +// Copyright (c) 2019-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -35,10 +35,11 @@ type MsgCFilterV2 struct { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFilterV2) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgCFilterV2.BtcDecode" if pver < CFilterV2Version { - str := fmt.Sprintf("%s message invalid for protocol version %d", + msg := fmt.Sprintf("%s message invalid for protocol version %d", msg.Command(), pver) - return messageError("MsgCFilterV2.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } err := readElement(r, &msg.BlockHash) @@ -62,9 +63,9 @@ func (msg *MsgCFilterV2) BtcDecode(r io.Reader, pver uint32) error { return err } if count > MaxHeaderProofHashes { - str := fmt.Sprintf("too many proof hashes for message [count %v, "+ - "max %v]", count, MaxHeaderProofHashes) - return messageError("MsgCFilterV2.BtcDecode", str) + msg := fmt.Sprintf("too many proof hashes for message "+ + "[count %v, max %v]", count, MaxHeaderProofHashes) + return messageError(op, ErrTooManyProofs, msg) } // Create a contiguous slice of hashes to deserialize into in order to @@ -83,24 +84,25 @@ func (msg *MsgCFilterV2) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFilterV2) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgCFilterV2.BtcEncode" if pver < CFilterV2Version { - str := fmt.Sprintf("%s message invalid for protocol version %d", + msg := fmt.Sprintf("%s message invalid for protocol version %d", msg.Command(), pver) - return messageError("MsgCFilterV2.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } size := len(msg.Data) if size > MaxCFilterDataSize { - str := fmt.Sprintf("filter size too large for message [size %v, "+ - "max %v]", size, MaxCFilterDataSize) - return messageError("MsgCFilterV2.BtcEncode", str) + msg := fmt.Sprintf("filter size too large for message "+ + "[size %v, max %v]", size, MaxCFilterDataSize) + return messageError(op, ErrFilterTooLarge, msg) } numHashes := len(msg.ProofHashes) if numHashes > MaxHeaderProofHashes { - str := fmt.Sprintf("too many proof hashes for message [count %v, "+ - "max %v]", numHashes, MaxHeaderProofHashes) - return messageError("MsgCFilterV2.BtcEncode", str) + msg := fmt.Sprintf("too many proof hashes for message "+ + "[count %v, max %v]", numHashes, MaxHeaderProofHashes) + return messageError(op, ErrTooManyProofs, msg) } err := writeElement(w, &msg.BlockHash) diff --git a/wire/msgcftypes.go b/wire/msgcftypes.go index 31a3415695..54d4ada8d7 100644 --- a/wire/msgcftypes.go +++ b/wire/msgcftypes.go @@ -1,6 +1,6 @@ // Copyright (c) 2017 The btcsuite developers // Copyright (c) 2017 The Lightning Network Developers -// Copyright (c) 2018-2019 The Decred developers +// Copyright (c) 2018-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -34,10 +34,11 @@ type MsgCFTypes struct { // BtcDecode decodes r using the wire protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgCFTypes.BtcDecode" if pver < NodeCFVersion { - str := fmt.Sprintf("cftypes message invalid for protocol "+ + msg := fmt.Sprintf("cftypes message invalid for protocol "+ "version %d", pver) - return messageError("MsgCFTypes.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } // Read the number of filter types supported. The count may not exceed the @@ -48,9 +49,9 @@ func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32) error { } if count > MaxFilterTypesPerMsg { - str := fmt.Sprintf("too many filter types for message "+ + msg := fmt.Sprintf("too many filter types for message "+ "[count %v, max %v]", count, MaxFilterTypesPerMsg) - return messageError("MsgCFTypes.BtcDecode", str) + return messageError(op, ErrTooManyFilterTypes, msg) } // Read each filter type. @@ -68,16 +69,17 @@ func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the wire protocol encoding. This is // part of the Message interface implementation. func (msg *MsgCFTypes) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgCFTypes.BtcEncode" if pver < NodeCFVersion { - str := fmt.Sprintf("cftypes message invalid for protocol "+ + msg := fmt.Sprintf("cftypes message invalid for protocol "+ "version %d", pver) - return messageError("MsgCFTypes.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } if len(msg.SupportedFilters) > MaxFilterTypesPerMsg { - str := fmt.Sprintf("too many filter types for message "+ + msg := fmt.Sprintf("too many filter types for message "+ "[count %v, max %v]", len(msg.SupportedFilters), MaxFilterTypesPerMsg) - return messageError("MsgCFTypes.BtcEncode", str) + return messageError(op, ErrTooManyFilterTypes, msg) } // Write length of supported filters slice. diff --git a/wire/msgfeefilter.go b/wire/msgfeefilter.go index 042cd665f1..963fa6a3a0 100644 --- a/wire/msgfeefilter.go +++ b/wire/msgfeefilter.go @@ -1,5 +1,5 @@ // Copyright (c) 2016 The btcsuite developers -// Copyright (c) 2017 The Decred developers +// Copyright (c) 2017-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -23,10 +23,11 @@ type MsgFeeFilter struct { // BtcDecode decodes r using the protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgFeeFilter) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgFeeFilter.BtcDecode" if pver < FeeFilterVersion { - str := fmt.Sprintf("feefilter message invalid for protocol "+ + msg := fmt.Sprintf("feefilter message invalid for protocol "+ "version %d", pver) - return messageError("MsgFeeFilter.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return readElement(r, &msg.MinFee) @@ -35,10 +36,11 @@ func (msg *MsgFeeFilter) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the protocol encoding. // This is part of the Message interface implementation. func (msg *MsgFeeFilter) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgFeeFilter.BtcEncode" if pver < FeeFilterVersion { - str := fmt.Sprintf("feefilter message invalid for protocol "+ + msg := fmt.Sprintf("feefilter message invalid for protocol "+ "version %d", pver) - return messageError("MsgFeeFilter.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return writeElement(w, msg.MinFee) diff --git a/wire/msggetblocks.go b/wire/msggetblocks.go index c984d7c20f..9d59966f03 100644 --- a/wire/msggetblocks.go +++ b/wire/msggetblocks.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -39,10 +39,11 @@ type MsgGetBlocks struct { // AddBlockLocatorHash adds a new block locator hash to the message. func (msg *MsgGetBlocks) AddBlockLocatorHash(hash *chainhash.Hash) error { + const op = "MsgGetBlocks.AddBlockLocatorHash" if len(msg.BlockLocatorHashes)+1 > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message [max %v]", + msg := fmt.Sprintf("too many block locator hashes for message [max %v]", MaxBlockLocatorsPerMsg) - return messageError("MsgGetBlocks.AddBlockLocatorHash", str) + return messageError(op, ErrTooManyLocators, msg) } msg.BlockLocatorHashes = append(msg.BlockLocatorHashes, hash) @@ -52,6 +53,7 @@ func (msg *MsgGetBlocks) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetBlocks.BtcDecode" err := readElement(r, &msg.ProtocolVersion) if err != nil { return err @@ -63,9 +65,9 @@ func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32) error { return err } if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ + msg := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetBlocks.BtcDecode", str) + return messageError(op, ErrTooManyLocators, msg) } // Create a contiguous slice of hashes to deserialize into in order to @@ -87,11 +89,12 @@ func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetBlocks) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetBlocks.BtcEncode" count := len(msg.BlockLocatorHashes) if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ + msg := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetBlocks.BtcEncode", str) + return messageError(op, ErrTooManyLocators, msg) } err := writeElement(w, msg.ProtocolVersion) diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index 2e3a3f6f42..09f35088e0 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -1,6 +1,6 @@ // Copyright (c) 2017 The btcsuite developers // Copyright (c) 2017 The Lightning Network Developers -// Copyright (c) 2018-2019 The Decred developers +// Copyright (c) 2018-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -24,10 +24,11 @@ type MsgGetCFHeaders struct { // AddBlockLocatorHash adds a new block locator hash to the message. func (msg *MsgGetCFHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { + const op = "MsgGetCFHeaders.AddBlockLocatorHash" if len(msg.BlockLocatorHashes)+1 > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message [max %v]", + msg := fmt.Sprintf("too many block locator hashes for message [max %v]", MaxBlockLocatorsPerMsg) - return messageError("MsgGetCFHeaders.AddBlockLocatorHash", str) + return messageError(op, ErrTooManyLocators, msg) } msg.BlockLocatorHashes = append(msg.BlockLocatorHashes, hash) @@ -37,10 +38,11 @@ func (msg *MsgGetCFHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the wire protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetCFHeaders.BtcDecode" if pver < NodeCFVersion { - str := fmt.Sprintf("getcfheaders message invalid for protocol "+ + msg := fmt.Sprintf("getcfheaders message invalid for protocol "+ "version %d", pver) - return messageError("MsgGetCFHeaders.BtcDecode", str) + return messageError(op, ErrTooManyAddrs, msg) } // Read num block locator hashes and limit to max. @@ -49,9 +51,9 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32) error { return err } if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ + msg := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetCFHeaders.BtcDecode", str) + return messageError(op, ErrTooManyLocators, msg) } // Create a contiguous slice of hashes to deserialize into in order to @@ -78,18 +80,19 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the wire protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetCFHeaders.BtcEncode" if pver < NodeCFVersion { - str := fmt.Sprintf("getcfheaders message invalid for protocol "+ + msg := fmt.Sprintf("getcfheaders message invalid for protocol "+ "version %d", pver) - return messageError("MsgGetCFHeaders.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } // Limit to max block locator hashes per message. count := len(msg.BlockLocatorHashes) if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ + msg := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetCFHeaders.BtcEncode", str) + return messageError(op, ErrTooManyLocators, msg) } err := WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 85a11343c3..5411f7a758 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -1,6 +1,6 @@ // Copyright (c) 2017 The btcsuite developers // Copyright (c) 2017 The Lightning Network Developers -// Copyright (c) 2018 The Decred developers +// Copyright (c) 2018-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -23,10 +23,11 @@ type MsgGetCFilter struct { // BtcDecode decodes r using the wire protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetCFilter.BtcDecode" if pver < NodeCFVersion { - str := fmt.Sprintf("getcfilter message invalid for protocol "+ + msg := fmt.Sprintf("getcfilter message invalid for protocol "+ "version %d", pver) - return messageError("MsgGetCFilter.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } err := readElement(r, &msg.BlockHash) @@ -39,10 +40,11 @@ func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the wire protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetCFilter.BtcEncode" if pver < NodeCFVersion { - str := fmt.Sprintf("getcfilter message invalid for protocol "+ + msg := fmt.Sprintf("getcfilter message invalid for protocol "+ "version %d", pver) - return messageError("MsgGetCFilter.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } err := writeElement(w, &msg.BlockHash) diff --git a/wire/msggetcfilterv2.go b/wire/msggetcfilterv2.go index fbe86ffa83..b465e30552 100644 --- a/wire/msggetcfilterv2.go +++ b/wire/msggetcfilterv2.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 The Decred developers +// Copyright (c) 2019-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -24,10 +24,11 @@ type MsgGetCFilterV2 struct { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFilterV2) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetCFilterV2.BtcDecode" if pver < CFilterV2Version { - str := fmt.Sprintf("%s message invalid for protocol version %d", + msg := fmt.Sprintf("%s message invalid for protocol version %d", msg.Command(), pver) - return messageError("MsgGetCFilterV2.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return readElement(r, &msg.BlockHash) @@ -36,10 +37,11 @@ func (msg *MsgGetCFilterV2) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFilterV2) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetCFilterV2.BtcEncode" if pver < CFilterV2Version { - str := fmt.Sprintf("%s message invalid for protocol version %d", + msg := fmt.Sprintf("%s message invalid for protocol version %d", msg.Command(), pver) - return messageError("MsgGetCFilterV2.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return writeElement(w, &msg.BlockHash) diff --git a/wire/msggetcftypes.go b/wire/msggetcftypes.go index 8fe89e5788..2516b05cf5 100644 --- a/wire/msggetcftypes.go +++ b/wire/msggetcftypes.go @@ -1,6 +1,6 @@ // Copyright (c) 2017 The btcsuite developers // Copyright (c) 2017 The Lightning Network Developers -// Copyright (c) 2018 The Decred developers +// Copyright (c) 2018-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -17,10 +17,11 @@ type MsgGetCFTypes struct{} // BtcDecode decodes the receiver from w using the wire protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFTypes) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetCFTypes.BtcDecode" if pver < NodeCFVersion { - str := fmt.Sprintf("getcftypes message invalid for protocol "+ + msg := fmt.Sprintf("getcftypes message invalid for protocol "+ "version %d", pver) - return messageError("MsgGetCFTypes.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return nil @@ -29,10 +30,11 @@ func (msg *MsgGetCFTypes) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the wire protocol encoding. This is // part of the Message interface implementation. func (msg *MsgGetCFTypes) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetCFTypes.BtcEncode" if pver < NodeCFVersion { - str := fmt.Sprintf("getcftypes message invalid for protocol "+ + msg := fmt.Sprintf("getcftypes message invalid for protocol "+ "version %d", pver) - return messageError("MsgGetCFTypes.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return nil diff --git a/wire/msggetdata.go b/wire/msggetdata.go index 2c691186dc..a83ee62f43 100644 --- a/wire/msggetdata.go +++ b/wire/msggetdata.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -26,10 +26,10 @@ type MsgGetData struct { // AddInvVect adds an inventory vector to the message. func (msg *MsgGetData) AddInvVect(iv *InvVect) error { + const op = "MsgGetData.AddInvVect" if len(msg.InvList)+1 > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [max %v]", - MaxInvPerMsg) - return messageError("MsgGetData.AddInvVect", str) + msg := fmt.Sprintf("too many invvect in message [max %v]", MaxInvPerMsg) + return messageError(op, ErrTooManyVectors, msg) } msg.InvList = append(msg.InvList, iv) @@ -39,6 +39,7 @@ func (msg *MsgGetData) AddInvVect(iv *InvVect) error { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetData.BtcDecode" count, err := ReadVarInt(r, pver) if err != nil { return err @@ -46,8 +47,8 @@ func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32) error { // Limit to max inventory vectors per message. if count > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [%v]", count) - return messageError("MsgGetData.BtcDecode", str) + msg := fmt.Sprintf("too many invvect in message [%v]", count) + return messageError(op, ErrTooManyVectors, msg) } // Create a contiguous slice of inventory vectors to deserialize into in @@ -69,11 +70,13 @@ func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetData) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetData.BtcEncode" + // Limit to max inventory vectors per message. count := len(msg.InvList) if count > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [%v]", count) - return messageError("MsgGetData.BtcEncode", str) + msg := fmt.Sprintf("too many invvect in message [%v]", count) + return messageError(op, ErrTooManyVectors, msg) } err := WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msggetheaders.go b/wire/msggetheaders.go index 0eb2b6373c..00da96d6a1 100644 --- a/wire/msggetheaders.go +++ b/wire/msggetheaders.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -36,10 +36,11 @@ type MsgGetHeaders struct { // AddBlockLocatorHash adds a new block locator hash to the message. func (msg *MsgGetHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { + const op = "MsgGetHeaders.AddBlockLocatorHash" if len(msg.BlockLocatorHashes)+1 > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message [max %v]", + msg := fmt.Sprintf("too many block locator hashes for message [max %v]", MaxBlockLocatorsPerMsg) - return messageError("MsgGetHeaders.AddBlockLocatorHash", str) + return messageError(op, ErrTooManyLocators, msg) } msg.BlockLocatorHashes = append(msg.BlockLocatorHashes, hash) @@ -49,6 +50,7 @@ func (msg *MsgGetHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgGetHeaders.BtcDecode" err := readElement(r, &msg.ProtocolVersion) if err != nil { return err @@ -60,9 +62,9 @@ func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32) error { return err } if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ + msg := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetHeaders.BtcDecode", str) + return messageError(op, ErrTooManyLocators, msg) } // Create a contiguous slice of hashes to deserialize into in order to @@ -84,12 +86,14 @@ func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetHeaders) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgGetHeaders.BtcEncode" + // Limit to max block locator hashes per message. count := len(msg.BlockLocatorHashes) if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ + msg := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetHeaders.BtcEncode", str) + return messageError(op, ErrTooManyLocators, msg) } err := writeElement(w, msg.ProtocolVersion) diff --git a/wire/msgheaders.go b/wire/msgheaders.go index edabcbf2b3..77463303d0 100644 --- a/wire/msgheaders.go +++ b/wire/msgheaders.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -25,10 +25,11 @@ type MsgHeaders struct { // AddBlockHeader adds a new block header to the message. func (msg *MsgHeaders) AddBlockHeader(bh *BlockHeader) error { + const op = "MsgHeaders.AddBlockHeader" if len(msg.Headers)+1 > MaxBlockHeadersPerMsg { - str := fmt.Sprintf("too many block headers in message [max %v]", + msg := fmt.Sprintf("too many block headers in message [max %v]", MaxBlockHeadersPerMsg) - return messageError("MsgHeaders.AddBlockHeader", str) + return messageError(op, ErrTooManyHeaders, msg) } msg.Headers = append(msg.Headers, bh) @@ -38,6 +39,7 @@ func (msg *MsgHeaders) AddBlockHeader(bh *BlockHeader) error { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgHeaders.BtcDecode" count, err := ReadVarInt(r, pver) if err != nil { return err @@ -45,9 +47,9 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32) error { // Limit to max block headers per message. if count > MaxBlockHeadersPerMsg { - str := fmt.Sprintf("too many block headers for message "+ + msg := fmt.Sprintf("too many block headers for message "+ "[count %v, max %v]", count, MaxBlockHeadersPerMsg) - return messageError("MsgHeaders.BtcDecode", str) + return messageError(op, ErrTooManyHeaders, msg) } // Create a contiguous slice of headers to deserialize into in order to @@ -68,9 +70,9 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32) error { // Ensure the transaction count is zero for headers. if txCount > 0 { - str := fmt.Sprintf("block headers may not contain "+ - "transactions [count %v]", txCount) - return messageError("MsgHeaders.BtcDecode", str) + msg := fmt.Sprintf("block headers may not contain transactions "+ + "[count %v]", txCount) + return messageError(op, ErrHeaderContainsTxs, msg) } msg.AddBlockHeader(bh) } @@ -81,12 +83,14 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgHeaders.BtcEncode" + // Limit to max block headers per message. count := len(msg.Headers) if count > MaxBlockHeadersPerMsg { - str := fmt.Sprintf("too many block headers for message "+ + msg := fmt.Sprintf("too many block headers for message "+ "[count %v, max %v]", count, MaxBlockHeadersPerMsg) - return messageError("MsgHeaders.BtcEncode", str) + return messageError(op, ErrTooManyHeaders, msg) } err := WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msginv.go b/wire/msginv.go index 357013a6b7..2264e1e170 100644 --- a/wire/msginv.go +++ b/wire/msginv.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -34,10 +34,10 @@ type MsgInv struct { // AddInvVect adds an inventory vector to the message. func (msg *MsgInv) AddInvVect(iv *InvVect) error { + const op = "MsgInv.AddInvVect" if len(msg.InvList)+1 > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [max %v]", - MaxInvPerMsg) - return messageError("MsgInv.AddInvVect", str) + msg := fmt.Sprintf("too many invvect in message [max %v]", MaxInvPerMsg) + return messageError(op, ErrTooManyVectors, msg) } msg.InvList = append(msg.InvList, iv) @@ -47,6 +47,7 @@ func (msg *MsgInv) AddInvVect(iv *InvVect) error { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgInv.BtcDecode" count, err := ReadVarInt(r, pver) if err != nil { return err @@ -54,8 +55,8 @@ func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32) error { // Limit to max inventory vectors per message. if count > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [%v]", count) - return messageError("MsgInv.BtcDecode", str) + msg := fmt.Sprintf("too many invvect in message [%v]", count) + return messageError(op, ErrTooManyVectors, msg) } // Create a contiguous slice of inventory vectors to deserialize into in @@ -77,11 +78,13 @@ func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgInv) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgInv.BtcEncode" + // Limit to max inventory vectors per message. count := len(msg.InvList) if count > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [%v]", count) - return messageError("MsgInv.BtcEncode", str) + msg := fmt.Sprintf("too many invvect in message [%v]", count) + return messageError(op, ErrTooManyVectors, msg) } err := WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msgminingstate.go b/wire/msgminingstate.go index 33730a5a95..0b28fa5648 100644 --- a/wire/msgminingstate.go +++ b/wire/msgminingstate.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -33,10 +33,11 @@ type MsgMiningState struct { // AddBlockHash adds a new block hash to the message. func (msg *MsgMiningState) AddBlockHash(hash *chainhash.Hash) error { + const op = "MsgMiningState.AddBlockHash" if len(msg.BlockHashes)+1 > MaxMSBlocksAtHeadPerMsg { - str := fmt.Sprintf("too many block hashes for message [max %v]", + msg := fmt.Sprintf("too many block hashes for message [max %v]", MaxMSBlocksAtHeadPerMsg) - return messageError("MsgMiningState.AddBlockHash", str) + return messageError(op, ErrTooManyHeaders, msg) } msg.BlockHashes = append(msg.BlockHashes, hash) @@ -45,10 +46,11 @@ func (msg *MsgMiningState) AddBlockHash(hash *chainhash.Hash) error { // AddVoteHash adds a new vote hash to the message. func (msg *MsgMiningState) AddVoteHash(hash *chainhash.Hash) error { + const op = "MsgMiningState.AddVoteHash" if len(msg.VoteHashes)+1 > MaxMSVotesAtHeadPerMsg { - str := fmt.Sprintf("too many vote hashes for message [max %v]", + msg := fmt.Sprintf("too many vote hashes for message [max %v]", MaxMSVotesAtHeadPerMsg) - return messageError("MsgMiningState.AddVoteHash", str) + return messageError(op, ErrTooManyVotes, msg) } msg.VoteHashes = append(msg.VoteHashes, hash) @@ -58,6 +60,7 @@ func (msg *MsgMiningState) AddVoteHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgMiningState) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgMiningState.BtcDecode" err := readElement(r, &msg.Version) if err != nil { return err @@ -74,9 +77,9 @@ func (msg *MsgMiningState) BtcDecode(r io.Reader, pver uint32) error { return err } if count > MaxMSBlocksAtHeadPerMsg { - str := fmt.Sprintf("too many block hashes for message "+ + msg := fmt.Sprintf("too many block hashes for message "+ "[count %v, max %v]", count, MaxMSBlocksAtHeadPerMsg) - return messageError("MsgMiningState.BtcDecode", str) + return messageError(op, ErrTooManyBlocks, msg) } msg.BlockHashes = make([]*chainhash.Hash, 0, count) @@ -95,9 +98,9 @@ func (msg *MsgMiningState) BtcDecode(r io.Reader, pver uint32) error { return err } if count > MaxMSVotesAtHeadPerMsg { - str := fmt.Sprintf("too many vote hashes for message "+ + msg := fmt.Sprintf("too many vote hashes for message "+ "[count %v, max %v]", count, MaxMSVotesAtHeadPerMsg) - return messageError("MsgMiningState.BtcDecode", str) + return messageError(op, ErrTooManyVotes, msg) } msg.VoteHashes = make([]*chainhash.Hash, 0, count) @@ -119,6 +122,7 @@ func (msg *MsgMiningState) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the protocol encoding. // This is part of the Message interface implementation. func (msg *MsgMiningState) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgMiningState.BtcEncode" err := writeElement(w, msg.Version) if err != nil { return err @@ -132,9 +136,9 @@ func (msg *MsgMiningState) BtcEncode(w io.Writer, pver uint32) error { // Write block hashes. count := len(msg.BlockHashes) if count > MaxMSBlocksAtHeadPerMsg { - str := fmt.Sprintf("too many block hashes for message "+ + msg := fmt.Sprintf("too many block hashes for message "+ "[count %v, max %v]", count, MaxMSBlocksAtHeadPerMsg) - return messageError("MsgMiningState.BtcEncode", str) + return messageError(op, ErrTooManyBlocks, msg) } err = WriteVarInt(w, pver, uint64(count)) @@ -152,9 +156,9 @@ func (msg *MsgMiningState) BtcEncode(w io.Writer, pver uint32) error { // Write vote hashes. count = len(msg.VoteHashes) if count > MaxMSVotesAtHeadPerMsg { - str := fmt.Sprintf("too many vote hashes for message "+ + msg := fmt.Sprintf("too many vote hashes for message "+ "[count %v, max %v]", count, MaxMSVotesAtHeadPerMsg) - return messageError("MsgMiningState.BtcEncode", str) + return messageError(op, ErrTooManyVotes, msg) } err = WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msgnotfound.go b/wire/msgnotfound.go index cc5d737880..289dff5e78 100644 --- a/wire/msgnotfound.go +++ b/wire/msgnotfound.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2015 The btcsuite developers -// Copyright (c) 2015-2019 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -23,10 +23,11 @@ type MsgNotFound struct { // AddInvVect adds an inventory vector to the message. func (msg *MsgNotFound) AddInvVect(iv *InvVect) error { + const op = "MsgNotFound.AddInvVect" if len(msg.InvList)+1 > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [max %v]", + msg := fmt.Sprintf("too many invvect in message [max %v]", MaxInvPerMsg) - return messageError("MsgNotFound.AddInvVect", str) + return messageError(op, ErrTooManyVectors, msg) } msg.InvList = append(msg.InvList, iv) @@ -36,6 +37,7 @@ func (msg *MsgNotFound) AddInvVect(iv *InvVect) error { // BtcDecode decodes r using the Decred protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgNotFound.BtcDecode" count, err := ReadVarInt(r, pver) if err != nil { return err @@ -43,8 +45,8 @@ func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32) error { // Limit to max inventory vectors per message. if count > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [%v]", count) - return messageError("MsgNotFound.BtcDecode", str) + msg := fmt.Sprintf("too many invvect in message [%v]", count) + return messageError(op, ErrTooManyVectors, msg) } // Create a contiguous slice of inventory vectors to deserialize into in @@ -66,11 +68,12 @@ func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the Decred protocol encoding. // This is part of the Message interface implementation. func (msg *MsgNotFound) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgNotFound.BtcEncode" // Limit to max inventory vectors per message. count := len(msg.InvList) if count > MaxInvPerMsg { - str := fmt.Sprintf("too many invvect in message [%v]", count) - return messageError("MsgNotFound.BtcEncode", str) + msg := fmt.Sprintf("too many invvect in message [%v]", count) + return messageError(op, ErrTooManyVectors, msg) } err := WriteVarInt(w, pver, uint64(count)) diff --git a/wire/msgsendheaders.go b/wire/msgsendheaders.go index 5021852bcd..7788491e22 100644 --- a/wire/msgsendheaders.go +++ b/wire/msgsendheaders.go @@ -1,5 +1,5 @@ // Copyright (c) 2016 The btcsuite developers -// Copyright (c) 2016 The Decred developers +// Copyright (c) 2016-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -21,10 +21,11 @@ type MsgSendHeaders struct{} // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgSendHeaders) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgSendHeaders.BtcDecode" if pver < SendHeadersVersion { - str := fmt.Sprintf("sendheaders message invalid for protocol "+ + msg := fmt.Sprintf("sendheaders message invalid for protocol "+ "version %d", pver) - return messageError("MsgSendHeaders.BtcDecode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return nil @@ -33,10 +34,11 @@ func (msg *MsgSendHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgSendHeaders) BtcEncode(w io.Writer, pver uint32) error { + const op = "MsgSendHeaders.BtcEncode" if pver < SendHeadersVersion { - str := fmt.Sprintf("sendheaders message invalid for protocol "+ + msg := fmt.Sprintf("sendheaders message invalid for protocol "+ "version %d", pver) - return messageError("MsgSendHeaders.BtcEncode", str) + return messageError(op, ErrMsgInvalidForPVer, msg) } return nil diff --git a/wire/msgtx.go b/wire/msgtx.go index d26d38350b..f7a62b90b4 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -215,6 +215,7 @@ var scriptPool scriptFreeList = make(chan []byte, freeListMaxItems) // fieldName parameter is only used for the error message so it provides more // context in the error. func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { + const op = "readScript" count, err := ReadVarInt(r, pver) if err != nil { return nil, err @@ -224,9 +225,9 @@ func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ( // be possible to cause memory exhaustion and panics without a sane // upper bound on this count. if count > uint64(maxAllowed) { - str := fmt.Sprintf("%s is larger than the max allowed size "+ + msg := fmt.Sprintf("%s is larger than the max allowed size "+ "[count %d, max %d]", fieldName, count, maxAllowed) - return nil, messageError("readScript", str) + return nil, messageError(op, ErrVarBytesTooLong, msg) } b := scriptPool.Borrow(count) @@ -595,6 +596,7 @@ func writeTxScriptsToMsgTx(msg *MsgTx, totalScriptSize uint64, serType TxSeriali // decodePrefix decodes a transaction prefix and stores the contents // in the embedded msgTx. func (msg *MsgTx) decodePrefix(r io.Reader, pver uint32) (uint64, error) { + const op = "MsgTx.decodePrefix" count, err := ReadVarInt(r, pver) if err != nil { return 0, err @@ -604,10 +606,9 @@ func (msg *MsgTx) decodePrefix(r io.Reader, pver uint32) (uint64, error) { // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if count > uint64(maxTxInPerMessage) { - str := fmt.Sprintf("too many input transactions to fit into "+ - "max message size [count %d, max %d]", count, - maxTxInPerMessage) - return 0, messageError("MsgTx.decodePrefix", str) + msg := fmt.Sprintf("too many input transactions to fit into max "+ + "message size [count %d, max %d]", count, maxTxInPerMessage) + return 0, messageError(op, ErrTooManyTxs, msg) } // TxIns. @@ -633,10 +634,9 @@ func (msg *MsgTx) decodePrefix(r io.Reader, pver uint32) (uint64, error) { // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if count > uint64(maxTxOutPerMessage) { - str := fmt.Sprintf("too many output transactions to fit into "+ - "max message size [count %d, max %d]", count, - maxTxOutPerMessage) - return 0, messageError("MsgTx.decodePrefix", str) + msg := fmt.Sprintf("too many output transactions to fit into "+ + "max message size [count %d, max %d]", count, maxTxOutPerMessage) + return 0, messageError(op, ErrTooManyTxs, msg) } // TxOuts. @@ -670,6 +670,8 @@ func (msg *MsgTx) decodePrefix(r io.Reader, pver uint32) (uint64, error) { } func (msg *MsgTx) decodeWitness(r io.Reader, pver uint32, isFull bool) (uint64, error) { + const op = "MsgTx.decodeWitness" + // Witness only; generate the TxIn list and fill out only the // sigScripts. var totalScriptSize uint64 @@ -684,9 +686,8 @@ func (msg *MsgTx) decodeWitness(r io.Reader, pver uint32, isFull bool) (uint64, // without a sane upper bound on this count. if count > uint64(maxTxInPerMessage) { str := fmt.Sprintf("too many input transactions to fit into "+ - "max message size [count %d, max %d]", count, - maxTxInPerMessage) - return 0, messageError("MsgTx.decodeWitness", str) + "max message size [count %d, max %d]", count, maxTxInPerMessage) + return 0, messageError(op, ErrTooManyTxs, str) } txIns := make([]TxIn, count) @@ -716,20 +717,18 @@ func (msg *MsgTx) decodeWitness(r io.Reader, pver uint32, isFull bool) (uint64, // Don't allow the deserializer to panic by accessing memory // that doesn't exist. if int(count) != len(msg.TxIn) { - str := fmt.Sprintf("non equal witness and prefix txin quantities "+ - "(witness %v, prefix %v)", count, - len(msg.TxIn)) - return 0, messageError("MsgTx.decodeWitness", str) + msg := fmt.Sprintf("non equal witness and prefix txin quantities "+ + "(witness %v, prefix %v)", count, len(msg.TxIn)) + return 0, messageError(op, ErrMismatchedWitnessCount, msg) } // Prevent more input transactions than could possibly fit into a // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if count > uint64(maxTxInPerMessage) { - str := fmt.Sprintf("too many input transactions to fit into "+ - "max message size [count %d, max %d]", count, - maxTxInPerMessage) - return 0, messageError("MsgTx.decodeWitness", str) + msg := fmt.Sprintf("too many input transactions to fit into "+ + "max message size [count %d, max %d]", count, maxTxInPerMessage) + return 0, messageError(op, ErrTooManyTxs, msg) } // Read in the witnesses, and copy them into the already generated @@ -758,6 +757,8 @@ func (msg *MsgTx) decodeWitness(r io.Reader, pver uint32, isFull bool) (uint64, // See Deserialize for decoding transactions stored to disk, such as in a // database, as opposed to decoding transactions from the wire. func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgTx.BtcDecode" + // The serialized encoding of the version includes the real transaction // version in the lower 16 bits and the transaction serialization type // in the upper 16 bits. @@ -826,7 +827,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error { totalScriptSizeOuts, txSerType) default: - return messageError("MsgTx.BtcDecode", "unsupported transaction type") + return messageError(op, ErrUnknownTxType, "unsupported transaction type") } return nil @@ -947,7 +948,8 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { } default: - return messageError("MsgTx.BtcEncode", "unsupported transaction type") + return messageError("MsgTx.BtcEncode", ErrUnknownTxType, + "unsupported transaction type") } return nil @@ -1154,7 +1156,7 @@ func WriteOutPoint(w io.Writer, pver uint32, version uint16, op *OutPoint) error // (TxIn) in the transaction prefix. func readTxInPrefix(r io.Reader, pver uint32, serType TxSerializeType, version uint16, ti *TxIn) error { if serType == TxSerializeOnlyWitness { - return messageError("readTxInPrefix", + return messageError("readTxInPrefix", ErrReadInPrefixFromWitnessOnlyTx, "tried to read a prefix input for a witness only tx") } diff --git a/wire/msgversion.go b/wire/msgversion.go index 7a81ef25c6..b11b25e8ae 100644 --- a/wire/msgversion.go +++ b/wire/msgversion.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers +// Copyright (c) 2015-2020 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -79,10 +79,10 @@ func (msg *MsgVersion) AddService(service ServiceFlag) { // // This is part of the Message interface implementation. func (msg *MsgVersion) BtcDecode(r io.Reader, pver uint32) error { + const op = "MsgVersion.BtcDecode" buf, ok := r.(*bytes.Buffer) if !ok { - return fmt.Errorf("in method MsgVersion.BtcDecode reader is not a " + - "*bytes.Buffer") + return messageError(op, ErrInvalidMsg, "reader is not a *bytes.Buffer") } err := readElements(buf, &msg.ProtocolVersion, &msg.Services, @@ -254,10 +254,11 @@ func NewMsgVersionFromConn(conn net.Conn, nonce uint64, // validateUserAgent checks userAgent length against MaxUserAgentLen func validateUserAgent(userAgent string) error { + const op = "MsgVersion.validateUserAgent" if len(userAgent) > MaxUserAgentLen { - str := fmt.Sprintf("user agent too long [len %v, max %v]", + msg := fmt.Sprintf("user agent too long [len %v, max %v]", len(userAgent), MaxUserAgentLen) - return messageError("MsgVersion", str) + return messageError(op, ErrUserAgentTooLong, msg) } return nil }