github.com/klaytn/klaytn@v1.12.1/blockchain/types/receipt.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from core/types/receipt.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package types
    22  
    23  import (
    24  	"fmt"
    25  	"io"
    26  	"unsafe"
    27  
    28  	"github.com/klaytn/klaytn/common"
    29  	"github.com/klaytn/klaytn/common/hexutil"
    30  	"github.com/klaytn/klaytn/log"
    31  	"github.com/klaytn/klaytn/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  	logger                     = log.NewModuleLogger(log.BlockchainTypes)
    40  )
    41  
    42  const (
    43  	// ReceiptStatusFailed is the status code of a transaction if execution failed.
    44  	ReceiptStatusFailed = uint(0)
    45  
    46  	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
    47  	ReceiptStatusSuccessful = uint(1)
    48  
    49  	// TODO-Klaytn Enable more error below.
    50  	// Klaytn specific
    51  	// NOTE-Klaytn Value should be consecutive from ReceiptStatusFailed to the last ReceiptStatusLast
    52  	//         Add a new ReceiptStatusErrXXX before ReceiptStatusLast
    53  	ReceiptStatusErrDefault                              = uint(0x02) // Default
    54  	ReceiptStatusErrDepth                                = uint(0x03)
    55  	ReceiptStatusErrContractAddressCollision             = uint(0x04)
    56  	ReceiptStatusErrCodeStoreOutOfGas                    = uint(0x05)
    57  	ReceiptStatuserrMaxCodeSizeExceed                    = uint(0x06)
    58  	ReceiptStatusErrOutOfGas                             = uint(0x07)
    59  	ReceiptStatusErrWriteProtection                      = uint(0x08)
    60  	ReceiptStatusErrExecutionReverted                    = uint(0x09)
    61  	ReceiptStatusErrOpcodeComputationCostLimitReached    = uint(0x0a)
    62  	ReceiptStatusErrAddressAlreadyExists                 = uint(0x0b)
    63  	ReceiptStatusErrNotAProgramAccount                   = uint(0x0c)
    64  	ReceiptStatusErrNotHumanReadableAddress              = uint(0x0d)
    65  	ReceiptStatusErrFeeRatioOutOfRange                   = uint(0x0e)
    66  	ReceiptStatusErrAccountKeyFailNotUpdatable           = uint(0x0f)
    67  	ReceiptStatusErrDifferentAccountKeyType              = uint(0x10)
    68  	ReceiptStatusErrAccountKeyNilUninitializable         = uint(0x11)
    69  	ReceiptStatusErrNotOnCurve                           = uint(0x12)
    70  	ReceiptStatusErrZeroKeyWeight                        = uint(0x13)
    71  	ReceiptStatusErrUnserializableKey                    = uint(0x14)
    72  	ReceiptStatusErrDuplicatedKey                        = uint(0x15)
    73  	ReceiptStatusErrWeightedSumOverflow                  = uint(0x16)
    74  	ReceiptStatusErrUnsatisfiableThreshold               = uint(0x17)
    75  	ReceiptStatusErrZeroLength                           = uint(0x18)
    76  	ReceiptStatusErrLengthTooLong                        = uint(0x19)
    77  	ReceiptStatusErrNestedRoleBasedKey                   = uint(0x1a)
    78  	ReceiptStatusErrLegacyTransactionMustBeWithLegacyKey = uint(0x1b)
    79  	ReceiptStatusErrDeprecated                           = uint(0x1c)
    80  	ReceiptStatusErrNotSupported                         = uint(0x1d)
    81  	ReceiptStatusErrInvalidCodeFormat                    = uint(0x1e)
    82  	ReceiptStatusLast                                    = uint(0x1f) // Last value which is not an actual ReceiptStatus
    83  //	ReceiptStatusErrInvalidJumpDestination   // TODO-Klaytn-Issue615
    84  //	ReceiptStatusErrInvalidOpcode            // Default case, because no static message available
    85  //	ReceiptStatusErrStackUnderflow           // Default case, because no static message available
    86  //	ReceiptStatusErrStackOverflow            // Default case, because no static message available
    87  //	ReceiptStatusErrInsufficientBalance      // No receipt available for this error
    88  //	ReceiptStatusErrTotalTimeLimitReached    // No receipt available for this error
    89  //	ReceiptStatusErrGasUintOverflow          // TODO-Klaytn-Issue615
    90  
    91  )
    92  
    93  // Receipt represents the results of a transaction.
    94  type Receipt struct {
    95  	// Consensus fields
    96  	Status uint   `json:"status"`
    97  	Bloom  Bloom  `json:"logsBloom"         gencodec:"required"`
    98  	Logs   []*Log `json:"logs"              gencodec:"required"`
    99  
   100  	// Implementation fields (don't reorder!)
   101  	TxHash          common.Hash    `json:"transactionHash" gencodec:"required"`
   102  	ContractAddress common.Address `json:"contractAddress"`
   103  	GasUsed         uint64         `json:"gasUsed" gencodec:"required"`
   104  }
   105  
   106  type receiptMarshaling struct {
   107  	Status  hexutil.Uint
   108  	GasUsed hexutil.Uint64
   109  }
   110  
   111  // receiptRLP is the consensus encoding of a receipt.
   112  type receiptRLP struct {
   113  	Status  uint
   114  	GasUsed uint64
   115  	Bloom   Bloom
   116  	Logs    []*Log
   117  }
   118  
   119  type receiptStorageRLP struct {
   120  	Status          uint
   121  	Bloom           Bloom
   122  	TxHash          common.Hash
   123  	ContractAddress common.Address
   124  	Logs            []*LogForStorage
   125  	GasUsed         uint64
   126  }
   127  
   128  // NewReceipt creates a barebone transaction receipt, copying the init fields.
   129  func NewReceipt(status uint, txHash common.Hash, gasUsed uint64) *Receipt {
   130  	return &Receipt{
   131  		Status:  status,
   132  		TxHash:  txHash,
   133  		GasUsed: gasUsed,
   134  	}
   135  }
   136  
   137  // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt
   138  // into an RLP stream. If no post state is present, byzantium fork is assumed.
   139  func (r *Receipt) EncodeRLP(w io.Writer) error {
   140  	return rlp.Encode(w, &receiptRLP{r.Status, r.GasUsed, r.Bloom, r.Logs})
   141  }
   142  
   143  // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
   144  // from an RLP stream.
   145  func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
   146  	var dec receiptRLP
   147  	if err := s.Decode(&dec); err != nil {
   148  		return err
   149  	}
   150  	r.Status = dec.Status
   151  	r.GasUsed, r.Bloom, r.Logs = dec.GasUsed, dec.Bloom, dec.Logs
   152  	return nil
   153  }
   154  
   155  // Size returns the approximate memory used by all internal contents. It is used
   156  // to approximate and limit the memory consumption of various caches.
   157  func (r *Receipt) Size() common.StorageSize {
   158  	size := common.StorageSize(unsafe.Sizeof(*r))
   159  
   160  	size += common.StorageSize(len(r.Logs)) * common.StorageSize(unsafe.Sizeof(Log{}))
   161  	for _, log := range r.Logs {
   162  		size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data))
   163  	}
   164  	return size
   165  }
   166  
   167  // String implements the Stringer interface.
   168  func (r *Receipt) String() string {
   169  	return fmt.Sprintf("receipt{status=%d gas=%v bloom=%x logs=%v}", r.Status, r.GasUsed, r.Bloom, r.Logs)
   170  }
   171  
   172  // ReceiptForStorage is a wrapper around a Receipt that flattens and parses the
   173  // entire content of a receipt, as opposed to only the consensus fields originally.
   174  type ReceiptForStorage Receipt
   175  
   176  // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
   177  // into an RLP stream.
   178  func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
   179  	enc := &receiptStorageRLP{
   180  		Status:          r.Status,
   181  		Bloom:           r.Bloom,
   182  		TxHash:          r.TxHash,
   183  		ContractAddress: r.ContractAddress,
   184  		Logs:            make([]*LogForStorage, len(r.Logs)),
   185  		GasUsed:         r.GasUsed,
   186  	}
   187  	for i, log := range r.Logs {
   188  		enc.Logs[i] = (*LogForStorage)(log)
   189  	}
   190  	return rlp.Encode(w, enc)
   191  }
   192  
   193  // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
   194  // fields of a receipt from an RLP stream.
   195  func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
   196  	var dec receiptStorageRLP
   197  	if err := s.Decode(&dec); err != nil {
   198  		return err
   199  	}
   200  	r.Status = dec.Status
   201  
   202  	// Assign the consensus fields
   203  	r.Bloom = dec.Bloom
   204  	r.Logs = make([]*Log, len(dec.Logs))
   205  	for i, log := range dec.Logs {
   206  		r.Logs[i] = (*Log)(log)
   207  	}
   208  	// Assign the implementation fields
   209  	r.TxHash, r.ContractAddress, r.GasUsed = dec.TxHash, dec.ContractAddress, dec.GasUsed
   210  	return nil
   211  }
   212  
   213  // Receipts is a wrapper around a Receipt array to implement DerivableList.
   214  type Receipts []*Receipt
   215  
   216  // Len returns the number of receipts in this list.
   217  func (r Receipts) Len() int { return len(r) }
   218  
   219  // GetRlp returns the RLP encoding of one receipt from the list.
   220  func (r Receipts) GetRlp(i int) []byte {
   221  	bytes, err := rlp.EncodeToBytes(r[i])
   222  	if err != nil {
   223  		panic(err)
   224  	}
   225  	return bytes
   226  }