github.com/lbryio/lbcd@v0.22.119/wire/msgmerkleblock.go (about) 1 // Copyright (c) 2014-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package wire 6 7 import ( 8 "fmt" 9 "io" 10 11 "github.com/lbryio/lbcd/chaincfg/chainhash" 12 ) 13 14 // maxFlagsPerMerkleBlock is the maximum number of flag bytes that could 15 // possibly fit into a merkle block. Since each transaction is represented by 16 // a single bit, this is the max number of transactions per block divided by 17 // 8 bits per byte. Then an extra one to cover partials. 18 const maxFlagsPerMerkleBlock = maxTxPerBlock / 8 19 20 // MsgMerkleBlock implements the Message interface and represents a bitcoin 21 // merkleblock message which is used to reset a Bloom filter. 22 // 23 // This message was not added until protocol version BIP0037Version. 24 type MsgMerkleBlock struct { 25 Header BlockHeader 26 Transactions uint32 27 Hashes []*chainhash.Hash 28 Flags []byte 29 } 30 31 // AddTxHash adds a new transaction hash to the message. 32 func (msg *MsgMerkleBlock) AddTxHash(hash *chainhash.Hash) error { 33 if len(msg.Hashes)+1 > maxTxPerBlock { 34 str := fmt.Sprintf("too many tx hashes for message [max %v]", 35 maxTxPerBlock) 36 return messageError("MsgMerkleBlock.AddTxHash", str) 37 } 38 39 msg.Hashes = append(msg.Hashes, hash) 40 return nil 41 } 42 43 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. 44 // This is part of the Message interface implementation. 45 func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { 46 if pver < BIP0037Version { 47 str := fmt.Sprintf("merkleblock message invalid for protocol "+ 48 "version %d", pver) 49 return messageError("MsgMerkleBlock.BtcDecode", str) 50 } 51 52 err := readBlockHeader(r, pver, &msg.Header) 53 if err != nil { 54 return err 55 } 56 57 err = readElement(r, &msg.Transactions) 58 if err != nil { 59 return err 60 } 61 62 // Read num block locator hashes and limit to max. 63 count, err := ReadVarInt(r, pver) 64 if err != nil { 65 return err 66 } 67 if count > maxTxPerBlock { 68 str := fmt.Sprintf("too many transaction hashes for message "+ 69 "[count %v, max %v]", count, maxTxPerBlock) 70 return messageError("MsgMerkleBlock.BtcDecode", str) 71 } 72 73 // Create a contiguous slice of hashes to deserialize into in order to 74 // reduce the number of allocations. 75 hashes := make([]chainhash.Hash, count) 76 msg.Hashes = make([]*chainhash.Hash, 0, count) 77 for i := uint64(0); i < count; i++ { 78 hash := &hashes[i] 79 err := readElement(r, hash) 80 if err != nil { 81 return err 82 } 83 msg.AddTxHash(hash) 84 } 85 86 msg.Flags, err = ReadVarBytes(r, pver, maxFlagsPerMerkleBlock, 87 "merkle block flags size") 88 return err 89 } 90 91 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. 92 // This is part of the Message interface implementation. 93 func (msg *MsgMerkleBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { 94 if pver < BIP0037Version { 95 str := fmt.Sprintf("merkleblock message invalid for protocol "+ 96 "version %d", pver) 97 return messageError("MsgMerkleBlock.BtcEncode", str) 98 } 99 100 // Read num transaction hashes and limit to max. 101 numHashes := len(msg.Hashes) 102 if numHashes > maxTxPerBlock { 103 str := fmt.Sprintf("too many transaction hashes for message "+ 104 "[count %v, max %v]", numHashes, maxTxPerBlock) 105 return messageError("MsgMerkleBlock.BtcDecode", str) 106 } 107 numFlagBytes := len(msg.Flags) 108 if numFlagBytes > maxFlagsPerMerkleBlock { 109 str := fmt.Sprintf("too many flag bytes for message [count %v, "+ 110 "max %v]", numFlagBytes, maxFlagsPerMerkleBlock) 111 return messageError("MsgMerkleBlock.BtcDecode", str) 112 } 113 114 err := writeBlockHeader(w, pver, &msg.Header) 115 if err != nil { 116 return err 117 } 118 119 err = writeElement(w, msg.Transactions) 120 if err != nil { 121 return err 122 } 123 124 err = WriteVarInt(w, pver, uint64(numHashes)) 125 if err != nil { 126 return err 127 } 128 for _, hash := range msg.Hashes { 129 err = writeElement(w, hash) 130 if err != nil { 131 return err 132 } 133 } 134 135 return WriteVarBytes(w, pver, msg.Flags) 136 } 137 138 // Command returns the protocol command string for the message. This is part 139 // of the Message interface implementation. 140 func (msg *MsgMerkleBlock) Command() string { 141 return CmdMerkleBlock 142 } 143 144 // MaxPayloadLength returns the maximum length the payload can be for the 145 // receiver. This is part of the Message interface implementation. 146 func (msg *MsgMerkleBlock) MaxPayloadLength(pver uint32) uint32 { 147 return MaxBlockPayload 148 } 149 150 // NewMsgMerkleBlock returns a new bitcoin merkleblock message that conforms to 151 // the Message interface. See MsgMerkleBlock for details. 152 func NewMsgMerkleBlock(bh *BlockHeader) *MsgMerkleBlock { 153 return &MsgMerkleBlock{ 154 Header: *bh, 155 Transactions: 0, 156 Hashes: make([]*chainhash.Hash, 0), 157 Flags: make([]byte, 0), 158 } 159 }