github.com/haliliceylan/bsc@v1.1.10-0.20220501224556-eb78d644ebcb/core/types/receipt.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package types 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 "io" 24 "math/big" 25 "unsafe" 26 27 "github.com/ethereum/go-ethereum/common" 28 "github.com/ethereum/go-ethereum/common/hexutil" 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/params" 31 "github.com/ethereum/go-ethereum/rlp" 32 ) 33 34 //go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go 35 36 var ( 37 receiptStatusFailedRLP = []byte{} 38 receiptStatusSuccessfulRLP = []byte{0x01} 39 ) 40 41 // This error is returned when a typed receipt is decoded, but the string is empty. 42 var errEmptyTypedReceipt = errors.New("empty typed receipt bytes") 43 44 const ( 45 // ReceiptStatusFailed is the status code of a transaction if execution failed. 46 ReceiptStatusFailed = uint64(0) 47 48 // ReceiptStatusSuccessful is the status code of a transaction if execution succeeded. 49 ReceiptStatusSuccessful = uint64(1) 50 ) 51 52 // Receipt represents the results of a transaction. 53 type OriginalDataAndReceipt struct { 54 Receipt Receipt `json:"receipt"` 55 TxData Transaction `json:"txData"` 56 } 57 58 // Receipt represents the results of a transaction. 59 type Receipt struct { 60 // Consensus fields: These fields are defined by the Yellow Paper 61 Type uint8 `json:"type,omitempty"` 62 PostState []byte `json:"root"` 63 Status uint64 `json:"status"` 64 CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"` 65 Bloom Bloom `json:"logsBloom" gencodec:"required"` 66 Logs []*Log `json:"logs" gencodec:"required"` 67 68 // Implementation fields: These fields are added by geth when processing a transaction. 69 // They are stored in the chain database. 70 TxHash common.Hash `json:"transactionHash" gencodec:"required"` 71 ContractAddress common.Address `json:"contractAddress"` 72 GasUsed uint64 `json:"gasUsed" gencodec:"required"` 73 74 // Inclusion information: These fields provide information about the inclusion of the 75 // transaction corresponding to this receipt. 76 BlockHash common.Hash `json:"blockHash,omitempty"` 77 BlockNumber *big.Int `json:"blockNumber,omitempty"` 78 TransactionIndex uint `json:"transactionIndex"` 79 } 80 81 type receiptMarshaling struct { 82 Type hexutil.Uint64 83 PostState hexutil.Bytes 84 Status hexutil.Uint64 85 CumulativeGasUsed hexutil.Uint64 86 GasUsed hexutil.Uint64 87 BlockNumber *hexutil.Big 88 TransactionIndex hexutil.Uint 89 } 90 91 // receiptRLP is the consensus encoding of a receipt. 92 type receiptRLP struct { 93 PostStateOrStatus []byte 94 CumulativeGasUsed uint64 95 Bloom Bloom 96 Logs []*Log 97 } 98 99 // storedReceiptRLP is the storage encoding of a receipt. 100 type storedReceiptRLP struct { 101 PostStateOrStatus []byte 102 CumulativeGasUsed uint64 103 Logs []*LogForStorage 104 } 105 106 // v4StoredReceiptRLP is the storage encoding of a receipt used in database version 4. 107 type v4StoredReceiptRLP struct { 108 PostStateOrStatus []byte 109 CumulativeGasUsed uint64 110 TxHash common.Hash 111 ContractAddress common.Address 112 Logs []*LogForStorage 113 GasUsed uint64 114 } 115 116 // v3StoredReceiptRLP is the original storage encoding of a receipt including some unnecessary fields. 117 type v3StoredReceiptRLP struct { 118 PostStateOrStatus []byte 119 CumulativeGasUsed uint64 120 Bloom Bloom 121 TxHash common.Hash 122 ContractAddress common.Address 123 Logs []*LogForStorage 124 GasUsed uint64 125 } 126 127 // NewReceipt creates a barebone transaction receipt, copying the init fields. 128 // Deprecated: create receipts using a struct literal instead. 129 func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt { 130 r := &Receipt{ 131 Type: LegacyTxType, 132 PostState: common.CopyBytes(root), 133 CumulativeGasUsed: cumulativeGasUsed, 134 } 135 if failed { 136 r.Status = ReceiptStatusFailed 137 } else { 138 r.Status = ReceiptStatusSuccessful 139 } 140 return r 141 } 142 143 // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt 144 // into an RLP stream. If no post state is present, byzantium fork is assumed. 145 func (r *Receipt) EncodeRLP(w io.Writer) error { 146 data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs} 147 if r.Type == LegacyTxType { 148 return rlp.Encode(w, data) 149 } 150 // It's an EIP-2718 typed TX receipt. 151 if r.Type != AccessListTxType { 152 return ErrTxTypeNotSupported 153 } 154 buf := encodeBufferPool.Get().(*bytes.Buffer) 155 defer encodeBufferPool.Put(buf) 156 buf.Reset() 157 buf.WriteByte(r.Type) 158 if err := rlp.Encode(buf, data); err != nil { 159 return err 160 } 161 return rlp.Encode(w, buf.Bytes()) 162 } 163 164 // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt 165 // from an RLP stream. 166 func (r *Receipt) DecodeRLP(s *rlp.Stream) error { 167 kind, _, err := s.Kind() 168 switch { 169 case err != nil: 170 return err 171 case kind == rlp.List: 172 // It's a legacy receipt. 173 var dec receiptRLP 174 if err := s.Decode(&dec); err != nil { 175 return err 176 } 177 r.Type = LegacyTxType 178 return r.setFromRLP(dec) 179 case kind == rlp.String: 180 // It's an EIP-2718 typed tx receipt. 181 b, err := s.Bytes() 182 if err != nil { 183 return err 184 } 185 if len(b) == 0 { 186 return errEmptyTypedReceipt 187 } 188 r.Type = b[0] 189 if r.Type == AccessListTxType { 190 var dec receiptRLP 191 if err := rlp.DecodeBytes(b[1:], &dec); err != nil { 192 return err 193 } 194 return r.setFromRLP(dec) 195 } 196 return ErrTxTypeNotSupported 197 default: 198 return rlp.ErrExpectedList 199 } 200 } 201 202 func (r *Receipt) setFromRLP(data receiptRLP) error { 203 r.CumulativeGasUsed, r.Bloom, r.Logs = data.CumulativeGasUsed, data.Bloom, data.Logs 204 return r.setStatus(data.PostStateOrStatus) 205 } 206 207 func (r *Receipt) setStatus(postStateOrStatus []byte) error { 208 switch { 209 case bytes.Equal(postStateOrStatus, receiptStatusSuccessfulRLP): 210 r.Status = ReceiptStatusSuccessful 211 case bytes.Equal(postStateOrStatus, receiptStatusFailedRLP): 212 r.Status = ReceiptStatusFailed 213 case len(postStateOrStatus) == len(common.Hash{}): 214 r.PostState = postStateOrStatus 215 default: 216 return fmt.Errorf("invalid receipt status %x", postStateOrStatus) 217 } 218 return nil 219 } 220 221 func (r *Receipt) statusEncoding() []byte { 222 if len(r.PostState) == 0 { 223 if r.Status == ReceiptStatusFailed { 224 return receiptStatusFailedRLP 225 } 226 return receiptStatusSuccessfulRLP 227 } 228 return r.PostState 229 } 230 231 // Size returns the approximate memory used by all internal contents. It is used 232 // to approximate and limit the memory consumption of various caches. 233 func (r *Receipt) Size() common.StorageSize { 234 size := common.StorageSize(unsafe.Sizeof(*r)) + common.StorageSize(len(r.PostState)) 235 size += common.StorageSize(len(r.Logs)) * common.StorageSize(unsafe.Sizeof(Log{})) 236 for _, log := range r.Logs { 237 size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data)) 238 } 239 return size 240 } 241 242 // ReceiptForStorage is a wrapper around a Receipt that flattens and parses the 243 // entire content of a receipt, as opposed to only the consensus fields originally. 244 type ReceiptForStorage Receipt 245 246 // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt 247 // into an RLP stream. 248 func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { 249 enc := &storedReceiptRLP{ 250 PostStateOrStatus: (*Receipt)(r).statusEncoding(), 251 CumulativeGasUsed: r.CumulativeGasUsed, 252 Logs: make([]*LogForStorage, len(r.Logs)), 253 } 254 for i, log := range r.Logs { 255 enc.Logs[i] = (*LogForStorage)(log) 256 } 257 return rlp.Encode(w, enc) 258 } 259 260 // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation 261 // fields of a receipt from an RLP stream. 262 func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { 263 // Retrieve the entire receipt blob as we need to try multiple decoders 264 blob, err := s.Raw() 265 if err != nil { 266 return err 267 } 268 // Try decoding from the newest format for future proofness, then the older one 269 // for old nodes that just upgraded. V4 was an intermediate unreleased format so 270 // we do need to decode it, but it's not common (try last). 271 if err := decodeStoredReceiptRLP(r, blob); err == nil { 272 return nil 273 } 274 if err := decodeV3StoredReceiptRLP(r, blob); err == nil { 275 return nil 276 } 277 return decodeV4StoredReceiptRLP(r, blob) 278 } 279 280 func decodeStoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { 281 var stored storedReceiptRLP 282 if err := rlp.DecodeBytes(blob, &stored); err != nil { 283 return err 284 } 285 if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { 286 return err 287 } 288 r.CumulativeGasUsed = stored.CumulativeGasUsed 289 r.Logs = make([]*Log, len(stored.Logs)) 290 for i, log := range stored.Logs { 291 r.Logs[i] = (*Log)(log) 292 } 293 r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) 294 295 return nil 296 } 297 298 func decodeV4StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { 299 var stored v4StoredReceiptRLP 300 if err := rlp.DecodeBytes(blob, &stored); err != nil { 301 return err 302 } 303 if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { 304 return err 305 } 306 r.CumulativeGasUsed = stored.CumulativeGasUsed 307 r.TxHash = stored.TxHash 308 r.ContractAddress = stored.ContractAddress 309 r.GasUsed = stored.GasUsed 310 r.Logs = make([]*Log, len(stored.Logs)) 311 for i, log := range stored.Logs { 312 r.Logs[i] = (*Log)(log) 313 } 314 r.Bloom = CreateBloom(Receipts{(*Receipt)(r)}) 315 316 return nil 317 } 318 319 func decodeV3StoredReceiptRLP(r *ReceiptForStorage, blob []byte) error { 320 var stored v3StoredReceiptRLP 321 if err := rlp.DecodeBytes(blob, &stored); err != nil { 322 return err 323 } 324 if err := (*Receipt)(r).setStatus(stored.PostStateOrStatus); err != nil { 325 return err 326 } 327 r.CumulativeGasUsed = stored.CumulativeGasUsed 328 r.Bloom = stored.Bloom 329 r.TxHash = stored.TxHash 330 r.ContractAddress = stored.ContractAddress 331 r.GasUsed = stored.GasUsed 332 r.Logs = make([]*Log, len(stored.Logs)) 333 for i, log := range stored.Logs { 334 r.Logs[i] = (*Log)(log) 335 } 336 return nil 337 } 338 339 // Receipts implements DerivableList for receipts. 340 type Receipts []*Receipt 341 342 // Len returns the number of receipts in this list. 343 func (rs Receipts) Len() int { return len(rs) } 344 345 // EncodeIndex encodes the i'th receipt to w. 346 func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { 347 r := rs[i] 348 data := &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs} 349 switch r.Type { 350 case LegacyTxType: 351 rlp.Encode(w, data) 352 case AccessListTxType: 353 w.WriteByte(AccessListTxType) 354 rlp.Encode(w, data) 355 default: 356 // For unsupported types, write nothing. Since this is for 357 // DeriveSha, the error will be caught matching the derived hash 358 // to the block. 359 } 360 } 361 362 // DeriveFields fills the receipts with their computed fields based on consensus 363 // data and contextual infos like containing block and transactions. 364 func (r Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, txs Transactions) error { 365 signer := MakeSigner(config, new(big.Int).SetUint64(number)) 366 367 logIndex := uint(0) 368 if len(txs) != len(r) { 369 return errors.New("transaction and receipt count mismatch") 370 } 371 for i := 0; i < len(r); i++ { 372 // The transaction type and hash can be retrieved from the transaction itself 373 r[i].Type = txs[i].Type() 374 r[i].TxHash = txs[i].Hash() 375 376 // block location fields 377 r[i].BlockHash = hash 378 r[i].BlockNumber = new(big.Int).SetUint64(number) 379 r[i].TransactionIndex = uint(i) 380 381 // The contract address can be derived from the transaction itself 382 if txs[i].To() == nil { 383 // Deriving the signer is expensive, only do if it's actually needed 384 from, _ := Sender(signer, txs[i]) 385 r[i].ContractAddress = crypto.CreateAddress(from, txs[i].Nonce()) 386 } 387 // The used gas can be calculated based on previous r 388 if i == 0 { 389 r[i].GasUsed = r[i].CumulativeGasUsed 390 } else { 391 r[i].GasUsed = r[i].CumulativeGasUsed - r[i-1].CumulativeGasUsed 392 } 393 // The derived log fields can simply be set from the block and transaction 394 for j := 0; j < len(r[i].Logs); j++ { 395 r[i].Logs[j].BlockNumber = number 396 r[i].Logs[j].BlockHash = hash 397 r[i].Logs[j].TxHash = r[i].TxHash 398 r[i].Logs[j].TxIndex = uint(i) 399 r[i].Logs[j].Index = logIndex 400 logIndex++ 401 } 402 } 403 return nil 404 }