diff --git a/internal_test.go b/internal_test.go index 686bdb7ea..c2fce9c5e 100644 --- a/internal_test.go +++ b/internal_test.go @@ -115,7 +115,7 @@ func TstWriteBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error { // TstReadMessageHeader makes the internal readMessageHeader function available // to the test package. -func TstReadMessageHeader(r io.Reader) (*messageHeader, error) { +func TstReadMessageHeader(r io.Reader) (int, *messageHeader, error) { return readMessageHeader(r) } diff --git a/message.go b/message.go index 32e813b80..985617348 100644 --- a/message.go +++ b/message.go @@ -11,6 +11,11 @@ import ( "unicode/utf8" ) +// MessageHeaderSize is the number of bytes in a bitcoin message header. +// Bitcoin network (magic) 4 bytes + command 12 bytes + payload length 4 bytes + +// checksum 4 bytes. +const MessageHeaderSize = 24 + // commandSize is the fixed size of all commands in the common bitcoin message // header. Shorter commands must be zero padded. const commandSize = 12 @@ -118,19 +123,27 @@ type messageHeader struct { } // readMessageHeader reads a bitcoin message header from r. -func readMessageHeader(r io.Reader) (*messageHeader, error) { - var command [commandSize]byte - - hdr := messageHeader{} - err := readElements(r, &hdr.magic, &command, &hdr.length, &hdr.checksum) +func readMessageHeader(r io.Reader) (int, *messageHeader, error) { + // Since readElements doesn't return the amount of bytes read, attempt + // to read the entire header into a buffer first in case there is a + // short read so the proper amount of read bytes are known. This works + // since the header is a fixed size. + headerBytes := make([]byte, MessageHeaderSize) + n, err := io.ReadFull(r, headerBytes) if err != nil { - return nil, err + return n, nil, err } + hr := bytes.NewBuffer(headerBytes) + + // Create and populate a messageHeader struct from the raw header bytes. + hdr := messageHeader{} + var command [commandSize]byte + readElements(hr, &hdr.magic, &command, &hdr.length, &hdr.checksum) // Strip trailing zeros from command string. hdr.command = string(bytes.TrimRight(command[:], string(0))) - return &hdr, nil + return n, &hdr, nil } // discardInput reads n bytes from reader r in chunks and discards the read @@ -153,17 +166,19 @@ func discardInput(r io.Reader, n uint32) { } } -// WriteMessage writes a bitcoin Message to w including the necessary header -// information. -func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) error { - var command [commandSize]byte +// WriteMessageN writes a bitcoin Message to w including the necessary header +// 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, btcnet BitcoinNet) (int, error) { + 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 messageError("WriteMessage", str) + return totalBytes, messageError("WriteMessage", str) } copy(command[:], []byte(cmd)) @@ -171,7 +186,7 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro var bw bytes.Buffer err := msg.BtcEncode(&bw, pver) if err != nil { - return err + return totalBytes, err } payload := bw.Bytes() lenp := len(payload) @@ -181,7 +196,7 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro str := fmt.Sprintf("message payload is too large - encoded "+ "%d bytes, but maximum message payload is %d bytes", lenp, maxMessagePayload) - return messageError("WriteMessage", str) + return totalBytes, messageError("WriteMessage", str) } // Enforce maximum message payload based on the message type. @@ -190,7 +205,7 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro 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 messageError("WriteMessage", str) + return totalBytes, messageError("WriteMessage", str) } // Create header for the message. @@ -200,34 +215,61 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro hdr.length = uint32(lenp) copy(hdr.checksum[:], DoubleSha256(payload)[0:4]) + // Encode the header for the message. This is done to a buffer + // rather than directly to the writer since writeElements doesn't + // return the number of bytes written. + var hw bytes.Buffer + writeElements(&hw, hdr.magic, command, hdr.length, hdr.checksum) + // Write header. - err = writeElements(w, hdr.magic, command, hdr.length, hdr.checksum) + n, err := w.Write(hw.Bytes()) if err != nil { - return err + totalBytes += n + return totalBytes, err } + totalBytes += n // Write payload. - _, err = w.Write(payload) + n, err = w.Write(payload) if err != nil { - return err + totalBytes += n + return totalBytes, err } - return nil + totalBytes += n + + return totalBytes, nil } -// ReadMessage reads, validates, and parses the next bitcoin Message from r for -// the provided protocol version and bitcoin network. -func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, error) { - hdr, err := readMessageHeader(r) +// WriteMessage writes a bitcoin Message to w including the necessary header +// information. This function is the same as WriteMessageN except it doesn't +// doesn't return the number of bytes written. This function is mainly provided +// for backwards compatibility with the original API, but it's also useful for +// callers that don't care about byte counts. +func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) error { + _, err := WriteMessageN(w, msg, pver, btcnet) + return err +} + +// ReadMessageN reads, validates, and parses the next bitcoin Message from r for +// the provided protocol version and bitcoin network. It returns the number of +// bytes read in addition to the parsed Message and raw bytes which comprise the +// message. This function is the same as ReadMessage except it also returns the +// number of bytes read. +func ReadMessageN(r io.Reader, pver uint32, btcnet BitcoinNet) (int, Message, []byte, error) { + totalBytes := 0 + n, hdr, err := readMessageHeader(r) if err != nil { - return nil, nil, err + totalBytes += n + return totalBytes, nil, nil, err } + totalBytes += n // 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 nil, nil, messageError("ReadMessage", str) + return totalBytes, nil, nil, messageError("ReadMessage", str) } @@ -235,7 +277,7 @@ func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, if hdr.magic != btcnet { discardInput(r, hdr.length) str := fmt.Sprintf("message from other network [%v]", hdr.magic) - return nil, nil, messageError("ReadMessage", str) + return totalBytes, nil, nil, messageError("ReadMessage", str) } // Check for malformed commands. @@ -243,14 +285,15 @@ func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, if !utf8.ValidString(command) { discardInput(r, hdr.length) str := fmt.Sprintf("invalid command %v", []byte(command)) - return nil, nil, messageError("ReadMessage", str) + return totalBytes, nil, nil, messageError("ReadMessage", str) } // Create struct of appropriate message type based on the command. msg, err := makeEmptyMessage(command) if err != nil { discardInput(r, hdr.length) - return nil, nil, messageError("ReadMessage", err.Error()) + return totalBytes, nil, nil, messageError("ReadMessage", + err.Error()) } // Check for maximum length based on the message type as a malicious client @@ -262,15 +305,17 @@ func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, 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 nil, nil, messageError("ReadMessage", str) + return totalBytes, nil, nil, messageError("ReadMessage", str) } // Read payload. payload := make([]byte, hdr.length) - _, err = io.ReadFull(r, payload) + n, err = io.ReadFull(r, payload) if err != nil { - return nil, nil, err + totalBytes += n + return totalBytes, nil, nil, err } + totalBytes += n // Test checksum. checksum := DoubleSha256(payload)[0:4] @@ -278,15 +323,26 @@ func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, str := fmt.Sprintf("payload checksum failed - header "+ "indicates %v, but actual checksum is %v.", hdr.checksum, checksum) - return nil, nil, messageError("ReadMessage", str) + return totalBytes, nil, nil, messageError("ReadMessage", str) } // Unmarshal message. pr := bytes.NewBuffer(payload) err = msg.BtcDecode(pr, pver) if err != nil { - return nil, nil, err + return totalBytes, nil, nil, err } - return msg, payload, nil + return totalBytes, msg, payload, nil +} + +// ReadMessage reads, validates, and parses the next bitcoin Message from r for +// the provided protocol version and bitcoin network. It returns the parsed +// Message and raw bytes which comprise the message. This function only differs +// from ReadMessageN in that it doesn't return the number of bytes read. This +// function is mainly provided for backwards compatibility with the original +// API, but it's also useful for callers that don't care about byte counts. +func ReadMessage(r io.Reader, pver uint32, btcnet BitcoinNet) (Message, []byte, error) { + _, msg, buf, err := ReadMessageN(r, pver, btcnet) + return msg, buf, err } diff --git a/message_test.go b/message_test.go index be29e7ef7..ba5428911 100644 --- a/message_test.go +++ b/message_test.go @@ -32,7 +32,7 @@ func makeHeader(btcnet btcwire.BitcoinNet, command string, return buf } -// TestMessage tests the Read/WriteMessage API. +// TestMessage tests the Read/WriteMessage and Read/WriteMessageN API. func TestMessage(t *testing.T) { pver := btcwire.ProtocolVersion @@ -74,25 +74,65 @@ func TestMessage(t *testing.T) { out btcwire.Message // Expected decoded value pver uint32 // Protocol version for wire encoding btcnet btcwire.BitcoinNet // Network to use for wire encoding + bytes int // Expected num bytes read/written }{ - {msgVersion, msgVersion, pver, btcwire.MainNet}, - {msgVerack, msgVerack, pver, btcwire.MainNet}, - {msgGetAddr, msgGetAddr, pver, btcwire.MainNet}, - {msgAddr, msgAddr, pver, btcwire.MainNet}, - {msgGetBlocks, msgGetBlocks, pver, btcwire.MainNet}, - {msgBlock, msgBlock, pver, btcwire.MainNet}, - {msgInv, msgInv, pver, btcwire.MainNet}, - {msgGetData, msgGetData, pver, btcwire.MainNet}, - {msgNotFound, msgNotFound, pver, btcwire.MainNet}, - {msgTx, msgTx, pver, btcwire.MainNet}, - {msgPing, msgPing, pver, btcwire.MainNet}, - {msgPong, msgPong, pver, btcwire.MainNet}, - {msgGetHeaders, msgGetHeaders, pver, btcwire.MainNet}, - {msgHeaders, msgHeaders, pver, btcwire.MainNet}, - {msgAlert, msgAlert, pver, btcwire.MainNet}, - {msgMemPool, msgMemPool, pver, btcwire.MainNet}, + {msgVersion, msgVersion, pver, btcwire.MainNet, 121}, + {msgVerack, msgVerack, pver, btcwire.MainNet, 24}, + {msgGetAddr, msgGetAddr, pver, btcwire.MainNet, 24}, + {msgAddr, msgAddr, pver, btcwire.MainNet, 25}, + {msgGetBlocks, msgGetBlocks, pver, btcwire.MainNet, 61}, + {msgBlock, msgBlock, pver, btcwire.MainNet, 239}, + {msgInv, msgInv, pver, btcwire.MainNet, 25}, + {msgGetData, msgGetData, pver, btcwire.MainNet, 25}, + {msgNotFound, msgNotFound, pver, btcwire.MainNet, 25}, + {msgTx, msgTx, pver, btcwire.MainNet, 34}, + {msgPing, msgPing, pver, btcwire.MainNet, 32}, + {msgPong, msgPong, pver, btcwire.MainNet, 32}, + {msgGetHeaders, msgGetHeaders, pver, btcwire.MainNet, 61}, + {msgHeaders, msgHeaders, pver, btcwire.MainNet, 25}, + {msgAlert, msgAlert, pver, btcwire.MainNet, 42}, + {msgMemPool, msgMemPool, pver, btcwire.MainNet, 24}, } + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + // Encode to wire format. + var buf bytes.Buffer + nw, err := btcwire.WriteMessageN(&buf, test.in, test.pver, test.btcnet) + if err != nil { + t.Errorf("WriteMessage #%d error %v", i, err) + continue + } + + // Ensure the number of bytes written match the expected value. + if nw != test.bytes { + t.Errorf("WriteMessage #%d unexpected num bytes "+ + "written - got %d, want %d", i, nw, test.bytes) + } + + // Decode from wire format. + rbuf := bytes.NewBuffer(buf.Bytes()) + nr, msg, _, err := btcwire.ReadMessageN(rbuf, test.pver, test.btcnet) + if err != nil { + t.Errorf("ReadMessage #%d error %v, msg %v", i, err, + spew.Sdump(msg)) + continue + } + if !reflect.DeepEqual(msg, test.out) { + t.Errorf("ReadMessage #%d\n got: %v want: %v", i, + spew.Sdump(msg), spew.Sdump(test.out)) + continue + } + + // Ensure the number of bytes read match the expected value. + if nr != test.bytes { + t.Errorf("ReadMessage #%d unexpected num bytes read - "+ + "got %d, want %d", i, nr, test.bytes) + } + } + + // Do the same thing for Read/WriteMessage, but ignore the bytes since + // they don't return them. t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode to wire format. @@ -186,6 +226,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet btcwire.BitcoinNet // Bitcoin network for wire encoding max int // Max size of fixed buffer to induce errors readErr error // Expected read error + bytes int // Expected num bytes read }{ // Latest protocol version with intentional read errors. @@ -196,6 +237,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, 0, io.EOF, + 0, }, // Wrong network. Want MainNet, but giving TestNet3. @@ -205,6 +247,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(testNet3Bytes), &btcwire.MessageError{}, + 24, }, // Exceed max overall message payload length. @@ -214,6 +257,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(exceedMaxPayloadBytes), &btcwire.MessageError{}, + 24, }, // Invalid UTF-8 command. @@ -223,6 +267,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(badCommandBytes), &btcwire.MessageError{}, + 24, }, // Valid, but unsupported command. @@ -232,6 +277,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(unsupportedCommandBytes), &btcwire.MessageError{}, + 24, }, // Exceed max allowed payload for a message of a specific type. @@ -241,6 +287,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(exceedTypePayloadBytes), &btcwire.MessageError{}, + 24, }, // Message with a payload shorter than the header indicates. @@ -250,6 +297,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(shortPayloadBytes), io.EOF, + 24, }, // Message with a bad checksum. @@ -259,6 +307,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(badChecksumBytes), &btcwire.MessageError{}, + 26, }, // Message with a valid header, but wrong format. @@ -268,6 +317,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(badMessageBytes), io.EOF, + 25, }, // 15k bytes of data to discard. @@ -277,6 +327,7 @@ func TestReadMessageWireErrors(t *testing.T) { btcnet, len(discardBytes), &btcwire.MessageError{}, + 24, }, } @@ -284,13 +335,19 @@ func TestReadMessageWireErrors(t *testing.T) { for i, test := range tests { // Decode from wire format. r := newFixedReader(test.max, test.buf) - _, _, err := btcwire.ReadMessage(r, test.pver, test.btcnet) + nr, _, _, err := btcwire.ReadMessageN(r, test.pver, test.btcnet) if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) { t.Errorf("ReadMessage #%d wrong error got: %v <%T>, "+ "want: %T", i, err, err, test.readErr) continue } + // Ensure the number of bytes written match the expected value. + if nr != test.bytes { + t.Errorf("ReadMessage #%d unexpected num bytes read - "+ + "got %d, want %d", i, nr, test.bytes) + } + // For errors which are not of type btcwire.MessageError, check // them for equality. if _, ok := err.(*btcwire.MessageError); !ok { @@ -336,32 +393,39 @@ func TestWriteMessageWireErrors(t *testing.T) { btcnet btcwire.BitcoinNet // Bitcoin network for wire encoding max int // Max size of fixed buffer to induce errors err error // Expected error + bytes int // Expected num bytes written }{ // Command too long. - {badCommandMsg, pver, btcnet, 0, btcwireErr}, + {badCommandMsg, pver, btcnet, 0, btcwireErr, 0}, // Force error in payload encode. - {encodeErrMsg, pver, btcnet, 0, btcwireErr}, + {encodeErrMsg, pver, btcnet, 0, btcwireErr, 0}, // Force error due to exceeding max overall message payload size. - {exceedOverallPayloadErrMsg, pver, btcnet, 0, btcwireErr}, + {exceedOverallPayloadErrMsg, pver, btcnet, 0, btcwireErr, 0}, // Force error due to exceeding max payload for message type. - {exceedPayloadErrMsg, pver, btcnet, 0, btcwireErr}, + {exceedPayloadErrMsg, pver, btcnet, 0, btcwireErr, 0}, // Force error in header write. - {bogusMsg, pver, btcnet, 0, io.ErrShortWrite}, + {bogusMsg, pver, btcnet, 0, io.ErrShortWrite, 0}, // Force error in payload write. - {bogusMsg, pver, btcnet, 24, io.ErrShortWrite}, + {bogusMsg, pver, btcnet, 24, io.ErrShortWrite, 24}, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode wire format. w := newFixedWriter(test.max) - err := btcwire.WriteMessage(w, test.msg, test.pver, test.btcnet) + nw, err := btcwire.WriteMessageN(w, test.msg, test.pver, test.btcnet) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { t.Errorf("WriteMessage #%d wrong error got: %v <%T>, "+ "want: %T", i, err, err, test.err) continue } + // Ensure the number of bytes written match the expected value. + if nw != test.bytes { + t.Errorf("WriteMessage #%d unexpected num bytes "+ + "written - got %d, want %d", i, nw, test.bytes) + } + // For errors which are not of type btcwire.MessageError, check // them for equality. if _, ok := err.(*btcwire.MessageError); !ok { diff --git a/test_coverage.txt b/test_coverage.txt index 0df2bc761..6b9fac8bd 100644 --- a/test_coverage.txt +++ b/test_coverage.txt @@ -1,111 +1,107 @@ -github.com/conformal/btcwire/common.go readElement 100.00% (61/61) github.com/conformal/btcwire/common.go writeElement 100.00% (61/61) -github.com/conformal/btcwire/message.go ReadMessage 100.00% (37/37) +github.com/conformal/btcwire/common.go readElement 100.00% (61/61) +github.com/conformal/btcwire/message.go ReadMessageN 100.00% (42/42) +github.com/conformal/btcwire/message.go WriteMessageN 100.00% (38/38) github.com/conformal/btcwire/msgtx.go MsgTx.BtcDecode 100.00% (36/36) -github.com/conformal/btcwire/message.go WriteMessage 100.00% (31/31) github.com/conformal/btcwire/msgtx.go MsgTx.BtcEncode 100.00% (26/26) github.com/conformal/btcwire/msgversion.go MsgVersion.BtcDecode 100.00% (25/25) github.com/conformal/btcwire/msgtx.go MsgTx.Copy 100.00% (24/24) -github.com/conformal/btcwire/msgversion.go MsgVersion.BtcEncode 100.00% (22/22) github.com/conformal/btcwire/msgtx.go readTxIn 100.00% (22/22) +github.com/conformal/btcwire/msgversion.go MsgVersion.BtcEncode 100.00% (22/22) +github.com/conformal/btcwire/msgblock.go MsgBlock.DeserializeTxLoc 100.00% (21/21) github.com/conformal/btcwire/common.go readVarInt 100.00% (21/21) github.com/conformal/btcwire/netaddress.go readNetAddress 100.00% (20/20) -github.com/conformal/btcwire/common.go writeVarInt 100.00% (20/20) -github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.BtcDecode 100.00% (20/20) -github.com/conformal/btcwire/message.go makeEmptyMessage 100.00% (20/20) github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.BtcDecode 100.00% (20/20) -github.com/conformal/btcwire/msgblock.go MsgBlock.DeserializeTxLoc 100.00% (19/19) +github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.BtcDecode 100.00% (20/20) +github.com/conformal/btcwire/common.go writeVarInt 100.00% (20/20) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.BtcDecode 100.00% (20/20) +github.com/conformal/btcwire/message.go makeEmptyMessage 100.00% (20/20) github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.BtcEncode 100.00% (18/18) github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.BtcEncode 100.00% (18/18) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.BtcDecode 100.00% (17/17) github.com/conformal/btcwire/msgtx.go readTxOut 100.00% (17/17) +github.com/conformal/btcwire/msgblock.go MsgBlock.BtcDecode 100.00% (17/17) github.com/conformal/btcwire/msgtx.go writeTxIn 100.00% (16/16) -github.com/conformal/btcwire/msgblock.go MsgBlock.BtcDecode 100.00% (15/15) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.BtcEncode 100.00% (15/15) github.com/conformal/btcwire/msgaddr.go MsgAddr.BtcEncode 100.00% (15/15) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.BtcEncode 100.00% (15/15) github.com/conformal/btcwire/shahash.go NewShaHashFromStr 100.00% (15/15) -github.com/conformal/btcwire/msginv.go MsgInv.BtcDecode 100.00% (14/14) -github.com/conformal/btcwire/netaddress.go writeNetAddress 100.00% (14/14) github.com/conformal/btcwire/msgaddr.go MsgAddr.BtcDecode 100.00% (14/14) -github.com/conformal/btcwire/msgnotfound.go MsgNotFound.BtcDecode 100.00% (14/14) +github.com/conformal/btcwire/netaddress.go writeNetAddress 100.00% (14/14) github.com/conformal/btcwire/msggetdata.go MsgGetData.BtcDecode 100.00% (14/14) +github.com/conformal/btcwire/msgnotfound.go MsgNotFound.BtcDecode 100.00% (14/14) +github.com/conformal/btcwire/msginv.go MsgInv.BtcDecode 100.00% (14/14) github.com/conformal/btcwire/msgtx.go writeTxOut 100.00% (13/13) -github.com/conformal/btcwire/msggetdata.go MsgGetData.BtcEncode 100.00% (12/12) -github.com/conformal/btcwire/protocol.go ServiceFlag.String 100.00% (12/12) -github.com/conformal/btcwire/msginv.go MsgInv.BtcEncode 100.00% (12/12) github.com/conformal/btcwire/msgnotfound.go MsgNotFound.BtcEncode 100.00% (12/12) +github.com/conformal/btcwire/msggetdata.go MsgGetData.BtcEncode 100.00% (12/12) +github.com/conformal/btcwire/msginv.go MsgInv.BtcEncode 100.00% (12/12) +github.com/conformal/btcwire/protocol.go ServiceFlag.String 100.00% (12/12) github.com/conformal/btcwire/common.go readVarString 100.00% (11/11) +github.com/conformal/btcwire/msgblock.go MsgBlock.BtcEncode 100.00% (11/11) github.com/conformal/btcwire/message.go discardInput 100.00% (10/10) -github.com/conformal/btcwire/blockheader.go readBlockHeader 100.00% (10/10) -github.com/conformal/btcwire/msgtx.go readOutPoint 100.00% (9/9) -github.com/conformal/btcwire/msgblock.go MsgBlock.BtcEncode 100.00% (9/9) +github.com/conformal/btcwire/message.go readMessageHeader 100.00% (10/10) github.com/conformal/btcwire/msgtx.go writeOutPoint 100.00% (9/9) -github.com/conformal/btcwire/msgalert.go MsgAlert.BtcEncode 100.00% (8/8) +github.com/conformal/btcwire/msgtx.go readOutPoint 100.00% (9/9) github.com/conformal/btcwire/msgalert.go MsgAlert.BtcDecode 100.00% (8/8) -github.com/conformal/btcwire/blockheader.go writeBlockHeader 100.00% (8/8) -github.com/conformal/btcwire/msgpong.go MsgPong.BtcEncode 100.00% (7/7) -github.com/conformal/btcwire/message.go readMessageHeader 100.00% (7/7) -github.com/conformal/btcwire/common.go randomUint64 100.00% (7/7) +github.com/conformal/btcwire/msgalert.go MsgAlert.BtcEncode 100.00% (8/8) github.com/conformal/btcwire/common.go writeVarString 100.00% (7/7) +github.com/conformal/btcwire/common.go randomUint64 100.00% (7/7) +github.com/conformal/btcwire/msgversion.go NewMsgVersionFromConn 100.00% (7/7) +github.com/conformal/btcwire/msgpong.go MsgPong.BtcEncode 100.00% (7/7) github.com/conformal/btcwire/msgpong.go MsgPong.BtcDecode 100.00% (7/7) github.com/conformal/btcwire/common.go varIntSerializeSize 100.00% (7/7) -github.com/conformal/btcwire/msgversion.go NewMsgVersionFromConn 100.00% (7/7) +github.com/conformal/btcwire/blockheader.go readBlockHeader 100.00% (6/6) github.com/conformal/btcwire/common.go DoubleSha256 100.00% (6/6) github.com/conformal/btcwire/msgtx.go MsgTx.SerializeSize 100.00% (6/6) -github.com/conformal/btcwire/shahash.go ShaHash.SetBytes 100.00% (5/5) -github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.AddBlockLocatorHash 100.00% (5/5) -github.com/conformal/btcwire/msgnotfound.go MsgNotFound.AddInvVect 100.00% (5/5) -github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.AddBlockLocatorHash 100.00% (5/5) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.AddBlockHeader 100.00% (5/5) -github.com/conformal/btcwire/common.go writeElements 100.00% (5/5) -github.com/conformal/btcwire/msgping.go MsgPing.BtcEncode 100.00% (5/5) -github.com/conformal/btcwire/common.go readElements 100.00% (5/5) -github.com/conformal/btcwire/msggetdata.go MsgGetData.AddInvVect 100.00% (5/5) -github.com/conformal/btcwire/shahash.go NewShaHash 100.00% (5/5) -github.com/conformal/btcwire/msginv.go MsgInv.AddInvVect 100.00% (5/5) -github.com/conformal/btcwire/netaddress.go NewNetAddress 100.00% (5/5) github.com/conformal/btcwire/blockheader.go BlockHeader.BlockSha 100.00% (5/5) -github.com/conformal/btcwire/msgtx.go MsgTx.TxSha 100.00% (5/5) -github.com/conformal/btcwire/msgblock.go MsgBlock.TxShas 100.00% (5/5) +github.com/conformal/btcwire/blockheader.go writeBlockHeader 100.00% (5/5) +github.com/conformal/btcwire/common.go readElements 100.00% (5/5) +github.com/conformal/btcwire/common.go writeElements 100.00% (5/5) github.com/conformal/btcwire/msgaddr.go MsgAddr.AddAddress 100.00% (5/5) github.com/conformal/btcwire/msgaddr.go MsgAddr.AddAddresses 100.00% (5/5) +github.com/conformal/btcwire/msgblock.go MsgBlock.TxShas 100.00% (5/5) +github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.AddBlockLocatorHash 100.00% (5/5) +github.com/conformal/btcwire/msggetdata.go MsgGetData.AddInvVect 100.00% (5/5) +github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.AddBlockLocatorHash 100.00% (5/5) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.AddBlockHeader 100.00% (5/5) +github.com/conformal/btcwire/msginv.go MsgInv.AddInvVect 100.00% (5/5) +github.com/conformal/btcwire/msgnotfound.go MsgNotFound.AddInvVect 100.00% (5/5) github.com/conformal/btcwire/msgping.go MsgPing.BtcDecode 100.00% (5/5) -github.com/conformal/btcwire/invvect.go readInvVect 100.00% (4/4) -github.com/conformal/btcwire/invvect.go writeInvVect 100.00% (4/4) -github.com/conformal/btcwire/msgmempool.go MsgMemPool.BtcDecode 100.00% (4/4) -github.com/conformal/btcwire/msgmempool.go MsgMemPool.BtcEncode 100.00% (4/4) -github.com/conformal/btcwire/msgping.go MsgPing.MaxPayloadLength 100.00% (4/4) +github.com/conformal/btcwire/msgping.go MsgPing.BtcEncode 100.00% (5/5) +github.com/conformal/btcwire/msgtx.go MsgTx.TxSha 100.00% (5/5) +github.com/conformal/btcwire/netaddress.go NewNetAddress 100.00% (5/5) +github.com/conformal/btcwire/shahash.go ShaHash.SetBytes 100.00% (5/5) +github.com/conformal/btcwire/shahash.go NewShaHash 100.00% (5/5) github.com/conformal/btcwire/msgpong.go MsgPong.MaxPayloadLength 100.00% (4/4) -github.com/conformal/btcwire/netaddress.go maxNetAddressPayload 100.00% (4/4) +github.com/conformal/btcwire/msgmempool.go MsgMemPool.BtcEncode 100.00% (4/4) +github.com/conformal/btcwire/invvect.go readInvVect 100.00% (4/4) github.com/conformal/btcwire/shahash.go ShaHash.String 100.00% (4/4) -github.com/conformal/btcwire/msggetdata.go NewMsgGetDataSizeHint 100.00% (3/3) -github.com/conformal/btcwire/netaddress.go NetAddress.HasService 100.00% (3/3) -github.com/conformal/btcwire/msgblock.go MsgBlock.AddTransaction 100.00% (3/3) -github.com/conformal/btcwire/invvect.go InvType.String 100.00% (3/3) -github.com/conformal/btcwire/msginv.go NewMsgInvSizeHint 100.00% (3/3) +github.com/conformal/btcwire/invvect.go writeInvVect 100.00% (4/4) +github.com/conformal/btcwire/msgping.go MsgPing.MaxPayloadLength 100.00% (4/4) +github.com/conformal/btcwire/netaddress.go maxNetAddressPayload 100.00% (4/4) +github.com/conformal/btcwire/msgmempool.go MsgMemPool.BtcDecode 100.00% (4/4) +github.com/conformal/btcwire/shahash.go ShaHash.Bytes 100.00% (3/3) github.com/conformal/btcwire/error.go MessageError.Error 100.00% (3/3) github.com/conformal/btcwire/protocol.go BitcoinNet.String 100.00% (3/3) -github.com/conformal/btcwire/msgversion.go MsgVersion.HasService 100.00% (3/3) -github.com/conformal/btcwire/shahash.go ShaHash.Bytes 100.00% (3/3) +github.com/conformal/btcwire/msggetdata.go NewMsgGetDataSizeHint 100.00% (3/3) +github.com/conformal/btcwire/netaddress.go NetAddress.HasService 100.00% (3/3) +github.com/conformal/btcwire/msginv.go NewMsgInvSizeHint 100.00% (3/3) +github.com/conformal/btcwire/invvect.go InvType.String 100.00% (3/3) github.com/conformal/btcwire/msgaddr.go MsgAddr.MaxPayloadLength 100.00% (3/3) +github.com/conformal/btcwire/msgversion.go MsgVersion.HasService 100.00% (3/3) +github.com/conformal/btcwire/message.go ReadMessage 100.00% (2/2) +github.com/conformal/btcwire/message.go WriteMessage 100.00% (2/2) github.com/conformal/btcwire/netaddress.go NetAddress.SetAddress 100.00% (2/2) +github.com/conformal/btcwire/msgblock.go MsgBlock.AddTransaction 100.00% (2/2) github.com/conformal/btcwire/netaddress.go NewNetAddressIPPort 100.00% (2/2) -github.com/conformal/btcwire/msgblock.go MsgBlock.ClearTransactions 100.00% (2/2) -github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.Command 100.00% (1/1) +github.com/conformal/btcwire/msgalert.go NewMsgAlert 100.00% (1/1) github.com/conformal/btcwire/msgnotfound.go MsgNotFound.Command 100.00% (1/1) github.com/conformal/btcwire/msgnotfound.go MsgNotFound.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgnotfound.go NewMsgNotFound 100.00% (1/1) -github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.BtcEncode 100.00% (1/1) -github.com/conformal/btcwire/msgheaders.go NewMsgHeaders 100.00% (1/1) github.com/conformal/btcwire/msgping.go MsgPing.Command 100.00% (1/1) -github.com/conformal/btcwire/common.go RandomUint64 100.00% (1/1) github.com/conformal/btcwire/msgping.go NewMsgPing 100.00% (1/1) -github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.BtcDecode 100.00% (1/1) -github.com/conformal/btcwire/msgblock.go NewMsgBlock 100.00% (1/1) +github.com/conformal/btcwire/msgalert.go MsgAlert.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msgalert.go MsgAlert.Command 100.00% (1/1) github.com/conformal/btcwire/msgpong.go MsgPong.Command 100.00% (1/1) -github.com/conformal/btcwire/shahash.go ShaHash.IsEqual 100.00% (1/1) github.com/conformal/btcwire/msgpong.go NewMsgPong 100.00% (1/1) github.com/conformal/btcwire/msgtx.go NewOutPoint 100.00% (1/1) github.com/conformal/btcwire/msgtx.go TxIn.SerializeSize 100.00% (1/1) @@ -114,52 +110,60 @@ github.com/conformal/btcwire/msgtx.go TxOut.SerializeSize 100.00% (1/1) github.com/conformal/btcwire/msgtx.go NewTxOut 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.AddTxIn 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.AddTxOut 100.00% (1/1) -github.com/conformal/btcwire/msgblock.go MsgBlock.BlockSha 100.00% (1/1) -github.com/conformal/btcwire/msgblock.go MsgBlock.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msgblock.go MsgBlock.Command 100.00% (1/1) +github.com/conformal/btcwire/msgheaders.go MsgHeaders.Command 100.00% (1/1) +github.com/conformal/btcwire/msgaddr.go NewMsgAddr 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.Deserialize 100.00% (1/1) -github.com/conformal/btcwire/msgblock.go MsgBlock.Serialize 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.Serialize 100.00% (1/1) -github.com/conformal/btcwire/msgblock.go MsgBlock.Deserialize 100.00% (1/1) +github.com/conformal/btcwire/msgaddr.go MsgAddr.Command 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.Command 100.00% (1/1) github.com/conformal/btcwire/msgtx.go MsgTx.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgtx.go NewMsgTx 100.00% (1/1) -github.com/conformal/btcwire/msgalert.go NewMsgAlert 100.00% (1/1) -github.com/conformal/btcwire/msgalert.go MsgAlert.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msgalert.go MsgAlert.Command 100.00% (1/1) -github.com/conformal/btcwire/msgaddr.go NewMsgAddr 100.00% (1/1) +github.com/conformal/btcwire/msgaddr.go MsgAddr.ClearAddresses 100.00% (1/1) +github.com/conformal/btcwire/invvect.go NewInvVect 100.00% (1/1) github.com/conformal/btcwire/msgverack.go MsgVerAck.BtcDecode 100.00% (1/1) github.com/conformal/btcwire/msgverack.go MsgVerAck.BtcEncode 100.00% (1/1) github.com/conformal/btcwire/msgverack.go MsgVerAck.Command 100.00% (1/1) github.com/conformal/btcwire/msgverack.go MsgVerAck.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgverack.go NewMsgVerAck 100.00% (1/1) github.com/conformal/btcwire/msgversion.go MsgVersion.AddService 100.00% (1/1) -github.com/conformal/btcwire/msgaddr.go MsgAddr.Command 100.00% (1/1) +github.com/conformal/btcwire/error.go messageError 100.00% (1/1) github.com/conformal/btcwire/msgversion.go MsgVersion.Command 100.00% (1/1) github.com/conformal/btcwire/msgversion.go MsgVersion.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgversion.go NewMsgVersion 100.00% (1/1) -github.com/conformal/btcwire/msgaddr.go MsgAddr.ClearAddresses 100.00% (1/1) -github.com/conformal/btcwire/blockheader.go NewBlockHeader 100.00% (1/1) +github.com/conformal/btcwire/common.go RandomUint64 100.00% (1/1) github.com/conformal/btcwire/netaddress.go NetAddress.AddService 100.00% (1/1) -github.com/conformal/btcwire/invvect.go NewInvVect 100.00% (1/1) -github.com/conformal/btcwire/error.go messageError 100.00% (1/1) +github.com/conformal/btcwire/msggetaddr.go NewMsgGetAddr 100.00% (1/1) +github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.Command 100.00% (1/1) +github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.Command 100.00% (1/1) +github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msggetblocks.go NewMsgGetBlocks 100.00% (1/1) +github.com/conformal/btcwire/shahash.go ShaHash.IsEqual 100.00% (1/1) +github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.BtcEncode 100.00% (1/1) +github.com/conformal/btcwire/msggetaddr.go MsgGetAddr.BtcDecode 100.00% (1/1) +github.com/conformal/btcwire/msggetdata.go MsgGetData.Command 100.00% (1/1) +github.com/conformal/btcwire/msggetdata.go MsgGetData.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go MsgBlock.Serialize 100.00% (1/1) +github.com/conformal/btcwire/blockheader.go NewBlockHeader 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go NewMsgBlock 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go MsgBlock.BlockSha 100.00% (1/1) +github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.Command 100.00% (1/1) github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msggetheaders.go NewMsgGetHeaders 100.00% (1/1) -github.com/conformal/btcwire/msggetheaders.go MsgGetHeaders.Command 100.00% (1/1) -github.com/conformal/btcwire/msggetdata.go NewMsgGetData 100.00% (1/1) -github.com/conformal/btcwire/msgheaders.go MsgHeaders.Command 100.00% (1/1) +github.com/conformal/btcwire/blockheader.go BlockHeader.Serialize 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go MsgBlock.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go MsgBlock.Command 100.00% (1/1) github.com/conformal/btcwire/msgheaders.go MsgHeaders.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msggetdata.go MsgGetData.MaxPayloadLength 100.00% (1/1) -github.com/conformal/btcwire/msggetdata.go MsgGetData.Command 100.00% (1/1) -github.com/conformal/btcwire/msggetblocks.go NewMsgGetBlocks 100.00% (1/1) -github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.Command 100.00% (1/1) +github.com/conformal/btcwire/msgheaders.go NewMsgHeaders 100.00% (1/1) +github.com/conformal/btcwire/blockheader.go BlockHeader.Deserialize 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go MsgBlock.Deserialize 100.00% (1/1) +github.com/conformal/btcwire/msgblock.go MsgBlock.ClearTransactions 100.00% (1/1) github.com/conformal/btcwire/msginv.go MsgInv.Command 100.00% (1/1) github.com/conformal/btcwire/msginv.go MsgInv.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msginv.go NewMsgInv 100.00% (1/1) -github.com/conformal/btcwire/msggetblocks.go MsgGetBlocks.MaxPayloadLength 100.00% (1/1) +github.com/conformal/btcwire/msggetdata.go NewMsgGetData 100.00% (1/1) github.com/conformal/btcwire/msgmempool.go MsgMemPool.Command 100.00% (1/1) github.com/conformal/btcwire/msgmempool.go MsgMemPool.MaxPayloadLength 100.00% (1/1) github.com/conformal/btcwire/msgmempool.go NewMsgMemPool 100.00% (1/1) -github.com/conformal/btcwire/msggetaddr.go NewMsgGetAddr 100.00% (1/1) -github.com/conformal/btcwire --------------------------------- 100.00% (1132/1132) +github.com/conformal/btcwire --------------------------------- 100.00% (1153/1153)