1 package wire
2 3 import (
4 "fmt"
5 "io"
6 )
7 8 // BloomUpdateType specifies how the filter is updated when a match is found
9 type BloomUpdateType uint8
10 11 const (
12 // BloomUpdateNone indicates the filter is not adjusted when a match is found.
13 BloomUpdateNone BloomUpdateType = 0
14 // BloomUpdateAll indicates if the filter matches any data element in a public
15 // key script, the outpoint is serialized and inserted into the filter.
16 BloomUpdateAll BloomUpdateType = 1
17 // BloomUpdateP2PubkeyOnly indicates if the filter matches a data element in a
18 // public key script and the script is of the standard pay-to-pubkey or
19 // multisig, the outpoint is serialized and inserted into the filter.
20 BloomUpdateP2PubkeyOnly BloomUpdateType = 2
21 )
22 const (
23 // MaxFilterLoadHashFuncs is the maximum number of hash functions to load into
24 // the Bloom filter.
25 MaxFilterLoadHashFuncs = 50
26 // MaxFilterLoadFilterSize is the maximum size in bytes a filter may be.
27 MaxFilterLoadFilterSize = 36000
28 )
29 30 // MsgFilterLoad implements the Message interface and represents a bitcoin
31 // filterload message which is used to reset a Bloom filter. This message was
32 // not added until protocol version BIP0037Version.
33 type MsgFilterLoad struct {
34 Filter []byte
35 HashFuncs uint32
36 Tweak uint32
37 Flags BloomUpdateType
38 }
39 40 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
41 // This is part of the Message interface implementation.
42 func (msg *MsgFilterLoad) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) (e error) {
43 if pver < BIP0037Version {
44 str := fmt.Sprintf("filterload message invalid for protocol version %d", pver)
45 return messageError("MsgFilterLoad.BtcDecode", str)
46 }
47 if msg.Filter, e = ReadVarBytes(r, pver, MaxFilterLoadFilterSize, "filterload filter size"); E.Chk(e) {
48 return
49 }
50 if e = readElements(r, &msg.HashFuncs, &msg.Tweak, &msg.Flags); E.Chk(e) {
51 return
52 }
53 if msg.HashFuncs > MaxFilterLoadHashFuncs {
54 str := fmt.Sprintf(
55 "too many filter hash functions for message [count %v, max %v]",
56 msg.HashFuncs, MaxFilterLoadHashFuncs,
57 )
58 return messageError("MsgFilterLoad.BtcDecode", str)
59 }
60 return
61 }
62 63 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. This is part of the Message interface
64 // implementation.
65 func (msg *MsgFilterLoad) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) (e error) {
66 if pver < BIP0037Version {
67 str := fmt.Sprintf(
68 "filterload message invalid for protocol "+
69 "version %d", pver,
70 )
71 return messageError("MsgFilterLoad.BtcEncode", str)
72 }
73 size := len(msg.Filter)
74 if size > MaxFilterLoadFilterSize {
75 str := fmt.Sprintf(
76 "filterload filter size too large for message "+
77 "[size %v, max %v]", size, MaxFilterLoadFilterSize,
78 )
79 return messageError("MsgFilterLoad.BtcEncode", str)
80 }
81 if msg.HashFuncs > MaxFilterLoadHashFuncs {
82 str := fmt.Sprintf(
83 "too many filter hash functions for message "+
84 "[count %v, max %v]", msg.HashFuncs, MaxFilterLoadHashFuncs,
85 )
86 return messageError("MsgFilterLoad.BtcEncode", str)
87 }
88 if e = WriteVarBytes(w, pver, msg.Filter); E.Chk(e) {
89 return
90 }
91 return writeElements(w, msg.HashFuncs, msg.Tweak, msg.Flags)
92 }
93 94 // Command returns the protocol command string for the message. This is part of the Message interface implementation.
95 func (msg *MsgFilterLoad) Command() string {
96 return CmdFilterLoad
97 }
98 99 // MaxPayloadLength returns the maximum length the payload can be for the receiver. This is part of the Message
100 // interface implementation.
101 func (msg *MsgFilterLoad) MaxPayloadLength(pver uint32) uint32 {
102 // Num filter bytes (varInt) + filter + 4 bytes hash funcs + 4 bytes tweak + 1 byte flags.
103 return uint32(VarIntSerializeSize(MaxFilterLoadFilterSize)) +
104 MaxFilterLoadFilterSize + 9
105 }
106 107 // NewMsgFilterLoad returns a new bitcoin filterload message that conforms to the Message interface. See MsgFilterLoad
108 // for details.
109 func NewMsgFilterLoad(filter []byte, hashFuncs uint32, tweak uint32, flags BloomUpdateType) *MsgFilterLoad {
110 return &MsgFilterLoad{
111 Filter: filter,
112 HashFuncs: hashFuncs,
113 Tweak: tweak,
114 Flags: flags,
115 }
116 }
117