github.com/haliliceylan/bsc@v1.1.10-0.20220501224556-eb78d644ebcb/core/types/receipt_test.go (about) 1 // Copyright 2019 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 "math" 22 "math/big" 23 "reflect" 24 "testing" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/crypto" 28 "github.com/ethereum/go-ethereum/params" 29 "github.com/ethereum/go-ethereum/rlp" 30 ) 31 32 func TestDecodeEmptyTypedReceipt(t *testing.T) { 33 input := []byte{0x80} 34 var r Receipt 35 err := rlp.DecodeBytes(input, &r) 36 if err != errEmptyTypedReceipt { 37 t.Fatal("wrong error:", err) 38 } 39 } 40 41 func TestLegacyReceiptDecoding(t *testing.T) { 42 tests := []struct { 43 name string 44 encode func(*Receipt) ([]byte, error) 45 }{ 46 { 47 "StoredReceiptRLP", 48 encodeAsStoredReceiptRLP, 49 }, 50 { 51 "V4StoredReceiptRLP", 52 encodeAsV4StoredReceiptRLP, 53 }, 54 { 55 "V3StoredReceiptRLP", 56 encodeAsV3StoredReceiptRLP, 57 }, 58 } 59 60 tx := NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil) 61 receipt := &Receipt{ 62 Status: ReceiptStatusFailed, 63 CumulativeGasUsed: 1, 64 Logs: []*Log{ 65 { 66 Address: common.BytesToAddress([]byte{0x11}), 67 Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, 68 Data: []byte{0x01, 0x00, 0xff}, 69 }, 70 { 71 Address: common.BytesToAddress([]byte{0x01, 0x11}), 72 Topics: []common.Hash{common.HexToHash("dead"), common.HexToHash("beef")}, 73 Data: []byte{0x01, 0x00, 0xff}, 74 }, 75 }, 76 TxHash: tx.Hash(), 77 ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), 78 GasUsed: 111111, 79 } 80 receipt.Bloom = CreateBloom(Receipts{receipt}) 81 82 for _, tc := range tests { 83 t.Run(tc.name, func(t *testing.T) { 84 enc, err := tc.encode(receipt) 85 if err != nil { 86 t.Fatalf("Error encoding receipt: %v", err) 87 } 88 var dec ReceiptForStorage 89 if err := rlp.DecodeBytes(enc, &dec); err != nil { 90 t.Fatalf("Error decoding RLP receipt: %v", err) 91 } 92 // Check whether all consensus fields are correct. 93 if dec.Status != receipt.Status { 94 t.Fatalf("Receipt status mismatch, want %v, have %v", receipt.Status, dec.Status) 95 } 96 if dec.CumulativeGasUsed != receipt.CumulativeGasUsed { 97 t.Fatalf("Receipt CumulativeGasUsed mismatch, want %v, have %v", receipt.CumulativeGasUsed, dec.CumulativeGasUsed) 98 } 99 if dec.Bloom != receipt.Bloom { 100 t.Fatalf("Bloom data mismatch, want %v, have %v", receipt.Bloom, dec.Bloom) 101 } 102 if len(dec.Logs) != len(receipt.Logs) { 103 t.Fatalf("Receipt log number mismatch, want %v, have %v", len(receipt.Logs), len(dec.Logs)) 104 } 105 for i := 0; i < len(dec.Logs); i++ { 106 if dec.Logs[i].Address != receipt.Logs[i].Address { 107 t.Fatalf("Receipt log %d address mismatch, want %v, have %v", i, receipt.Logs[i].Address, dec.Logs[i].Address) 108 } 109 if !reflect.DeepEqual(dec.Logs[i].Topics, receipt.Logs[i].Topics) { 110 t.Fatalf("Receipt log %d topics mismatch, want %v, have %v", i, receipt.Logs[i].Topics, dec.Logs[i].Topics) 111 } 112 if !bytes.Equal(dec.Logs[i].Data, receipt.Logs[i].Data) { 113 t.Fatalf("Receipt log %d data mismatch, want %v, have %v", i, receipt.Logs[i].Data, dec.Logs[i].Data) 114 } 115 } 116 }) 117 } 118 } 119 120 func encodeAsStoredReceiptRLP(want *Receipt) ([]byte, error) { 121 stored := &storedReceiptRLP{ 122 PostStateOrStatus: want.statusEncoding(), 123 CumulativeGasUsed: want.CumulativeGasUsed, 124 Logs: make([]*LogForStorage, len(want.Logs)), 125 } 126 for i, log := range want.Logs { 127 stored.Logs[i] = (*LogForStorage)(log) 128 } 129 return rlp.EncodeToBytes(stored) 130 } 131 132 func encodeAsV4StoredReceiptRLP(want *Receipt) ([]byte, error) { 133 stored := &v4StoredReceiptRLP{ 134 PostStateOrStatus: want.statusEncoding(), 135 CumulativeGasUsed: want.CumulativeGasUsed, 136 TxHash: want.TxHash, 137 ContractAddress: want.ContractAddress, 138 Logs: make([]*LogForStorage, len(want.Logs)), 139 GasUsed: want.GasUsed, 140 } 141 for i, log := range want.Logs { 142 stored.Logs[i] = (*LogForStorage)(log) 143 } 144 return rlp.EncodeToBytes(stored) 145 } 146 147 func encodeAsV3StoredReceiptRLP(want *Receipt) ([]byte, error) { 148 stored := &v3StoredReceiptRLP{ 149 PostStateOrStatus: want.statusEncoding(), 150 CumulativeGasUsed: want.CumulativeGasUsed, 151 Bloom: want.Bloom, 152 TxHash: want.TxHash, 153 ContractAddress: want.ContractAddress, 154 Logs: make([]*LogForStorage, len(want.Logs)), 155 GasUsed: want.GasUsed, 156 } 157 for i, log := range want.Logs { 158 stored.Logs[i] = (*LogForStorage)(log) 159 } 160 return rlp.EncodeToBytes(stored) 161 } 162 163 // Tests that receipt data can be correctly derived from the contextual infos 164 func TestDeriveFields(t *testing.T) { 165 // Create a few transactions to have receipts for 166 to2 := common.HexToAddress("0x2") 167 to3 := common.HexToAddress("0x3") 168 txs := Transactions{ 169 NewTx(&LegacyTx{ 170 Nonce: 1, 171 Value: big.NewInt(1), 172 Gas: 1, 173 GasPrice: big.NewInt(1), 174 }), 175 NewTx(&LegacyTx{ 176 To: &to2, 177 Nonce: 2, 178 Value: big.NewInt(2), 179 Gas: 2, 180 GasPrice: big.NewInt(2), 181 }), 182 NewTx(&AccessListTx{ 183 To: &to3, 184 Nonce: 3, 185 Value: big.NewInt(3), 186 Gas: 3, 187 GasPrice: big.NewInt(3), 188 }), 189 } 190 // Create the corresponding receipts 191 receipts := Receipts{ 192 &Receipt{ 193 Status: ReceiptStatusFailed, 194 CumulativeGasUsed: 1, 195 Logs: []*Log{ 196 {Address: common.BytesToAddress([]byte{0x11})}, 197 {Address: common.BytesToAddress([]byte{0x01, 0x11})}, 198 }, 199 TxHash: txs[0].Hash(), 200 ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}), 201 GasUsed: 1, 202 }, 203 &Receipt{ 204 PostState: common.Hash{2}.Bytes(), 205 CumulativeGasUsed: 3, 206 Logs: []*Log{ 207 {Address: common.BytesToAddress([]byte{0x22})}, 208 {Address: common.BytesToAddress([]byte{0x02, 0x22})}, 209 }, 210 TxHash: txs[1].Hash(), 211 ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}), 212 GasUsed: 2, 213 }, 214 &Receipt{ 215 Type: AccessListTxType, 216 PostState: common.Hash{3}.Bytes(), 217 CumulativeGasUsed: 6, 218 Logs: []*Log{ 219 {Address: common.BytesToAddress([]byte{0x33})}, 220 {Address: common.BytesToAddress([]byte{0x03, 0x33})}, 221 }, 222 TxHash: txs[2].Hash(), 223 ContractAddress: common.BytesToAddress([]byte{0x03, 0x33, 0x33}), 224 GasUsed: 3, 225 }, 226 } 227 // Clear all the computed fields and re-derive them 228 number := big.NewInt(1) 229 hash := common.BytesToHash([]byte{0x03, 0x14}) 230 231 clearComputedFieldsOnReceipts(t, receipts) 232 if err := receipts.DeriveFields(params.TestChainConfig, hash, number.Uint64(), txs); err != nil { 233 t.Fatalf("DeriveFields(...) = %v, want <nil>", err) 234 } 235 // Iterate over all the computed fields and check that they're correct 236 signer := MakeSigner(params.TestChainConfig, number) 237 238 logIndex := uint(0) 239 for i := range receipts { 240 if receipts[i].Type != txs[i].Type() { 241 t.Errorf("receipts[%d].Type = %d, want %d", i, receipts[i].Type, txs[i].Type()) 242 } 243 if receipts[i].TxHash != txs[i].Hash() { 244 t.Errorf("receipts[%d].TxHash = %s, want %s", i, receipts[i].TxHash.String(), txs[i].Hash().String()) 245 } 246 if receipts[i].BlockHash != hash { 247 t.Errorf("receipts[%d].BlockHash = %s, want %s", i, receipts[i].BlockHash.String(), hash.String()) 248 } 249 if receipts[i].BlockNumber.Cmp(number) != 0 { 250 t.Errorf("receipts[%c].BlockNumber = %s, want %s", i, receipts[i].BlockNumber.String(), number.String()) 251 } 252 if receipts[i].TransactionIndex != uint(i) { 253 t.Errorf("receipts[%d].TransactionIndex = %d, want %d", i, receipts[i].TransactionIndex, i) 254 } 255 if receipts[i].GasUsed != txs[i].Gas() { 256 t.Errorf("receipts[%d].GasUsed = %d, want %d", i, receipts[i].GasUsed, txs[i].Gas()) 257 } 258 if txs[i].To() != nil && receipts[i].ContractAddress != (common.Address{}) { 259 t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), (common.Address{}).String()) 260 } 261 from, _ := Sender(signer, txs[i]) 262 contractAddress := crypto.CreateAddress(from, txs[i].Nonce()) 263 if txs[i].To() == nil && receipts[i].ContractAddress != contractAddress { 264 t.Errorf("receipts[%d].ContractAddress = %s, want %s", i, receipts[i].ContractAddress.String(), contractAddress.String()) 265 } 266 for j := range receipts[i].Logs { 267 if receipts[i].Logs[j].BlockNumber != number.Uint64() { 268 t.Errorf("receipts[%d].Logs[%d].BlockNumber = %d, want %d", i, j, receipts[i].Logs[j].BlockNumber, number.Uint64()) 269 } 270 if receipts[i].Logs[j].BlockHash != hash { 271 t.Errorf("receipts[%d].Logs[%d].BlockHash = %s, want %s", i, j, receipts[i].Logs[j].BlockHash.String(), hash.String()) 272 } 273 if receipts[i].Logs[j].TxHash != txs[i].Hash() { 274 t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String()) 275 } 276 if receipts[i].Logs[j].TxHash != txs[i].Hash() { 277 t.Errorf("receipts[%d].Logs[%d].TxHash = %s, want %s", i, j, receipts[i].Logs[j].TxHash.String(), txs[i].Hash().String()) 278 } 279 if receipts[i].Logs[j].TxIndex != uint(i) { 280 t.Errorf("receipts[%d].Logs[%d].TransactionIndex = %d, want %d", i, j, receipts[i].Logs[j].TxIndex, i) 281 } 282 if receipts[i].Logs[j].Index != logIndex { 283 t.Errorf("receipts[%d].Logs[%d].Index = %d, want %d", i, j, receipts[i].Logs[j].Index, logIndex) 284 } 285 logIndex++ 286 } 287 } 288 } 289 290 // TestTypedReceiptEncodingDecoding reproduces a flaw that existed in the receipt 291 // rlp decoder, which failed due to a shadowing error. 292 func TestTypedReceiptEncodingDecoding(t *testing.T) { 293 var payload = common.FromHex("f9043eb9010c01f90108018262d4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010c01f901080182cd14b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010d01f901090183013754b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0b9010d01f90109018301a194b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0") 294 check := func(bundle []*Receipt) { 295 t.Helper() 296 for i, receipt := range bundle { 297 if got, want := receipt.Type, uint8(1); got != want { 298 t.Fatalf("bundle %d: got %x, want %x", i, got, want) 299 } 300 } 301 } 302 { 303 var bundle []*Receipt 304 rlp.DecodeBytes(payload, &bundle) 305 check(bundle) 306 } 307 { 308 var bundle []*Receipt 309 r := bytes.NewReader(payload) 310 s := rlp.NewStream(r, uint64(len(payload))) 311 if err := s.Decode(&bundle); err != nil { 312 t.Fatal(err) 313 } 314 check(bundle) 315 } 316 } 317 318 func clearComputedFieldsOnReceipts(t *testing.T, receipts Receipts) { 319 t.Helper() 320 321 for _, receipt := range receipts { 322 clearComputedFieldsOnReceipt(t, receipt) 323 } 324 } 325 326 func clearComputedFieldsOnReceipt(t *testing.T, receipt *Receipt) { 327 t.Helper() 328 329 receipt.TxHash = common.Hash{} 330 receipt.BlockHash = common.Hash{} 331 receipt.BlockNumber = big.NewInt(math.MaxUint32) 332 receipt.TransactionIndex = math.MaxUint32 333 receipt.ContractAddress = common.Address{} 334 receipt.GasUsed = 0 335 336 clearComputedFieldsOnLogs(t, receipt.Logs) 337 } 338 339 func clearComputedFieldsOnLogs(t *testing.T, logs []*Log) { 340 t.Helper() 341 342 for _, log := range logs { 343 clearComputedFieldsOnLog(t, log) 344 } 345 } 346 347 func clearComputedFieldsOnLog(t *testing.T, log *Log) { 348 t.Helper() 349 350 log.BlockNumber = math.MaxUint32 351 log.BlockHash = common.Hash{} 352 log.TxHash = common.Hash{} 353 log.TxIndex = math.MaxUint32 354 log.Index = math.MaxUint32 355 }