Add Read/WriteMessageN to return number of bytes.

This commit adds two new funtions named ReadMessageN and WriteMessageN
which return an additional paramter for the number of bytes read or written,
respectively.

It also adds tests to ensure the number of bytes read and written are the
expected values both for successful reads/writes and unsuccessful ones.

Closes #6.
This commit is contained in:
Dave Collins 2014-01-18 22:29:44 -06:00
parent 6672f71d68
commit ff783faf53
4 changed files with 271 additions and 147 deletions

View file

@ -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)
}

View file

@ -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
}

View file

@ -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 {

View file

@ -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)