github.com/amazechain/amc@v0.1.3/common/block/receipt.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package block
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"github.com/amazechain/amc/api/protocol/types_pb"
    23  	"github.com/amazechain/amc/common/types"
    24  	"github.com/amazechain/amc/internal/avm/rlp"
    25  	"github.com/amazechain/amc/utils"
    26  	"github.com/holiman/uint256"
    27  	"google.golang.org/protobuf/proto"
    28  )
    29  
    30  const (
    31  	// ReceiptStatusFailed is the status code of a transaction if execution failed.
    32  	ReceiptStatusFailed = uint64(0)
    33  
    34  	// ReceiptStatusSuccessful is the status code of a transaction if execution succeeded.
    35  	ReceiptStatusSuccessful = uint64(1)
    36  )
    37  
    38  type Receipts []*Receipt
    39  
    40  func (rs *Receipts) Marshal() ([]byte, error) {
    41  	pb := rs.ToProtoMessage()
    42  	return proto.Marshal(pb)
    43  }
    44  
    45  func (rs *Receipts) Unmarshal(data []byte) error {
    46  	pb := new(types_pb.Receipts)
    47  	if err := proto.Unmarshal(data, pb); nil != err {
    48  		return err
    49  	}
    50  
    51  	return rs.FromProtoMessage(pb)
    52  }
    53  
    54  // Len returns the number of receipts in this list.
    55  func (rs Receipts) Len() int { return len(rs) }
    56  
    57  // EncodeIndex encodes the i'th receipt to w.
    58  func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
    59  	r := rs[i]
    60  
    61  	logs := make([]*storedLog, len(r.Logs))
    62  
    63  	for k, log := range r.Logs {
    64  		logs[k] = &storedLog{
    65  			Address: log.Address,
    66  			Topics:  log.Topics,
    67  			Data:    log.Data,
    68  		}
    69  	}
    70  	data := &storedReceipt{r.Status, r.CumulativeGasUsed, logs}
    71  
    72  	rlp.Encode(w, data)
    73  	//byte, _ := json.Marshal(data)
    74  	//w.Write(byte)
    75  }
    76  
    77  func (rs *Receipts) FromProtoMessage(receipts *types_pb.Receipts) error {
    78  	for _, receipt := range receipts.Receipts {
    79  		var rec Receipt
    80  		err := rec.fromProtoMessage(receipt)
    81  		if err == nil {
    82  			*rs = append(*rs, &rec)
    83  		}
    84  	}
    85  	return nil
    86  }
    87  
    88  func (rs *Receipts) ToProtoMessage() proto.Message {
    89  	var receipts []*types_pb.Receipt
    90  	for _, receipt := range *rs {
    91  		pReceipt := receipt.toProtoMessage()
    92  		receipts = append(receipts, pReceipt.(*types_pb.Receipt))
    93  	}
    94  	return &types_pb.Receipts{
    95  		Receipts: receipts,
    96  	}
    97  }
    98  
    99  type Receipt struct {
   100  	// Consensus fields: These fields are defined by the Yellow Paper
   101  	Type              uint8  `json:"type,omitempty"`
   102  	PostState         []byte `json:"root"`
   103  	Status            uint64 `json:"status"`
   104  	CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
   105  	Bloom             Bloom  `json:"logsBloom"         gencodec:"required"`
   106  	Logs              []*Log `json:"logs"              gencodec:"required"`
   107  
   108  	// Implementation fields: These fields are added by geth when processing a transaction.
   109  	// They are stored in the chain database.
   110  	TxHash          types.Hash    `json:"transactionHash" gencodec:"required"`
   111  	ContractAddress types.Address `json:"contractAddress"`
   112  	GasUsed         uint64        `json:"gasUsed" gencodec:"required"`
   113  
   114  	// Inclusion information: These fields provide information about the inclusion of the
   115  	// transaction corresponding to this receipt.
   116  	BlockHash        types.Hash   `json:"blockHash,omitempty"`
   117  	BlockNumber      *uint256.Int `json:"blockNumber,omitempty"`
   118  	TransactionIndex uint         `json:"transactionIndex"`
   119  }
   120  
   121  func (r *Receipt) Marshal() ([]byte, error) {
   122  	bpBlock := r.toProtoMessage()
   123  	return proto.Marshal(bpBlock)
   124  }
   125  
   126  func (r *Receipt) Unmarshal(data []byte) error {
   127  	var pReceipt types_pb.Receipt
   128  	if err := proto.Unmarshal(data, &pReceipt); err != nil {
   129  		return err
   130  	}
   131  	if err := r.fromProtoMessage(&pReceipt); err != nil {
   132  		return err
   133  	}
   134  	return nil
   135  }
   136  
   137  func (r *Receipt) toProtoMessage() proto.Message {
   138  	//bloom, _ := r.Bloom.Marshal()
   139  
   140  	var logs []*types_pb.Log
   141  	for _, log := range r.Logs {
   142  		logs = append(logs, log.ToProtoMessage().(*types_pb.Log))
   143  	}
   144  	pb := &types_pb.Receipt{
   145  		Type:              uint32(r.Type),
   146  		PostState:         r.PostState,
   147  		Status:            r.Status,
   148  		CumulativeGasUsed: r.CumulativeGasUsed,
   149  		Logs:              logs,
   150  		TxHash:            utils.ConvertHashToH256(r.TxHash),
   151  		ContractAddress:   utils.ConvertAddressToH160(r.ContractAddress),
   152  		GasUsed:           r.GasUsed,
   153  		BlockHash:         utils.ConvertHashToH256(r.BlockHash),
   154  		BlockNumber:       utils.ConvertUint256IntToH256(r.BlockNumber),
   155  		TransactionIndex:  uint64(r.TransactionIndex),
   156  		Bloom:             utils.ConvertBytesToH2048(r.Bloom[:]),
   157  	}
   158  	return pb
   159  }
   160  
   161  func (r *Receipt) fromProtoMessage(message proto.Message) error {
   162  	var (
   163  		pReceipt *types_pb.Receipt
   164  		ok       bool
   165  	)
   166  
   167  	if pReceipt, ok = message.(*types_pb.Receipt); !ok {
   168  		return fmt.Errorf("type conversion failure")
   169  	}
   170  
   171  	//bloom := new(types.Bloom)
   172  	//err := bloom.UnMarshalBloom(pReceipt.Bloom)
   173  	//if err != nil {
   174  	//	return fmt.Errorf("type conversion failure bloom")
   175  	//}
   176  
   177  	var logs []*Log
   178  	for _, logMessage := range pReceipt.Logs {
   179  		log := new(Log)
   180  
   181  		if err := log.FromProtoMessage(logMessage); err != nil {
   182  			return fmt.Errorf("type conversion failure log %s", err)
   183  		}
   184  		logs = append(logs, log)
   185  	}
   186  
   187  	r.Type = uint8(pReceipt.Type)
   188  	r.PostState = pReceipt.PostState
   189  	r.Status = pReceipt.Status
   190  	r.CumulativeGasUsed = pReceipt.CumulativeGasUsed
   191  	r.Bloom = utils.ConvertH2048ToBloom(pReceipt.Bloom)
   192  	r.Logs = logs
   193  	r.TxHash = utils.ConvertH256ToHash(pReceipt.TxHash)
   194  	r.ContractAddress = utils.ConvertH160toAddress(pReceipt.ContractAddress)
   195  	r.GasUsed = pReceipt.GasUsed
   196  	r.BlockHash = utils.ConvertH256ToHash(pReceipt.BlockHash)
   197  	r.BlockNumber = utils.ConvertH256ToUint256Int(pReceipt.BlockNumber)
   198  	r.TransactionIndex = uint(pReceipt.TransactionIndex)
   199  
   200  	return nil
   201  }
   202  
   203  // storedReceipt is the consensus encoding of a receipt.
   204  type storedReceipt struct {
   205  	PostStateOrStatus uint64
   206  	CumulativeGasUsed uint64
   207  	Logs              []*storedLog
   208  }
   209  
   210  type storedLog struct {
   211  	Address types.Address
   212  	Topics  []types.Hash
   213  	Data    []byte
   214  }