github.com/btcsuite/btcd@v0.24.0/wire/msgblock.go (about) 1 // Copyright (c) 2013-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 "bytes" 9 "fmt" 10 "io" 11 12 "github.com/btcsuite/btcd/chaincfg/chainhash" 13 ) 14 15 // defaultTransactionAlloc is the default size used for the backing array 16 // for transactions. The transaction array will dynamically grow as needed, but 17 // this figure is intended to provide enough space for the number of 18 // transactions in the vast majority of blocks without needing to grow the 19 // backing array multiple times. 20 const defaultTransactionAlloc = 2048 21 22 // MaxBlocksPerMsg is the maximum number of blocks allowed per message. 23 const MaxBlocksPerMsg = 500 24 25 // MaxBlockPayload is the maximum bytes a block message can be in bytes. 26 // After Segregated Witness, the max block payload has been raised to 4MB. 27 const MaxBlockPayload = 4000000 28 29 // maxTxPerBlock is the maximum number of transactions that could 30 // possibly fit into a block. 31 const maxTxPerBlock = (MaxBlockPayload / minTxPayload) + 1 32 33 // TxLoc holds locator data for the offset and length of where a transaction is 34 // located within a MsgBlock data buffer. 35 type TxLoc struct { 36 TxStart int 37 TxLen int 38 } 39 40 // MsgBlock implements the Message interface and represents a bitcoin 41 // block message. It is used to deliver block and transaction information in 42 // response to a getdata message (MsgGetData) for a given block hash. 43 type MsgBlock struct { 44 Header BlockHeader 45 Transactions []*MsgTx 46 } 47 48 // AddTransaction adds a transaction to the message. 49 func (msg *MsgBlock) AddTransaction(tx *MsgTx) error { 50 msg.Transactions = append(msg.Transactions, tx) 51 return nil 52 53 } 54 55 // ClearTransactions removes all transactions from the message. 56 func (msg *MsgBlock) ClearTransactions() { 57 msg.Transactions = make([]*MsgTx, 0, defaultTransactionAlloc) 58 } 59 60 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. 61 // This is part of the Message interface implementation. 62 // See Deserialize for decoding blocks stored to disk, such as in a database, as 63 // opposed to decoding blocks from the wire. 64 func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { 65 buf := binarySerializer.Borrow() 66 defer binarySerializer.Return(buf) 67 68 err := readBlockHeaderBuf(r, pver, &msg.Header, buf) 69 if err != nil { 70 return err 71 } 72 73 txCount, err := ReadVarIntBuf(r, pver, buf) 74 if err != nil { 75 return err 76 } 77 78 // Prevent more transactions than could possibly fit into a block. 79 // It would be possible to cause memory exhaustion and panics without 80 // a sane upper bound on this count. 81 if txCount > maxTxPerBlock { 82 str := fmt.Sprintf("too many transactions to fit into a block "+ 83 "[count %d, max %d]", txCount, maxTxPerBlock) 84 return messageError("MsgBlock.BtcDecode", str) 85 } 86 87 scriptBuf := scriptPool.Borrow() 88 defer scriptPool.Return(scriptBuf) 89 90 msg.Transactions = make([]*MsgTx, 0, txCount) 91 for i := uint64(0); i < txCount; i++ { 92 tx := MsgTx{} 93 err := tx.btcDecode(r, pver, enc, buf, scriptBuf[:]) 94 if err != nil { 95 return err 96 } 97 msg.Transactions = append(msg.Transactions, &tx) 98 } 99 100 return nil 101 } 102 103 // Deserialize decodes a block from r into the receiver using a format that is 104 // suitable for long-term storage such as a database while respecting the 105 // Version field in the block. This function differs from BtcDecode in that 106 // BtcDecode decodes from the bitcoin wire protocol as it was sent across the 107 // network. The wire encoding can technically differ depending on the protocol 108 // version and doesn't even really need to match the format of a stored block at 109 // all. As of the time this comment was written, the encoded block is the same 110 // in both instances, but there is a distinct difference and separating the two 111 // allows the API to be flexible enough to deal with changes. 112 func (msg *MsgBlock) Deserialize(r io.Reader) error { 113 // At the current time, there is no difference between the wire encoding 114 // at protocol version 0 and the stable long-term storage format. As 115 // a result, make use of BtcDecode. 116 // 117 // Passing an encoding type of WitnessEncoding to BtcEncode for the 118 // MessageEncoding parameter indicates that the transactions within the 119 // block are expected to be serialized according to the new 120 // serialization structure defined in BIP0141. 121 return msg.BtcDecode(r, 0, WitnessEncoding) 122 } 123 124 // DeserializeNoWitness decodes a block from r into the receiver similar to 125 // Deserialize, however DeserializeWitness strips all (if any) witness data 126 // from the transactions within the block before encoding them. 127 func (msg *MsgBlock) DeserializeNoWitness(r io.Reader) error { 128 return msg.BtcDecode(r, 0, BaseEncoding) 129 } 130 131 // DeserializeTxLoc decodes r in the same manner Deserialize does, but it takes 132 // a byte buffer instead of a generic reader and returns a slice containing the 133 // start and length of each transaction within the raw data that is being 134 // deserialized. 135 func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { 136 fullLen := r.Len() 137 138 buf := binarySerializer.Borrow() 139 defer binarySerializer.Return(buf) 140 141 // At the current time, there is no difference between the wire encoding 142 // at protocol version 0 and the stable long-term storage format. As 143 // a result, make use of existing wire protocol functions. 144 err := readBlockHeaderBuf(r, 0, &msg.Header, buf) 145 if err != nil { 146 return nil, err 147 } 148 149 txCount, err := ReadVarIntBuf(r, 0, buf) 150 if err != nil { 151 return nil, err 152 } 153 154 // Prevent more transactions than could possibly fit into a block. 155 // It would be possible to cause memory exhaustion and panics without 156 // a sane upper bound on this count. 157 if txCount > maxTxPerBlock { 158 str := fmt.Sprintf("too many transactions to fit into a block "+ 159 "[count %d, max %d]", txCount, maxTxPerBlock) 160 return nil, messageError("MsgBlock.DeserializeTxLoc", str) 161 } 162 163 scriptBuf := scriptPool.Borrow() 164 defer scriptPool.Return(scriptBuf) 165 166 // Deserialize each transaction while keeping track of its location 167 // within the byte stream. 168 msg.Transactions = make([]*MsgTx, 0, txCount) 169 txLocs := make([]TxLoc, txCount) 170 for i := uint64(0); i < txCount; i++ { 171 txLocs[i].TxStart = fullLen - r.Len() 172 tx := MsgTx{} 173 err := tx.btcDecode(r, 0, WitnessEncoding, buf, scriptBuf[:]) 174 if err != nil { 175 return nil, err 176 } 177 msg.Transactions = append(msg.Transactions, &tx) 178 txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart 179 } 180 181 return txLocs, nil 182 } 183 184 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. 185 // This is part of the Message interface implementation. 186 // See Serialize for encoding blocks to be stored to disk, such as in a 187 // database, as opposed to encoding blocks for the wire. 188 func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { 189 buf := binarySerializer.Borrow() 190 defer binarySerializer.Return(buf) 191 192 err := writeBlockHeaderBuf(w, pver, &msg.Header, buf) 193 if err != nil { 194 return err 195 } 196 197 err = WriteVarIntBuf(w, pver, uint64(len(msg.Transactions)), buf) 198 if err != nil { 199 return err 200 } 201 202 for _, tx := range msg.Transactions { 203 err = tx.btcEncode(w, pver, enc, buf) 204 if err != nil { 205 return err 206 } 207 } 208 209 return nil 210 } 211 212 // Serialize encodes the block to w using a format that suitable for long-term 213 // storage such as a database while respecting the Version field in the block. 214 // This function differs from BtcEncode in that BtcEncode encodes the block to 215 // the bitcoin wire protocol in order to be sent across the network. The wire 216 // encoding can technically differ depending on the protocol version and doesn't 217 // even really need to match the format of a stored block at all. As of the 218 // time this comment was written, the encoded block is the same in both 219 // instances, but there is a distinct difference and separating the two allows 220 // the API to be flexible enough to deal with changes. 221 func (msg *MsgBlock) Serialize(w io.Writer) error { 222 // At the current time, there is no difference between the wire encoding 223 // at protocol version 0 and the stable long-term storage format. As 224 // a result, make use of BtcEncode. 225 // 226 // Passing WitnessEncoding as the encoding type here indicates that 227 // each of the transactions should be serialized using the witness 228 // serialization structure defined in BIP0141. 229 return msg.BtcEncode(w, 0, WitnessEncoding) 230 } 231 232 // SerializeNoWitness encodes a block to w using an identical format to 233 // Serialize, with all (if any) witness data stripped from all transactions. 234 // This method is provided in additon to the regular Serialize, in order to 235 // allow one to selectively encode transaction witness data to non-upgraded 236 // peers which are unaware of the new encoding. 237 func (msg *MsgBlock) SerializeNoWitness(w io.Writer) error { 238 return msg.BtcEncode(w, 0, BaseEncoding) 239 } 240 241 // SerializeSize returns the number of bytes it would take to serialize the 242 // block, factoring in any witness data within transaction. 243 func (msg *MsgBlock) SerializeSize() int { 244 // Block header bytes + Serialized varint size for the number of 245 // transactions. 246 n := blockHeaderLen + VarIntSerializeSize(uint64(len(msg.Transactions))) 247 248 for _, tx := range msg.Transactions { 249 n += tx.SerializeSize() 250 } 251 252 return n 253 } 254 255 // SerializeSizeStripped returns the number of bytes it would take to serialize 256 // the block, excluding any witness data (if any). 257 func (msg *MsgBlock) SerializeSizeStripped() int { 258 // Block header bytes + Serialized varint size for the number of 259 // transactions. 260 n := blockHeaderLen + VarIntSerializeSize(uint64(len(msg.Transactions))) 261 262 for _, tx := range msg.Transactions { 263 n += tx.SerializeSizeStripped() 264 } 265 266 return n 267 } 268 269 // Command returns the protocol command string for the message. This is part 270 // of the Message interface implementation. 271 func (msg *MsgBlock) Command() string { 272 return CmdBlock 273 } 274 275 // MaxPayloadLength returns the maximum length the payload can be for the 276 // receiver. This is part of the Message interface implementation. 277 func (msg *MsgBlock) MaxPayloadLength(pver uint32) uint32 { 278 // Block header at 80 bytes + transaction count + max transactions 279 // which can vary up to the MaxBlockPayload (including the block header 280 // and transaction count). 281 return MaxBlockPayload 282 } 283 284 // BlockHash computes the block identifier hash for this block. 285 func (msg *MsgBlock) BlockHash() chainhash.Hash { 286 return msg.Header.BlockHash() 287 } 288 289 // TxHashes returns a slice of hashes of all of transactions in this block. 290 func (msg *MsgBlock) TxHashes() ([]chainhash.Hash, error) { 291 hashList := make([]chainhash.Hash, 0, len(msg.Transactions)) 292 for _, tx := range msg.Transactions { 293 hashList = append(hashList, tx.TxHash()) 294 } 295 return hashList, nil 296 } 297 298 // NewMsgBlock returns a new bitcoin block message that conforms to the 299 // Message interface. See MsgBlock for details. 300 func NewMsgBlock(blockHeader *BlockHeader) *MsgBlock { 301 return &MsgBlock{ 302 Header: *blockHeader, 303 Transactions: make([]*MsgTx, 0, defaultTransactionAlloc), 304 } 305 }