github.com/palcoin-project/palcd@v1.0.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/palcoin-project/palcd/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 err := readBlockHeader(r, pver, &msg.Header) 66 if err != nil { 67 return err 68 } 69 70 txCount, err := ReadVarInt(r, pver) 71 if err != nil { 72 return err 73 } 74 75 // Prevent more transactions than could possibly fit into a block. 76 // It would be possible to cause memory exhaustion and panics without 77 // a sane upper bound on this count. 78 if txCount > maxTxPerBlock { 79 str := fmt.Sprintf("too many transactions to fit into a block "+ 80 "[count %d, max %d]", txCount, maxTxPerBlock) 81 return messageError("MsgBlock.BtcDecode", str) 82 } 83 84 msg.Transactions = make([]*MsgTx, 0, txCount) 85 for i := uint64(0); i < txCount; i++ { 86 tx := MsgTx{} 87 err := tx.BtcDecode(r, pver, enc) 88 if err != nil { 89 return err 90 } 91 msg.Transactions = append(msg.Transactions, &tx) 92 } 93 94 return nil 95 } 96 97 // Deserialize decodes a block from r into the receiver using a format that is 98 // suitable for long-term storage such as a database while respecting the 99 // Version field in the block. This function differs from BtcDecode in that 100 // BtcDecode decodes from the bitcoin wire protocol as it was sent across the 101 // network. The wire encoding can technically differ depending on the protocol 102 // version and doesn't even really need to match the format of a stored block at 103 // all. As of the time this comment was written, the encoded block is the same 104 // in both instances, but there is a distinct difference and separating the two 105 // allows the API to be flexible enough to deal with changes. 106 func (msg *MsgBlock) Deserialize(r io.Reader) error { 107 // At the current time, there is no difference between the wire encoding 108 // at protocol version 0 and the stable long-term storage format. As 109 // a result, make use of BtcDecode. 110 // 111 // Passing an encoding type of WitnessEncoding to BtcEncode for the 112 // MessageEncoding parameter indicates that the transactions within the 113 // block are expected to be serialized according to the new 114 // serialization structure defined in BIP0141. 115 return msg.BtcDecode(r, 0, WitnessEncoding) 116 } 117 118 // DeserializeNoWitness decodes a block from r into the receiver similar to 119 // Deserialize, however DeserializeWitness strips all (if any) witness data 120 // from the transactions within the block before encoding them. 121 func (msg *MsgBlock) DeserializeNoWitness(r io.Reader) error { 122 return msg.BtcDecode(r, 0, BaseEncoding) 123 } 124 125 // DeserializeTxLoc decodes r in the same manner Deserialize does, but it takes 126 // a byte buffer instead of a generic reader and returns a slice containing the 127 // start and length of each transaction within the raw data that is being 128 // deserialized. 129 func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { 130 fullLen := r.Len() 131 132 // At the current time, there is no difference between the wire encoding 133 // at protocol version 0 and the stable long-term storage format. As 134 // a result, make use of existing wire protocol functions. 135 err := readBlockHeader(r, 0, &msg.Header) 136 if err != nil { 137 return nil, err 138 } 139 140 txCount, err := ReadVarInt(r, 0) 141 if err != nil { 142 return nil, err 143 } 144 145 // Prevent more transactions than could possibly fit into a block. 146 // It would be possible to cause memory exhaustion and panics without 147 // a sane upper bound on this count. 148 if txCount > maxTxPerBlock { 149 str := fmt.Sprintf("too many transactions to fit into a block "+ 150 "[count %d, max %d]", txCount, maxTxPerBlock) 151 return nil, messageError("MsgBlock.DeserializeTxLoc", str) 152 } 153 154 // Deserialize each transaction while keeping track of its location 155 // within the byte stream. 156 msg.Transactions = make([]*MsgTx, 0, txCount) 157 txLocs := make([]TxLoc, txCount) 158 for i := uint64(0); i < txCount; i++ { 159 txLocs[i].TxStart = fullLen - r.Len() 160 tx := MsgTx{} 161 err := tx.Deserialize(r) 162 if err != nil { 163 return nil, err 164 } 165 msg.Transactions = append(msg.Transactions, &tx) 166 txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart 167 } 168 169 return txLocs, nil 170 } 171 172 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. 173 // This is part of the Message interface implementation. 174 // See Serialize for encoding blocks to be stored to disk, such as in a 175 // database, as opposed to encoding blocks for the wire. 176 func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { 177 err := writeBlockHeader(w, pver, &msg.Header) 178 if err != nil { 179 return err 180 } 181 182 err = WriteVarInt(w, pver, uint64(len(msg.Transactions))) 183 if err != nil { 184 return err 185 } 186 187 for _, tx := range msg.Transactions { 188 err = tx.BtcEncode(w, pver, enc) 189 if err != nil { 190 return err 191 } 192 } 193 194 return nil 195 } 196 197 // Serialize encodes the block to w using a format that suitable for long-term 198 // storage such as a database while respecting the Version field in the block. 199 // This function differs from BtcEncode in that BtcEncode encodes the block to 200 // the bitcoin wire protocol in order to be sent across the network. The wire 201 // encoding can technically differ depending on the protocol version and doesn't 202 // even really need to match the format of a stored block at all. As of the 203 // time this comment was written, the encoded block is the same in both 204 // instances, but there is a distinct difference and separating the two allows 205 // the API to be flexible enough to deal with changes. 206 func (msg *MsgBlock) Serialize(w io.Writer) error { 207 // At the current time, there is no difference between the wire encoding 208 // at protocol version 0 and the stable long-term storage format. As 209 // a result, make use of BtcEncode. 210 // 211 // Passing WitnessEncoding as the encoding type here indicates that 212 // each of the transactions should be serialized using the witness 213 // serialization structure defined in BIP0141. 214 return msg.BtcEncode(w, 0, WitnessEncoding) 215 } 216 217 // SerializeNoWitness encodes a block to w using an identical format to 218 // Serialize, with all (if any) witness data stripped from all transactions. 219 // This method is provided in additon to the regular Serialize, in order to 220 // allow one to selectively encode transaction witness data to non-upgraded 221 // peers which are unaware of the new encoding. 222 func (msg *MsgBlock) SerializeNoWitness(w io.Writer) error { 223 return msg.BtcEncode(w, 0, BaseEncoding) 224 } 225 226 // SerializeSize returns the number of bytes it would take to serialize the 227 // block, factoring in any witness data within transaction. 228 func (msg *MsgBlock) SerializeSize() int { 229 // Block header bytes + Serialized varint size for the number of 230 // transactions. 231 n := blockHeaderLen + VarIntSerializeSize(uint64(len(msg.Transactions))) 232 233 for _, tx := range msg.Transactions { 234 n += tx.SerializeSize() 235 } 236 237 return n 238 } 239 240 // SerializeSizeStripped returns the number of bytes it would take to serialize 241 // the block, excluding any witness data (if any). 242 func (msg *MsgBlock) SerializeSizeStripped() int { 243 // Block header bytes + Serialized varint size for the number of 244 // transactions. 245 n := blockHeaderLen + VarIntSerializeSize(uint64(len(msg.Transactions))) 246 247 for _, tx := range msg.Transactions { 248 n += tx.SerializeSizeStripped() 249 } 250 251 return n 252 } 253 254 // Command returns the protocol command string for the message. This is part 255 // of the Message interface implementation. 256 func (msg *MsgBlock) Command() string { 257 return CmdBlock 258 } 259 260 // MaxPayloadLength returns the maximum length the payload can be for the 261 // receiver. This is part of the Message interface implementation. 262 func (msg *MsgBlock) MaxPayloadLength(pver uint32) uint32 { 263 // Block header at 80 bytes + transaction count + max transactions 264 // which can vary up to the MaxBlockPayload (including the block header 265 // and transaction count). 266 return MaxBlockPayload 267 } 268 269 // BlockHash computes the block identifier hash for this block. 270 func (msg *MsgBlock) BlockHash() chainhash.Hash { 271 return msg.Header.BlockHash() 272 } 273 274 // TxHashes returns a slice of hashes of all of transactions in this block. 275 func (msg *MsgBlock) TxHashes() ([]chainhash.Hash, error) { 276 hashList := make([]chainhash.Hash, 0, len(msg.Transactions)) 277 for _, tx := range msg.Transactions { 278 hashList = append(hashList, tx.TxHash()) 279 } 280 return hashList, nil 281 } 282 283 // NewMsgBlock returns a new bitcoin block message that conforms to the 284 // Message interface. See MsgBlock for details. 285 func NewMsgBlock(blockHeader *BlockHeader) *MsgBlock { 286 return &MsgBlock{ 287 Header: *blockHeader, 288 Transactions: make([]*MsgTx, 0, defaultTransactionAlloc), 289 } 290 }