text: // Copyright 2014 The go-ethereum Authors
  // This file is part of the go-ethereum library.
  //
  // The go-ethereum library is free software: you can redistribute it and/or modify
  // it under the terms of the GNU Lesser General Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  //
  // The go-ethereum library is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  // GNU Lesser General Public License for more details.
  //
  // You should have received a copy of the GNU Lesser General Public License
  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  
  package types
  
  import (
  	"bytes"
  	"fmt"
  	"io"
  	"unsafe"
  
  	"github.com/sero-cash/go-sero/common"
  	"github.com/sero-cash/go-sero/common/hexutil"
  	"github.com/sero-cash/go-sero/rlp"
  )
  
  //go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go
  
  var (
  	receiptStatusFailedRLP     = []byte{}
  	receiptStatusSuccessfulRLP = []byte{0x01}
  )
  
  const (
  	// ReceiptStatusFailed is the status code of a transaction if execution failed.
  	ReceiptStatusFailed = uint64(0)
  
  	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
  	ReceiptStatusSuccessful = uint64(1)
  )
  
  // Receipt represents the results of a transaction.
  type Receipt struct {
  	// Consensus fields
  	PostState         []byte `json:"root"`
  	Status            uint64 `json:"status"`
  	CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
  	Bloom             Bloom  `json:"logsBloom"         gencodec:"required"`
  	Logs              []*Log `json:"logs"              gencodec:"required"`
  
  	// Implementation fields (don't reorder!)
  	TxHash          common.Hash    `json:"transactionHash" gencodec:"required"`
  	ContractAddress common.Address `json:"contractAddress"`
  	GasUsed         uint64         `json:"gasUsed" gencodec:"required"`
  
  	//Staking
  	PoolId  *common.Hash `rlp:"nil"`
  	ShareId *common.Hash `rlp:"nil"`
  }
  
  type receiptMarshaling struct {
  	PostState         hexutil.Bytes
  	Status            hexutil.Uint64
  	CumulativeGasUsed hexutil.Uint64
  	GasUsed           hexutil.Uint64
  }
  
  // receiptRLP is the consensus encoding of a receipt.
  type receiptRLP struct {
  	PostStateOrStatus []byte
  	CumulativeGasUsed uint64
  	Bloom             Bloom
  	Logs              []*Log
  }
  
  // NewReceipt creates a barebone transaction receipt, copying the init fields.
  func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
  	r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: cumulativeGasUsed}
  	if failed {
  		r.Status = ReceiptStatusFailed
  	} else {
  		r.Status = ReceiptStatusSuccessful
  	}
  	return r
  }
  
  // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt
  // into an RLP stream. If no post state is present, byzantium fork is assumed.
  func (r *Receipt) EncodeRLP(w io.Writer) error {
  	return rlp.Encode(w, &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs})
  }
  
  // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
  // from an RLP stream.
  func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
  	var dec receiptRLP
  	if err := s.Decode(&dec); err != nil {
  		return err
  	}
  	if err := r.setStatus(dec.PostStateOrStatus); err != nil {
  		return err
  	}
  	r.CumulativeGasUsed, r.Bloom, r.Logs = dec.CumulativeGasUsed, dec.Bloom, dec.Logs
  	return nil
  }
  
  func (r *Receipt) setStatus(postStateOrStatus []byte) error {
  	switch {
  	case bytes.Equal(postStateOrStatus, receiptStatusSuccessfulRLP):
  		r.Status = ReceiptStatusSuccessful
  	case bytes.Equal(postStateOrStatus, receiptStatusFailedRLP):
  		r.Status = ReceiptStatusFailed
  	case len(postStateOrStatus) == len(common.Hash{}):
  		r.PostState = postStateOrStatus
  	default:
  		return fmt.Errorf("invalid receipt status %x", postStateOrStatus)
  	}
  	return nil
  }
  
  func (r *Receipt) statusEncoding() []byte {
  	if len(r.PostState) == 0 {
  		if r.Status == ReceiptStatusFailed {
  			return receiptStatusFailedRLP
  		}
  		return receiptStatusSuccessfulRLP
  	}
  	return r.PostState
  }
  
  // Size returns the approximate memory used by all internal contents. It is used
  // to approximate and limit the memory consumption of various caches.
  func (r *Receipt) Size() common.StorageSize {
  	size := common.StorageSize(unsafe.Sizeof(*r)) + common.StorageSize(len(r.PostState))
  
  	size += common.StorageSize(len(r.Logs)) * common.StorageSize(unsafe.Sizeof(Log{}))
  	for _, log := range r.Logs {
  		size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data))
  	}
  	return size
  }
  
  // Receipts is a wrapper around a Receipt array to implement DerivableList.
  type Receipts []*Receipt
  
  // Len returns the number of receipts in this list.
  func (r Receipts) Len() int { return len(r) }
  
  // GetRlp returns the RLP encoding of one receipt from the list.
  func (r Receipts) GetRlp(i int) []byte {
  	bytes, err := rlp.EncodeToBytes(r[i])
  	if err != nil {
  		panic(err)
  	}
  	return bytes
  }
  