multi: change cfilter Extended bool to FilterType uint8

The cfilter BIP specifies that the filter type is a uint8. The
current code encodes it correctly on the wire, but everywhere else,
it's treated as a boolean (false for basic filter, true for
extended). This commit corrects that to account for possible
additional filter types in the future. All package changes are
done in one commit as they're all interdependent. The following
packages are updated:

* blockchain/indexers
* btcjson
* peer
* wire
* main (server.go and rpcserver.go)
This commit is contained in:
Alex 2017-09-13 14:42:24 +02:00 committed by Olaoluwa Osuntokun
parent e2f65acf02
commit 621c73dad1
11 changed files with 116 additions and 111 deletions

View File

@ -30,21 +30,21 @@ var (
// the index. The rest of the buckets live below this bucket. // the index. The rest of the buckets live below this bucket.
cfIndexParentBucketKey = []byte("cfindexparentbucket") cfIndexParentBucketKey = []byte("cfindexparentbucket")
// cfBasicIndexKey is the name of the db bucket used to house the // cfIndexKeys is an array of db bucket names used to house indexes of
// block hash -> basic cf index (cf#0). // block hashes to cfilters.
cfBasicIndexKey = []byte("cf0byhashidx") cfIndexKeys = [][]byte{
[]byte("cf0byhashidx"),
[]byte("cf1byhashidx"),
}
// cfBasicHeaderKey is the name of the db bucket used to house the // cfHeaderKeys is an array of db bucket names used to house indexes of
// block hash -> basic cf header index (cf#0). // block hashes to cf headers.
cfBasicHeaderKey = []byte("cf0headerbyhashidx") cfHeaderKeys = [][]byte{
[]byte("cf0headerbyhashidx"),
[]byte("cf1headerbyhashidx"),
}
// cfExtendedIndexKey is the name of the db bucket used to house the maxFilterType = uint8(len(cfHeaderKeys) - 1)
// block hash -> extended cf index (cf#1).
cfExtendedIndexKey = []byte("cf1byhashidx")
// cfExtendedHeaderKey is the name of the db bucket used to house the
// block hash -> extended cf header index (cf#1).
cfExtendedHeaderKey = []byte("cf1headerbyhashidx")
) )
// dbFetchFilter retrieves a block's basic or extended filter. A filter's // dbFetchFilter retrieves a block's basic or extended filter. A filter's
@ -131,27 +131,25 @@ func (idx *CfIndex) Create(dbTx database.Tx) error {
if err != nil { if err != nil {
return err return err
} }
_, err = cfIndexParentBucket.CreateBucket(cfBasicIndexKey)
for _, bucketName := range cfIndexKeys {
_, err = cfIndexParentBucket.CreateBucket(bucketName)
if err != nil { if err != nil {
return err return err
} }
_, err = cfIndexParentBucket.CreateBucket(cfBasicHeaderKey) }
for _, bucketName := range cfHeaderKeys {
_, err = cfIndexParentBucket.CreateBucket(bucketName)
if err != nil { if err != nil {
return err return err
} }
_, err = cfIndexParentBucket.CreateBucket(cfExtendedIndexKey)
if err != nil {
return err
}
_, err = cfIndexParentBucket.CreateBucket(cfExtendedHeaderKey)
if err != nil {
return err
} }
firstHeader := make([]byte, chainhash.HashSize) firstHeader := make([]byte, chainhash.HashSize)
err = dbStoreFilterHeader( err = dbStoreFilterHeader(
dbTx, dbTx,
cfBasicHeaderKey, cfHeaderKeys[0],
&idx.chainParams.GenesisBlock.Header.PrevBlock, &idx.chainParams.GenesisBlock.Header.PrevBlock,
firstHeader, firstHeader,
) )
@ -161,7 +159,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error {
return dbStoreFilterHeader( return dbStoreFilterHeader(
dbTx, dbTx,
cfExtendedHeaderKey, cfHeaderKeys[1],
&idx.chainParams.GenesisBlock.Header.PrevBlock, &idx.chainParams.GenesisBlock.Header.PrevBlock,
firstHeader, firstHeader,
) )
@ -170,15 +168,14 @@ func (idx *CfIndex) Create(dbTx database.Tx) error {
// storeFilter stores a given filter, and performs the steps needed to // storeFilter stores a given filter, and performs the steps needed to
// generate the filter's header. // generate the filter's header.
func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter,
extended bool) error { filterType uint8) error {
if filterType > maxFilterType {
return errors.New("unsupported filter type")
}
// Figure out which buckets to use. // Figure out which buckets to use.
fkey := cfBasicIndexKey fkey := cfIndexKeys[filterType]
hkey := cfBasicHeaderKey hkey := cfHeaderKeys[filterType]
if extended {
fkey = cfExtendedIndexKey
hkey = cfExtendedHeaderKey
}
// Start by storing the filter. // Start by storing the filter.
h := block.Hash() h := block.Hash()
@ -218,7 +215,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
return err return err
} }
if err := storeFilter(dbTx, block, f, false); err != nil { if err := storeFilter(dbTx, block, f, 0); err != nil {
return err return err
} }
@ -227,7 +224,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
return err return err
} }
return storeFilter(dbTx, block, f, true) return storeFilter(dbTx, block, f, 1)
} }
// DisconnectBlock is invoked by the index manager when a block has been // DisconnectBlock is invoked by the index manager when a block has been
@ -236,26 +233,34 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block,
view *blockchain.UtxoViewpoint) error { view *blockchain.UtxoViewpoint) error {
err := dbDeleteFilter(dbTx, cfBasicIndexKey, block.Hash()) for _, key := range cfIndexKeys {
err := dbDeleteFilter(dbTx, key, block.Hash())
if err != nil { if err != nil {
return err return err
} }
}
return dbDeleteFilter(dbTx, cfExtendedIndexKey, block.Hash()) for _, key := range cfHeaderKeys {
err := dbDeleteFilterHeader(dbTx, key, block.Hash())
if err != nil {
return err
}
}
return nil
} }
// FilterByBlockHash returns the serialized contents of a block's basic or // FilterByBlockHash returns the serialized contents of a block's basic or
// extended committed filter. // extended committed filter.
func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, filterType uint8) ([]byte, error) {
var f []byte var f []byte
err := idx.db.View(func(dbTx database.Tx) error { err := idx.db.View(func(dbTx database.Tx) error {
var err error if filterType > maxFilterType {
key := cfBasicIndexKey return errors.New("unsupported filter type")
if extended {
key = cfExtendedIndexKey
} }
f, err = dbFetchFilter(dbTx, key, h) var err error
f, err = dbFetchFilter(dbTx, cfIndexKeys[filterType], h)
return err return err
}) })
return f, err return f, err
@ -263,16 +268,15 @@ func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte,
// FilterHeaderByBlockHash returns the serialized contents of a block's basic // FilterHeaderByBlockHash returns the serialized contents of a block's basic
// or extended committed filter header. // or extended committed filter header.
func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, filterType uint8) ([]byte, error) {
var fh []byte var fh []byte
err := idx.db.View(func(dbTx database.Tx) error { err := idx.db.View(func(dbTx database.Tx) error {
var err error if filterType > 1 {
key := cfBasicHeaderKey return errors.New("unsupported filter type")
if extended {
key = cfExtendedHeaderKey
} }
fh, err = dbFetchFilterHeader(dbTx, key, h) var err error
fh, err = dbFetchFilterHeader(dbTx, cfHeaderKeys[filterType], h)
return err return err
}) })
return fh, err return fh, err

View File

@ -278,33 +278,34 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd {
Request: request, Request: request,
} }
} }
// GetCFilterCmd defines the getcfilter JSON-RPC command. // GetCFilterCmd defines the getcfilter JSON-RPC command.
type GetCFilterCmd struct { type GetCFilterCmd struct {
Hash string Hash string
Extended bool FilterType uint8
} }
// NewGetCFilterCmd returns a new instance which can be used to issue a // NewGetCFilterCmd returns a new instance which can be used to issue a
// getcfilter JSON-RPC command. // getcfilter JSON-RPC command.
func NewGetCFilterCmd(hash string, extended bool) *GetCFilterCmd { func NewGetCFilterCmd(hash string, filterType uint8) *GetCFilterCmd {
return &GetCFilterCmd{ return &GetCFilterCmd{
Hash: hash, Hash: hash,
Extended: extended, FilterType: filterType,
} }
} }
// GetCFilterHeaderCmd defines the getcfilterheader JSON-RPC command. // GetCFilterHeaderCmd defines the getcfilterheader JSON-RPC command.
type GetCFilterHeaderCmd struct { type GetCFilterHeaderCmd struct {
Hash string Hash string
Extended bool FilterType uint8
} }
// NewGetCFilterHeaderCmd returns a new instance which can be used to issue a // NewGetCFilterHeaderCmd returns a new instance which can be used to issue a
// getcfilterheader JSON-RPC command. // getcfilterheader JSON-RPC command.
func NewGetCFilterHeaderCmd(hash string, extended bool) *GetCFilterHeaderCmd { func NewGetCFilterHeaderCmd(hash string, filterType uint8) *GetCFilterHeaderCmd {
return &GetCFilterHeaderCmd{ return &GetCFilterHeaderCmd{
Hash: hash, Hash: hash,
Extended: extended, FilterType: filterType,
} }
} }

