github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/wire/msgblock.go (about) 1 // Copyright (c) 2013-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 "bytes" 10 "fmt" 11 "io" 12 ) 13 14 // defaultTransactionAlloc is the default size used for the backing array 15 // for transactions. The transaction array will dynamically grow as needed, but 16 // this figure is intended to provide enough space for the number of 17 // transactions in the vast majority of blocks without needing to grow the 18 // backing array multiple times. 19 const defaultTransactionAlloc = 2048 20 21 // MaxBlocksPerMsg is the maximum number of blocks allowed per message. 22 const MaxBlocksPerMsg = 500 23 24 // MaxBlockPayload is the maximum bytes a block message can be in bytes. 25 const MaxBlockPayload = 1000000 // Not actually 1MB which would be 1024 * 1024 26 27 // maxTxPerBlock is the maximum number of transactions that could 28 // possibly fit into a block. 29 const maxTxPerBlock = (MaxBlockPayload / minTxPayload) + 1 30 31 // TxLoc holds locator data for the offset and length of where a transaction is 32 // located within a MsgBlock data buffer. 33 type TxLoc struct { 34 TxStart int 35 TxLen int 36 } 37 38 // MsgBlock implements the Message interface and represents a bitcoin 39 // block message. It is used to deliver block and transaction information in 40 // response to a getdata message (MsgGetData) for a given block hash. 41 type MsgBlock struct { 42 Header BlockHeader 43 Transactions []*MsgTx 44 } 45 46 // AddTransaction adds a transaction to the message. 47 func (msg *MsgBlock) AddTransaction(tx *MsgTx) error { 48 msg.Transactions = append(msg.Transactions, tx) 49 return nil 50 51 } 52 53 // ClearTransactions removes all transactions from the message. 54 func (msg *MsgBlock) ClearTransactions() { 55 msg.Transactions = make([]*MsgTx, 0, defaultTransactionAlloc) 56 } 57 58 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. 59 // This is part of the Message interface implementation. 60 // See Deserialize for decoding blocks stored to disk, such as in a database, as 61 // opposed to decoding blocks from the wire. 62 func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32) error { 63 err := readBlockHeader(r, pver, &msg.Header) 64 if err != nil { 65 return err 66 } 67 68 txCount, err := ReadVarInt(r, pver) 69 if err != nil { 70 return err 71 } 72 73 // Prevent more transactions than could possibly fit into a block. 74 // It would be possible to cause memory exhaustion and panics without 75 // a sane upper bound on this count. 76 if txCount > maxTxPerBlock { 77 str := fmt.Sprintf("too many transactions to fit into a block "+ 78 "[count %d, max %d]", txCount, maxTxPerBlock) 79 return messageError("MsgBlock.BtcDecode", str) 80 } 81 82 msg.Transactions = make([]*MsgTx, 0, txCount) 83 for i := uint64(0); i < txCount; i++ { 84 tx := MsgTx{} 85 err := tx.BtcDecode(r, pver) 86 if err != nil { 87 return err 88 } 89 msg.Transactions = append(msg.Transactions, &tx) 90 } 91 92 return nil 93 } 94 95 // Deserialize decodes a block from r into the receiver using a format that is 96 // suitable for long-term storage such as a database while respecting the 97 // Version field in the block. This function differs from BtcDecode in that 98 // BtcDecode decodes from the bitcoin wire protocol as it was sent across the 99 // network. The wire encoding can technically differ depending on the protocol 100 // version and doesn't even really need to match the format of a stored block at 101 // all. As of the time this comment was written, the encoded block is the same 102 // in both instances, but there is a distinct difference and separating the two 103 // allows the API to be flexible enough to deal with changes. 104 func (msg *MsgBlock) Deserialize(r io.Reader) error { 105 // At the current time, there is no difference between the wire encoding 106 // at protocol version 0 and the stable long-term storage format. As 107 // a result, make use of BtcDecode. 108 return msg.BtcDecode(r, 0) 109 } 110 111 // DeserializeTxLoc decodes r in the same manner Deserialize does, but it takes 112 // a byte buffer instead of a generic reader and returns a slice containing the 113 // start and length of each transaction within the raw data that is being 114 // deserialized. 115 func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { 116 fullLen := r.Len() 117 118 // At the current time, there is no difference between the wire encoding 119 // at protocol version 0 and the stable long-term storage format. As 120 // a result, make use of existing wire protocol functions. 121 err := readBlockHeader(r, 0, &msg.Header) 122 if err != nil { 123 return nil, err 124 } 125 126 txCount, err := ReadVarInt(r, 0) 127 if err != nil { 128 return nil, err 129 } 130 131 // Prevent more transactions than could possibly fit into a block. 132 // It would be possible to cause memory exhaustion and panics without 133 // a sane upper bound on this count. 134 if txCount > maxTxPerBlock { 135 str := fmt.Sprintf("too many transactions to fit into a block "+ 136 "[count %d, max %d]", txCount, maxTxPerBlock) 137 return nil, messageError("MsgBlock.DeserializeTxLoc", str) 138 } 139 140 // Deserialize each transaction while keeping track of its location 141 // within the byte stream. 142 msg.Transactions = make([]*MsgTx, 0, txCount) 143 txLocs := make([]TxLoc, txCount) 144 for i := uint64(0); i < txCount; i++ { 145 txLocs[i].TxStart = fullLen - r.Len() 146 tx := MsgTx{} 147 err := tx.Deserialize(r) 148 if err != nil { 149 return nil, err 150 } 151 msg.Transactions = append(msg.Transactions, &tx) 152 txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart 153 } 154 155 return txLocs, nil 156 } 157 158 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. 159 // This is part of the Message interface implementation. 160 // See Serialize for encoding blocks to be stored to disk, such as in a 161 // database, as opposed to encoding blocks for the wire. 162 func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32) error { 163 err := writeBlockHeader(w, pver, &msg.Header) 164 if err != nil { 165 return err 166 } 167 168 err = WriteVarInt(w, pver, uint64(len(msg.Transactions))) 169 if err != nil { 170 return err 171 } 172 173 for _, tx := range msg.Transactions { 174 err = tx.BtcEncode(w, pver) 175 if err != nil { 176 return err 177 } 178 } 179 180 return nil 181 } 182 183 // Serialize encodes the block to w using a format that suitable for long-term 184 // storage such as a database while respecting the Version field in the block. 185 // This function differs from BtcEncode in that BtcEncode encodes the block to 186 // the bitcoin wire protocol in order to be sent across the network. The wire 187 // encoding can technically differ depending on the protocol version and doesn't 188 // even really need to match the format of a stored block at all. As of the 189 // time this comment was written, the encoded block is the same in both 190 // instances, but there is a distinct difference and separating the two allows 191 // the API to be flexible enough to deal with changes. 192 func (msg *MsgBlock) Serialize(w io.Writer) error { 193 // At the current time, there is no difference between the wire encoding 194 // at protocol version 0 and the stable long-term storage format. As 195 // a result, make use of BtcEncode. 196 return msg.BtcEncode(w, 0) 197 } 198 199 // SerializeSize returns the number of bytes it would take to serialize the 200 // the block. 201 func (msg *MsgBlock) SerializeSize() int { 202 // Block header bytes + Serialized varint size for the number of 203 // transactions. 204 n := blockHeaderLen + VarIntSerializeSize(uint64(len(msg.Transactions))) 205 206 for _, tx := range msg.Transactions { 207 n += tx.SerializeSize() 208 } 209 210 return n 211 } 212 213 // Command returns the protocol command string for the message. This is part 214 // of the Message interface implementation. 215 func (msg *MsgBlock) Command() string { 216 return CmdBlock 217 } 218 219 // MaxPayloadLength returns the maximum length the payload can be for the 220 // receiver. This is part of the Message interface implementation. 221 func (msg *MsgBlock) MaxPayloadLength(pver uint32) uint32 { 222 // Block header at 80 bytes + transaction count + max transactions 223 // which can vary up to the MaxBlockPayload (including the block header 224 // and transaction count). 225 return MaxBlockPayload 226 } 227 228 // BlockSha computes the block identifier hash for this block. 229 func (msg *MsgBlock) BlockSha() ShaHash { 230 return msg.Header.BlockSha() 231 } 232 233 // TxShas returns a slice of hashes of all of transactions in this block. 234 func (msg *MsgBlock) TxShas() ([]ShaHash, error) { 235 shaList := make([]ShaHash, 0, len(msg.Transactions)) 236 for _, tx := range msg.Transactions { 237 shaList = append(shaList, tx.TxSha()) 238 } 239 return shaList, nil 240 } 241 242 // NewMsgBlock returns a new bitcoin block message that conforms to the 243 // Message interface. See MsgBlock for details. 244 func NewMsgBlock(blockHeader *BlockHeader) *MsgBlock { 245 return &MsgBlock{ 246 Header: *blockHeader, 247 Transactions: make([]*MsgTx, 0, defaultTransactionAlloc), 248 } 249 }