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  }