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  }