From 89d6696560347700cc42cabdbd8a8f9a26b53f58 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 13 Sep 2017 17:16:58 +0200 Subject: [PATCH] wire: add getcftypes and cftypes messages --- wire/message.go | 8 ++++ wire/message_test.go | 4 ++ wire/msgcftypes.go | 92 +++++++++++++++++++++++++++++++++++++++++++ wire/msggetcftypes.go | 42 ++++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 wire/msgcftypes.go create mode 100644 wire/msggetcftypes.go diff --git a/wire/message.go b/wire/message.go index 9a34a2fa5..4b4745533 100644 --- a/wire/message.go +++ b/wire/message.go @@ -53,8 +53,10 @@ const ( CmdFeeFilter = "feefilter" CmdGetCFilter = "getcfilter" CmdGetCFHeaders = "getcfheaders" + CmdGetCFTypes = "getcftypes" CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" + CmdCFTypes = "cftypes" ) // MessageEncoding represents the wire message encoding format to be used. @@ -166,12 +168,18 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFHeaders: msg = &MsgGetCFHeaders{} + case CmdGetCFTypes: + msg = &MsgGetCFTypes{} + case CmdCFilter: msg = &MsgCFilter{} case CmdCFHeaders: msg = &MsgCFHeaders{} + case CmdCFTypes: + msg = &MsgCFTypes{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/message_test.go b/wire/message_test.go index 6bf7fd2b4..2be2a5a0d 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -71,8 +71,10 @@ func TestMessage(t *testing.T) { msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, 0) msgGetCFHeaders := NewMsgGetCFHeaders() + msgGetCFTypes := NewMsgGetCFTypes() msgCFilter := NewMsgCFilter(&chainhash.Hash{}, 1, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() + msgCFTypes := NewMsgCFTypes([]uint8{2}) tests := []struct { in Message // Value to encode @@ -104,8 +106,10 @@ func TestMessage(t *testing.T) { {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 62}, + {msgGetCFTypes, msgGetCFTypes, pver, MainNet, 24}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, + {msgCFTypes, msgCFTypes, pver, MainNet, 26}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcftypes.go b/wire/msgcftypes.go new file mode 100644 index 000000000..92a8f718a --- /dev/null +++ b/wire/msgcftypes.go @@ -0,0 +1,92 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import "io" + +// MsgCFTypes is the cftypes message. +type MsgCFTypes struct { + NumFilters uint8 + SupportedFilters []uint8 +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + // Read the number of filter types supported + err := readElement(r, &msg.NumFilters) + if err != nil { + return err + } + + // Read each filter type. + msg.SupportedFilters = make([]uint8, msg.NumFilters) + for i := uint8(0); i < msg.NumFilters; i++ { + err = readElement(r, &msg.SupportedFilters[i]) + if err != nil { + return err + } + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + // Write length of supported filters slice; don't trust that the caller + // has set it correctly. + err := writeElement(w, uint8(len(msg.SupportedFilters))) + if err != nil { + return err + } + + for i := range msg.SupportedFilters { + err = writeElement(w, msg.SupportedFilters[i]) + if err != nil { + return err + } + } + + return nil +} + +// Deserialize decodes a filter from r into the receiver using a format that is +// suitable for long-term storage such as a database. This function differs +// from BtcDecode in that BtcDecode decodes from the bitcoin wire protocol as +// it was sent across the network. The wire encoding can technically differ +// depending on the protocol version and doesn't even really need to match the +// format of a stored filter at all. As of the time this comment was written, +// the encoded filter is the same in both instances, but there is a distinct +// difference and separating the two allows the API to be flexible enough to +// deal with changes. +func (msg *MsgCFTypes) Deserialize(r io.Reader) error { + // At the current time, there is no difference between the wire encoding + // and the stable long-term storage format. As a result, make use of + // BtcDecode. + return msg.BtcDecode(r, 0, BaseEncoding) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgCFTypes) Command() string { + return CmdCFTypes +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgCFTypes) MaxPayloadLength(pver uint32) uint32 { + // 1 byte for NumFilters, and 1 byte for up to 255 filter types. + return 256 +} + +// NewMsgCFTypes returns a new bitcoin cftypes message that conforms to the +// Message interface. See MsgCFTypes for details. +func NewMsgCFTypes(filterTypes []uint8) *MsgCFTypes { + return &MsgCFTypes{ + NumFilters: uint8(len(filterTypes)), + SupportedFilters: filterTypes, + } +} diff --git a/wire/msggetcftypes.go b/wire/msggetcftypes.go new file mode 100644 index 000000000..304ce87bf --- /dev/null +++ b/wire/msggetcftypes.go @@ -0,0 +1,42 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import "io" + +// MsgGetCFTypes is the getcftypes message. +type MsgGetCFTypes struct { +} + +// BtcDecode decodes the receiver from w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + return nil +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFTypes) Command() string { + return CmdGetCFTypes +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFTypes) MaxPayloadLength(pver uint32) uint32 { + // Empty message. + return 0 +} + +// NewMsgGetCFTypes returns a new bitcoin getcftypes message that conforms to +// the Message interface. +func NewMsgGetCFTypes() *MsgGetCFTypes { + return &MsgGetCFTypes{} +}