View File

@ -320,10 +320,10 @@ func TestChainSvrCmds(t *testing.T) {
{ {
name: "getcfilter", name: "getcfilter",
newCmd: func() (interface{}, error) { newCmd: func() (interface{}, error) {
return btcjson.NewCmd("getcfilter", "123", false) return btcjson.NewCmd("getcfilter", "123", 0)
}, },
staticCmd: func() interface{} { staticCmd: func() interface{} {
return btcjson.NewGetCFilterCmd("123", false) return btcjson.NewGetCFilterCmd("123", 0)
}, },
marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",false],"id":1}`, marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",false],"id":1}`,
unmarshalled: &btcjson.GetCFilterCmd{ unmarshalled: &btcjson.GetCFilterCmd{
@ -333,10 +333,10 @@ func TestChainSvrCmds(t *testing.T) {
{ {
name: "getcfilterheader", name: "getcfilterheader",
newCmd: func() (interface{}, error) { newCmd: func() (interface{}, error) {
return btcjson.NewCmd("getcfilterheader", "123", false) return btcjson.NewCmd("getcfilterheader", "123", 0)
}, },
staticCmd: func() interface{} { staticCmd: func() interface{} {
return btcjson.NewGetCFilterHeaderCmd("123", false) return btcjson.NewGetCFilterHeaderCmd("123", 0)
}, },
marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",false],"id":1}`, marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",false],"id":1}`,
unmarshalled: &btcjson.GetCFilterHeaderCmd{ unmarshalled: &btcjson.GetCFilterHeaderCmd{

View File

@ -536,7 +536,7 @@ func TestPeerListeners(t *testing.T) {
}, },
{ {
"OnGetCFilter", "OnGetCFilter",
wire.NewMsgGetCFilter(&chainhash.Hash{}, false), wire.NewMsgGetCFilter(&chainhash.Hash{}, 0),
}, },
{ {
"OnGetCFHeaders", "OnGetCFHeaders",
@ -544,7 +544,7 @@ func TestPeerListeners(t *testing.T) {
}, },
{ {
"OnCFilter", "OnCFilter",
wire.NewMsgCFilter(&chainhash.Hash{}, true, wire.NewMsgCFilter(&chainhash.Hash{}, 1,
[]byte("payload")), []byte("payload")),
}, },
{ {

View File

@ -2163,7 +2163,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{})
return nil, rpcDecodeHexError(c.Hash) return nil, rpcDecodeHexError(c.Hash)
} }
filterBytes, err := s.cfg.CfIndex.FilterByBlockHash(hash, c.Extended) filterBytes, err := s.cfg.CfIndex.FilterByBlockHash(hash, c.FilterType)
if err != nil { if err != nil {
rpcsLog.Debugf("Could not find committed filter for %v: %v", rpcsLog.Debugf("Could not find committed filter for %v: %v",
hash, err) hash, err)
@ -2192,7 +2192,7 @@ func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan stru
return nil, rpcDecodeHexError(c.Hash) return nil, rpcDecodeHexError(c.Hash)
} }
headerBytes, err := s.cfg.CfIndex.FilterHeaderByBlockHash(hash, c.Extended) headerBytes, err := s.cfg.CfIndex.FilterHeaderByBlockHash(hash, c.FilterType)
if len(headerBytes) > 0 { if len(headerBytes) > 0 {
rpcsLog.Debugf("Found header of committed filter for %v", hash) rpcsLog.Debugf("Found header of committed filter for %v", hash)
} else { } else {

View File

@ -747,7 +747,7 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) {
} }
filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash, filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash,
msg.Extended) msg.FilterType)
if len(filterBytes) > 0 { if len(filterBytes) > 0 {
peerLog.Tracef("Obtained CF for %v", msg.BlockHash) peerLog.Tracef("Obtained CF for %v", msg.BlockHash)
@ -756,7 +756,7 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) {
err) err)
} }
filterMsg := wire.NewMsgCFilter(&msg.BlockHash, msg.Extended, filterMsg := wire.NewMsgCFilter(&msg.BlockHash, msg.FilterType,
filterBytes) filterBytes)
sp.QueueMessage(filterMsg, nil) sp.QueueMessage(filterMsg, nil)
} }
@ -789,7 +789,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
// Fetch the raw committed filter header bytes from the // Fetch the raw committed filter header bytes from the
// database. // database.
headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash(
&msg.HashStop, msg.Extended) &msg.HashStop, msg.FilterType)
if (err != nil) || (len(headerBytes) == 0) { if (err != nil) || (len(headerBytes) == 0) {
peerLog.Warnf("Could not obtain CF header for %v: %v", peerLog.Warnf("Could not obtain CF header for %v: %v",
msg.HashStop, err) msg.HashStop, err)
@ -808,7 +808,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
headersMsg := wire.NewMsgCFHeaders() headersMsg := wire.NewMsgCFHeaders()
headersMsg.AddCFHeader(&header) headersMsg.AddCFHeader(&header)
headersMsg.StopHash = msg.HashStop headersMsg.StopHash = msg.HashStop
headersMsg.Extended = msg.Extended headersMsg.FilterType = msg.FilterType
sp.QueueMessage(headersMsg, nil) sp.QueueMessage(headersMsg, nil)
return return
} }
@ -849,7 +849,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
// Fetch the raw committed filter header bytes from the // Fetch the raw committed filter header bytes from the
// database. // database.
headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash(
&hashList[i], msg.Extended) &hashList[i], msg.FilterType)
if (err != nil) || (len(headerBytes) == 0) { if (err != nil) || (len(headerBytes) == 0) {
peerLog.Warnf("Could not obtain CF header for %v: %v", peerLog.Warnf("Could not obtain CF header for %v: %v",
hashList[i], err) hashList[i], err)
@ -868,7 +868,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) {
headersMsg.AddCFHeader(&header) headersMsg.AddCFHeader(&header)
} }
headersMsg.Extended = msg.Extended headersMsg.FilterType = msg.FilterType
headersMsg.StopHash = hashList[len(hashList)-1] headersMsg.StopHash = hashList[len(hashList)-1]
sp.QueueMessage(headersMsg, nil) sp.QueueMessage(headersMsg, nil)
} }

