github.com/Ethersocial/go-esn@v0.3.7/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 "fmt" 22 "io" 23 "unsafe" 24 25 "github.com/ethersocial/go-esn/common" 26 "github.com/ethersocial/go-esn/common/hexutil" 27 "github.com/ethersocial/go-esn/rlp" 28 ) 29 30 //go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go 31 32 var ( 33 receiptStatusFailedRLP = []byte{} 34 receiptStatusSuccessfulRLP = []byte{0x01} 35 ) 36 37 const ( 38 // ReceiptStatusFailed is the status code of a transaction if execution failed. 39 ReceiptStatusFailed = uint64(0) 40 41 // ReceiptStatusSuccessful is the status code of a transaction if execution succeeded. 42 ReceiptStatusSuccessful = uint64(1) 43 ) 44 45 // Receipt represents the results of a transaction. 46 type Receipt struct { 47 // Consensus fields 48 PostState []byte `json:"root"` 49 Status uint64 `json:"status"` 50 CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"` 51 Bloom Bloom `json:"logsBloom" gencodec:"required"` 52 Logs []*Log `json:"logs" gencodec:"required"` 53 54 // Implementation fields (don't reorder!) 55 TxHash common.Hash `json:"transactionHash" gencodec:"required"` 56 ContractAddress common.Address `json:"contractAddress"` 57 GasUsed uint64 `json:"gasUsed" gencodec:"required"` 58 } 59 60 type receiptMarshaling struct { 61 PostState hexutil.Bytes 62 Status hexutil.Uint64 63 CumulativeGasUsed hexutil.Uint64 64 GasUsed hexutil.Uint64 65 } 66 67 // receiptRLP is the consensus encoding of a receipt. 68 type receiptRLP struct { 69 PostStateOrStatus []byte 70 CumulativeGasUsed uint64 71 Bloom Bloom 72 Logs []*Log 73 } 74 75 type receiptStorageRLP struct { 76 PostStateOrStatus []byte 77 CumulativeGasUsed uint64 78 Bloom Bloom 79 TxHash common.Hash 80 ContractAddress common.Address 81 Logs []*LogForStorage 82 GasUsed uint64 83 } 84 85 // NewReceipt creates a barebone transaction receipt, copying the init fields. 86 func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt { 87 r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: cumulativeGasUsed} 88 if failed { 89 r.Status = ReceiptStatusFailed 90 } else { 91 r.Status = ReceiptStatusSuccessful 92 } 93 return r 94 } 95 96 // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt 97 // into an RLP stream. If no post state is present, byzantium fork is assumed. 98 func (r *Receipt) EncodeRLP(w io.Writer) error { 99 return rlp.Encode(w, &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs}) 100 } 101 102 // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt 103 // from an RLP stream. 104 func (r *Receipt) DecodeRLP(s *rlp.Stream) error { 105 var dec receiptRLP 106 if err := s.Decode(&dec); err != nil { 107 return err 108 } 109 if err := r.setStatus(dec.PostStateOrStatus); err != nil { 110 return err 111 } 112 r.CumulativeGasUsed, r.Bloom, r.Logs = dec.CumulativeGasUsed, dec.Bloom, dec.Logs 113 return nil 114 } 115 116 func (r *Receipt) setStatus(postStateOrStatus []byte) error { 117 switch { 118 case bytes.Equal(postStateOrStatus, receiptStatusSuccessfulRLP): 119 r.Status = ReceiptStatusSuccessful 120 case bytes.Equal(postStateOrStatus, receiptStatusFailedRLP): 121 r.Status = ReceiptStatusFailed 122 case len(postStateOrStatus) == len(common.Hash{}): 123 r.PostState = postStateOrStatus 124 default: 125 return fmt.Errorf("invalid receipt status %x", postStateOrStatus) 126 } 127 return nil 128 } 129 130 func (r *Receipt) statusEncoding() []byte { 131 if len(r.PostState) == 0 { 132 if r.Status == ReceiptStatusFailed { 133 return receiptStatusFailedRLP 134 } 135 return receiptStatusSuccessfulRLP 136 } 137 return r.PostState 138 } 139 140 // Size returns the approximate memory used by all internal contents. It is used 141 // to approximate and limit the memory consumption of various caches. 142 func (r *Receipt) Size() common.StorageSize { 143 size := common.StorageSize(unsafe.Sizeof(*r)) + common.StorageSize(len(r.PostState)) 144 145 size += common.StorageSize(len(r.Logs)) * common.StorageSize(unsafe.Sizeof(Log{})) 146 for _, log := range r.Logs { 147 size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data)) 148 } 149 return size 150 } 151 152 // ReceiptForStorage is a wrapper around a Receipt that flattens and parses the 153 // entire content of a receipt, as opposed to only the consensus fields originally. 154 type ReceiptForStorage Receipt 155 156 // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt 157 // into an RLP stream. 158 func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { 159 enc := &receiptStorageRLP{ 160 PostStateOrStatus: (*Receipt)(r).statusEncoding(), 161 CumulativeGasUsed: r.CumulativeGasUsed, 162 Bloom: r.Bloom, 163 TxHash: r.TxHash, 164 ContractAddress: r.ContractAddress, 165 Logs: make([]*LogForStorage, len(r.Logs)), 166 GasUsed: r.GasUsed, 167 } 168 for i, log := range r.Logs { 169 enc.Logs[i] = (*LogForStorage)(log) 170 } 171 return rlp.Encode(w, enc) 172 } 173 174 // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation 175 // fields of a receipt from an RLP stream. 176 func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { 177 var dec receiptStorageRLP 178 if err := s.Decode(&dec); err != nil { 179 return err 180 } 181 if err := (*Receipt)(r).setStatus(dec.PostStateOrStatus); err != nil { 182 return err 183 } 184 // Assign the consensus fields 185 r.CumulativeGasUsed, r.Bloom = dec.CumulativeGasUsed, dec.Bloom 186 r.Logs = make([]*Log, len(dec.Logs)) 187 for i, log := range dec.Logs { 188 r.Logs[i] = (*Log)(log) 189 } 190 // Assign the implementation fields 191 r.TxHash, r.ContractAddress, r.GasUsed = dec.TxHash, dec.ContractAddress, dec.GasUsed 192 return nil 193 } 194 195 // Receipts is a wrapper around a Receipt array to implement DerivableList. 196 type Receipts []*Receipt 197 198 // Len returns the number of receipts in this list. 199 func (r Receipts) Len() int { return len(r) } 200 201 // GetRlp returns the RLP encoding of one receipt from the list. 202 func (r Receipts) GetRlp(i int) []byte { 203 bytes, err := rlp.EncodeToBytes(r[i]) 204 if err != nil { 205 panic(err) 206 } 207 return bytes 208 }