BIP0144+wire: add a MessageEncoding variant for serialization/deserialization

This commit modifies the existing wire.Message interface to introduce a
new MessageEncoding variant which dictates the exact encoding to be
used when serializing and deserializing messages. Such an option is now
necessary due to the segwit soft-fork package, as btcd will need to be
able to optionally encode transactions/blocks without witness data to
un-upgraded peers.

Two new functions have been introduced: ReadMessageWithEncodingN and
WriteMessageWithEncodingN which wrap BtcDecode/BtcEncode with the
desired encoding format.
This commit is contained in:
Olaoluwa Osuntokun
2016-10-18 16:21:48 -07:00
committed by Dave Collins
parent 1b359e1131
commit 48abfdf87c
51 changed files with 862 additions and 515 deletions

View File

@@ -139,10 +139,11 @@ func TestVersionWire(t *testing.T) {
verRelayTxFalseEncoded[len(verRelayTxFalseEncoded)-1] = 0
tests := []struct {
in *MsgVersion // Message to encode
out *MsgVersion // Expected decoded message
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
in *MsgVersion // Message to encode
out *MsgVersion // Expected decoded message
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
enc MessageEncoding // Message encoding format
}{
// Latest protocol version.
{
@@ -150,6 +151,7 @@ func TestVersionWire(t *testing.T) {
baseVersionBIP0037,
baseVersionBIP0037Encoded,
ProtocolVersion,
BaseEncoding,
},
// Protocol version BIP0037Version with relay transactions field
@@ -159,6 +161,7 @@ func TestVersionWire(t *testing.T) {
baseVersionBIP0037,
baseVersionBIP0037Encoded,
BIP0037Version,
BaseEncoding,
},
// Protocol version BIP0037Version with relay transactions field
@@ -168,6 +171,7 @@ func TestVersionWire(t *testing.T) {
verRelayTxFalse,
verRelayTxFalseEncoded,
BIP0037Version,
BaseEncoding,
},
// Protocol version BIP0035Version.
@@ -176,6 +180,7 @@ func TestVersionWire(t *testing.T) {
baseVersion,
baseVersionEncoded,
BIP0035Version,
BaseEncoding,
},
// Protocol version BIP0031Version.
@@ -184,6 +189,7 @@ func TestVersionWire(t *testing.T) {
baseVersion,
baseVersionEncoded,
BIP0031Version,
BaseEncoding,
},
// Protocol version NetAddressTimeVersion.
@@ -192,6 +198,7 @@ func TestVersionWire(t *testing.T) {
baseVersion,
baseVersionEncoded,
NetAddressTimeVersion,
BaseEncoding,
},
// Protocol version MultipleAddressVersion.
@@ -200,6 +207,7 @@ func TestVersionWire(t *testing.T) {
baseVersion,
baseVersionEncoded,
MultipleAddressVersion,
BaseEncoding,
},
}
@@ -207,7 +215,7 @@ func TestVersionWire(t *testing.T) {
for i, test := range tests {
// Encode the message to wire format.
var buf bytes.Buffer
err := test.in.BtcEncode(&buf, test.pver)
err := test.in.BtcEncode(&buf, test.pver, test.enc)
if err != nil {
t.Errorf("BtcEncode #%d error %v", i, err)
continue
@@ -221,7 +229,7 @@ func TestVersionWire(t *testing.T) {
// Decode the message from wire format.
var msg MsgVersion
rbuf := bytes.NewBuffer(test.buf)
err = msg.BtcDecode(rbuf, test.pver)
err = msg.BtcDecode(rbuf, test.pver, test.enc)
if err != nil {
t.Errorf("BtcDecode #%d error %v", i, err)
continue
@@ -241,12 +249,13 @@ func TestVersionWireErrors(t *testing.T) {
// because the test data is using bytes encoded with that protocol
// version.
pver := uint32(60002)
enc := BaseEncoding
wireErr := &MessageError{}
// Ensure calling MsgVersion.BtcDecode with a non *bytes.Buffer returns
// error.
fr := newFixedReader(0, []byte{})
if err := baseVersion.BtcDecode(fr, pver); err == nil {
if err := baseVersion.BtcDecode(fr, pver, enc); err == nil {
t.Errorf("Did not received error when calling " +
"MsgVersion.BtcDecode with non *bytes.Buffer")
}
@@ -276,46 +285,47 @@ func TestVersionWireErrors(t *testing.T) {
copy(exceedUAVerEncoded[83+len(newUA):], baseVersionEncoded[97:100])
tests := []struct {
in *MsgVersion // Value to encode
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
max int // Max size of fixed buffer to induce errors
writeErr error // Expected write error
readErr error // Expected read error
in *MsgVersion // Value to encode
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
enc MessageEncoding // Message encoding format
max int // Max size of fixed buffer to induce errors
writeErr error // Expected write error
readErr error // Expected read error
}{
// Force error in protocol version.
{baseVersion, baseVersionEncoded, pver, 0, io.ErrShortWrite, io.EOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
// Force error in services.
{baseVersion, baseVersionEncoded, pver, 4, io.ErrShortWrite, io.EOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 4, io.ErrShortWrite, io.EOF},
// Force error in timestamp.
{baseVersion, baseVersionEncoded, pver, 12, io.ErrShortWrite, io.EOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 12, io.ErrShortWrite, io.EOF},
// Force error in remote address.
{baseVersion, baseVersionEncoded, pver, 20, io.ErrShortWrite, io.EOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 20, io.ErrShortWrite, io.EOF},
// Force error in local address.
{baseVersion, baseVersionEncoded, pver, 47, io.ErrShortWrite, io.ErrUnexpectedEOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 47, io.ErrShortWrite, io.ErrUnexpectedEOF},
// Force error in nonce.
{baseVersion, baseVersionEncoded, pver, 73, io.ErrShortWrite, io.ErrUnexpectedEOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 73, io.ErrShortWrite, io.ErrUnexpectedEOF},
// Force error in user agent length.
{baseVersion, baseVersionEncoded, pver, 81, io.ErrShortWrite, io.EOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 81, io.ErrShortWrite, io.EOF},
// Force error in user agent.
{baseVersion, baseVersionEncoded, pver, 82, io.ErrShortWrite, io.ErrUnexpectedEOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 82, io.ErrShortWrite, io.ErrUnexpectedEOF},
// Force error in last block.
{baseVersion, baseVersionEncoded, pver, 98, io.ErrShortWrite, io.ErrUnexpectedEOF},
{baseVersion, baseVersionEncoded, pver, BaseEncoding, 98, io.ErrShortWrite, io.ErrUnexpectedEOF},
// Force error in relay tx - no read error should happen since
// it's optional.
{
baseVersionBIP0037, baseVersionBIP0037Encoded,
BIP0037Version, 101, io.ErrShortWrite, nil,
BIP0037Version, BaseEncoding, 101, io.ErrShortWrite, nil,
},
// Force error due to user agent too big
{exceedUAVer, exceedUAVerEncoded, pver, newLen, wireErr, wireErr},
{exceedUAVer, exceedUAVerEncoded, pver, BaseEncoding, newLen, wireErr, wireErr},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Encode to wire format.
w := newFixedWriter(test.max)
err := test.in.BtcEncode(w, test.pver)
err := test.in.BtcEncode(w, test.pver, test.enc)
if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
i, err, test.writeErr)
@@ -335,7 +345,7 @@ func TestVersionWireErrors(t *testing.T) {
// Decode from wire format.
var msg MsgVersion
buf := bytes.NewBuffer(test.buf[0:test.max])
err = msg.BtcDecode(buf, test.pver)
err = msg.BtcDecode(buf, test.pver, test.enc)
if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
i, err, test.readErr)
@@ -407,34 +417,40 @@ func TestVersionOptionalFields(t *testing.T) {
copy(lastBlockVersionEncoded, baseVersionEncoded)
tests := []struct {
msg *MsgVersion // Expected message
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
msg *MsgVersion // Expected message
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
enc MessageEncoding // Message encoding format
}{
{
&onlyRequiredVersion,
onlyRequiredVersionEncoded,
ProtocolVersion,
BaseEncoding,
},
{
&addrMeVersion,
addrMeVersionEncoded,
ProtocolVersion,
BaseEncoding,
},
{
&nonceVersion,
nonceVersionEncoded,
ProtocolVersion,
BaseEncoding,
},
{
&uaVersion,
uaVersionEncoded,
ProtocolVersion,
BaseEncoding,
},
{
&lastBlockVersion,
lastBlockVersionEncoded,
ProtocolVersion,
BaseEncoding,
},
}
@@ -442,7 +458,7 @@ func TestVersionOptionalFields(t *testing.T) {
// Decode the message from wire format.
var msg MsgVersion
rbuf := bytes.NewBuffer(test.buf)
err := msg.BtcDecode(rbuf, test.pver)
err := msg.BtcDecode(rbuf, test.pver, test.enc)
if err != nil {
t.Errorf("BtcDecode #%d error %v", i, err)
continue