View File

@ -69,9 +69,9 @@ func TestMessage(t *testing.T) {
bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0) bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0)
msgMerkleBlock := NewMsgMerkleBlock(bh) msgMerkleBlock := NewMsgMerkleBlock(bh)
msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block")
msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, false) msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, 0)
msgGetCFHeaders := NewMsgGetCFHeaders() msgGetCFHeaders := NewMsgGetCFHeaders()
msgCFilter := NewMsgCFilter(&chainhash.Hash{}, true, []byte("payload")) msgCFilter := NewMsgCFilter(&chainhash.Hash{}, 1, []byte("payload"))
msgCFHeaders := NewMsgCFHeaders() msgCFHeaders := NewMsgCFHeaders()
tests := []struct { tests := []struct {

View File

@ -28,7 +28,7 @@ const (
// MsgGetCFHeaders for details on requesting the headers. // MsgGetCFHeaders for details on requesting the headers.
type MsgCFHeaders struct { type MsgCFHeaders struct {
StopHash chainhash.Hash StopHash chainhash.Hash
Extended bool FilterType uint8
HeaderHashes []*chainhash.Hash HeaderHashes []*chainhash.Hash
} }
@ -53,8 +53,8 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding)
return err return err
} }
// Read extended flag // Read filter type
err = readElement(r, &msg.Extended) err = readElement(r, &msg.FilterType)
if err != nil { if err != nil {
return err return err
} }
@ -97,8 +97,8 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding)
return err return err
} }
// Write extended flag // Write filter type
err = writeElement(w, msg.Extended) err = writeElement(w, msg.FilterType)
if err != nil { if err != nil {
return err return err
} }

