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