github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/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-wtc 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-wtc 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 "math/big" 24 25 "github.com/wtc/go-wtc/common" 26 "github.com/wtc/go-wtc/common/hexutil" 27 "github.com/wtc/go-wtc/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 = uint(0) 40 41 // ReceiptStatusSuccessful is the status code of a transaction if execution succeeded. 42 ReceiptStatusSuccessful = uint(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 uint `json:"status"` 50 CumulativeGasUsed *big.Int `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 *big.Int `json:"gasUsed" gencodec:"required"` 58 } 59 60 type receiptMarshaling struct { 61 PostState hexutil.Bytes 62 Status hexutil.Uint 63 CumulativeGasUsed *hexutil.Big 64 GasUsed *hexutil.Big 65 } 66 67 // receiptRLP is the consensus encoding of a receipt. 68 type receiptRLP struct { 69 PostStateOrStatus []byte 70 CumulativeGasUsed *big.Int 71 Bloom Bloom 72 Logs []*Log 73 } 74 75 type receiptStorageRLP struct { 76 PostStateOrStatus []byte 77 CumulativeGasUsed *big.Int 78 Bloom Bloom 79 TxHash common.Hash 80 ContractAddress common.Address 81 Logs []*LogForStorage 82 GasUsed *big.Int 83 } 84 85 // NewReceipt creates a barebone transaction receipt, copying the init fields. 86 func NewReceipt(root []byte, failed bool, cumulativeGasUsed *big.Int) *Receipt { 87 r := &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(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 // String implements the Stringer interface. 141 func (r *Receipt) String() string { 142 if len(r.PostState) == 0 { 143 return fmt.Sprintf("receipt{status=%d cgas=%v bloom=%x logs=%v}", r.Status, r.CumulativeGasUsed, r.Bloom, r.Logs) 144 } 145 return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs) 146 } 147 148 // ReceiptForStorage is a wrapper around a Receipt that flattens and parses the 149 // entire content of a receipt, as opposed to only the consensus fields originally. 150 type ReceiptForStorage Receipt 151 152 // EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt 153 // into an RLP stream. 154 func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { 155 enc := &receiptStorageRLP{ 156 PostStateOrStatus: (*Receipt)(r).statusEncoding(), 157 CumulativeGasUsed: r.CumulativeGasUsed, 158 Bloom: r.Bloom, 159 TxHash: r.TxHash, 160 ContractAddress: r.ContractAddress, 161 Logs: make([]*LogForStorage, len(r.Logs)), 162 GasUsed: r.GasUsed, 163 } 164 for i, log := range r.Logs { 165 enc.Logs[i] = (*LogForStorage)(log) 166 } 167 return rlp.Encode(w, enc) 168 } 169 170 // DecodeRLP implements rlp.Decoder, and loads both consensus and implementation 171 // fields of a receipt from an RLP stream. 172 func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { 173 var dec receiptStorageRLP 174 if err := s.Decode(&dec); err != nil { 175 return err 176 } 177 if err := (*Receipt)(r).setStatus(dec.PostStateOrStatus); err != nil { 178 return err 179 } 180 // Assign the consensus fields 181 r.CumulativeGasUsed, r.Bloom = dec.CumulativeGasUsed, dec.Bloom 182 r.Logs = make([]*Log, len(dec.Logs)) 183 for i, log := range dec.Logs { 184 r.Logs[i] = (*Log)(log) 185 } 186 // Assign the implementation fields 187 r.TxHash, r.ContractAddress, r.GasUsed = dec.TxHash, dec.ContractAddress, dec.GasUsed 188 return nil 189 } 190 191 // Receipts is a wrapper around a Receipt array to implement DerivableList. 192 type Receipts []*Receipt 193 194 // Len returns the number of receipts in this list. 195 func (r Receipts) Len() int { return len(r) } 196 197 // GetRlp returns the RLP encoding of one receipt from the list. 198 func (r Receipts) GetRlp(i int) []byte { 199 bytes, err := rlp.EncodeToBytes(r[i]) 200 if err != nil { 201 panic(err) 202 } 203 return bytes 204 }