View File

@ -18,7 +18,7 @@ const (
type MsgCFilter struct { type MsgCFilter struct {
BlockHash chainhash.Hash BlockHash chainhash.Hash
Extended bool FilterType uint8
Data []byte Data []byte
} }
@ -31,8 +31,8 @@ func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) er
if err != nil { if err != nil {
return err return err
} }
// Read extended flag // Read filter type
err = readElement(r, &msg.Extended) err = readElement(r, &msg.FilterType)
if err != nil { if err != nil {
return err return err
} }
@ -57,7 +57,7 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) er
return err return err
} }
err = writeElement(w, msg.Extended) err = writeElement(w, msg.FilterType)
if err != nil { if err != nil {
return err return err
} }
@ -96,11 +96,11 @@ func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 {
// NewMsgCFilter returns a new bitcoin cfilter message that conforms to the // NewMsgCFilter returns a new bitcoin cfilter message that conforms to the
// Message interface. See MsgCFilter for details. // Message interface. See MsgCFilter for details.
func NewMsgCFilter(blockHash *chainhash.Hash, extended bool, func NewMsgCFilter(blockHash *chainhash.Hash, filterType uint8,
data []byte) *MsgCFilter { data []byte) *MsgCFilter {
return &MsgCFilter{ return &MsgCFilter{
BlockHash: *blockHash, BlockHash: *blockHash,
Extended: extended, FilterType: filterType,
Data: data, Data: data,
} }
} }

View File

@ -12,13 +12,13 @@ import (
) )
// MsgGetCFHeaders is a message similar to MsgGetHeaders, but for committed // MsgGetCFHeaders is a message similar to MsgGetHeaders, but for committed
// filter headers. It allows to set the Extended field to get headers in the // filter headers. It allows to set the FilterType field to get headers in the
// chain of basic (false) or extended (true) headers. // chain of basic (0x00) or extended (0x01) headers.
type MsgGetCFHeaders struct { type MsgGetCFHeaders struct {
ProtocolVersion uint32 ProtocolVersion uint32
BlockLocatorHashes []*chainhash.Hash BlockLocatorHashes []*chainhash.Hash
HashStop chainhash.Hash HashStop chainhash.Hash
Extended bool FilterType uint8
} }
// AddBlockLocatorHash adds a new block locator hash to the message. // AddBlockLocatorHash adds a new block locator hash to the message.
@ -70,7 +70,7 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncodin
return err return err
} }
return readElement(r, &msg.Extended) return readElement(r, &msg.FilterType)
} }
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
@ -106,7 +106,7 @@ func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncodin
return err return err
} }
return writeElement(w, msg.Extended) return writeElement(w, msg.FilterType)
} }
// Command returns the protocol command string for the message. This is part // Command returns the protocol command string for the message. This is part
@ -119,7 +119,7 @@ func (msg *MsgGetCFHeaders) Command() string {
// receiver. This is part of the Message interface implementation. // receiver. This is part of the Message interface implementation.
func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 { func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 {
// Version 4 bytes + num block locator hashes (varInt) + max allowed // Version 4 bytes + num block locator hashes (varInt) + max allowed
// block locators + hash stop + Extended flag 1 byte. // block locators + hash stop + filter type 1 byte.
return 4 + MaxVarIntPayload + (MaxBlockLocatorsPerMsg * return 4 + MaxVarIntPayload + (MaxBlockLocatorsPerMsg *
chainhash.HashSize) + chainhash.HashSize + 1 chainhash.HashSize) + chainhash.HashSize + 1
} }

View File

@ -12,7 +12,7 @@ import (
type MsgGetCFilter struct { type MsgGetCFilter struct {
BlockHash chainhash.Hash BlockHash chainhash.Hash
Extended bool FilterType uint8
} }
func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error {
@ -20,7 +20,7 @@ func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding)
if err != nil { if err != nil {
return err return err
} }
return readElement(r, &msg.Extended) return readElement(r, &msg.FilterType)
} }
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
@ -30,7 +30,7 @@ func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding)
if err != nil { if err != nil {
return err return err
} }
return writeElement(w, msg.Extended) return writeElement(w, msg.FilterType)
} }
// Command returns the protocol command string for the message. This is part // Command returns the protocol command string for the message. This is part
@ -42,16 +42,16 @@ func (msg *MsgGetCFilter) Command() string {
// MaxPayloadLength returns the maximum length the payload can be for the // MaxPayloadLength returns the maximum length the payload can be for the
// receiver. This is part of the Message interface implementation. // receiver. This is part of the Message interface implementation.
func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 {
// Block hash + Extended flag. // Block hash + filter type.
return chainhash.HashSize + 1 return chainhash.HashSize + 1
} }
// NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to // NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to
// the Message interface using the passed parameters and defaults for the // the Message interface using the passed parameters and defaults for the
// remaining fields. // remaining fields.
func NewMsgGetCFilter(blockHash *chainhash.Hash, extended bool) *MsgGetCFilter { func NewMsgGetCFilter(blockHash *chainhash.Hash, filterType uint8) *MsgGetCFilter {
return &MsgGetCFilter{ return &MsgGetCFilter{
BlockHash: *blockHash, BlockHash: *blockHash,
Extended: extended, FilterType: filterType,
} }
} }