github.com/baptiste-b-pegasys/quorum/v22@v22.4.2/core/rawdb/accessors_chain_test.go (about)

     1  // Copyright 2018 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 rawdb
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"math/rand"
    26  	"os"
    27  	"reflect"
    28  	"testing"
    29  
    30  	"github.com/ethereum/go-ethereum/common"
    31  	"github.com/ethereum/go-ethereum/core/types"
    32  	"github.com/ethereum/go-ethereum/ethdb"
    33  	"github.com/ethereum/go-ethereum/log"
    34  	"github.com/ethereum/go-ethereum/params"
    35  	"github.com/ethereum/go-ethereum/rlp"
    36  	"github.com/stretchr/testify/assert"
    37  	"golang.org/x/crypto/sha3"
    38  )
    39  
    40  // Tests block header storage and retrieval operations.
    41  func TestHeaderStorage(t *testing.T) {
    42  	db := NewMemoryDatabase()
    43  
    44  	// Create a test header to move around the database and make sure it's really new
    45  	header := &types.Header{Number: big.NewInt(42), Extra: []byte("test header")}
    46  	if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil {
    47  		t.Fatalf("Non existent header returned: %v", entry)
    48  	}
    49  	// Write and verify the header in the database
    50  	WriteHeader(db, header)
    51  	if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry == nil {
    52  		t.Fatalf("Stored header not found")
    53  	} else if entry.Hash() != header.Hash() {
    54  		t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, header)
    55  	}
    56  	if entry := ReadHeaderRLP(db, header.Hash(), header.Number.Uint64()); entry == nil {
    57  		t.Fatalf("Stored header RLP not found")
    58  	} else {
    59  		hasher := sha3.NewLegacyKeccak256()
    60  		hasher.Write(entry)
    61  
    62  		if hash := common.BytesToHash(hasher.Sum(nil)); hash != header.Hash() {
    63  			t.Fatalf("Retrieved RLP header mismatch: have %v, want %v", entry, header)
    64  		}
    65  	}
    66  	// Delete the header and verify the execution
    67  	DeleteHeader(db, header.Hash(), header.Number.Uint64())
    68  	if entry := ReadHeader(db, header.Hash(), header.Number.Uint64()); entry != nil {
    69  		t.Fatalf("Deleted header returned: %v", entry)
    70  	}
    71  }
    72  
    73  // Tests block body storage and retrieval operations.
    74  func TestBodyStorage(t *testing.T) {
    75  	db := NewMemoryDatabase()
    76  
    77  	// Create a test body to move around the database and make sure it's really new
    78  	body := &types.Body{Uncles: []*types.Header{{Extra: []byte("test header")}}}
    79  
    80  	hasher := sha3.NewLegacyKeccak256()
    81  	rlp.Encode(hasher, body)
    82  	hash := common.BytesToHash(hasher.Sum(nil))
    83  
    84  	if entry := ReadBody(db, hash, 0); entry != nil {
    85  		t.Fatalf("Non existent body returned: %v", entry)
    86  	}
    87  	// Write and verify the body in the database
    88  	WriteBody(db, hash, 0, body)
    89  	if entry := ReadBody(db, hash, 0); entry == nil {
    90  		t.Fatalf("Stored body not found")
    91  	} else if types.DeriveSha(types.Transactions(entry.Transactions), newHasher()) != types.DeriveSha(types.Transactions(body.Transactions), newHasher()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) {
    92  		t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, body)
    93  	}
    94  	if entry := ReadBodyRLP(db, hash, 0); entry == nil {
    95  		t.Fatalf("Stored body RLP not found")
    96  	} else {
    97  		hasher := sha3.NewLegacyKeccak256()
    98  		hasher.Write(entry)
    99  
   100  		if calc := common.BytesToHash(hasher.Sum(nil)); calc != hash {
   101  			t.Fatalf("Retrieved RLP body mismatch: have %v, want %v", entry, body)
   102  		}
   103  	}
   104  	// Delete the body and verify the execution
   105  	DeleteBody(db, hash, 0)
   106  	if entry := ReadBody(db, hash, 0); entry != nil {
   107  		t.Fatalf("Deleted body returned: %v", entry)
   108  	}
   109  }
   110  
   111  // Tests block storage and retrieval operations.
   112  func TestBlockStorage(t *testing.T) {
   113  	db := NewMemoryDatabase()
   114  
   115  	// Create a test block to move around the database and make sure it's really new
   116  	block := types.NewBlockWithHeader(&types.Header{
   117  		Extra:       []byte("test block"),
   118  		UncleHash:   types.EmptyUncleHash,
   119  		TxHash:      types.EmptyRootHash,
   120  		ReceiptHash: types.EmptyRootHash,
   121  	})
   122  	if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
   123  		t.Fatalf("Non existent block returned: %v", entry)
   124  	}
   125  	if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil {
   126  		t.Fatalf("Non existent header returned: %v", entry)
   127  	}
   128  	if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil {
   129  		t.Fatalf("Non existent body returned: %v", entry)
   130  	}
   131  	// Write and verify the block in the database
   132  	WriteBlock(db, block)
   133  	if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil {
   134  		t.Fatalf("Stored block not found")
   135  	} else if entry.Hash() != block.Hash() {
   136  		t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
   137  	}
   138  	if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry == nil {
   139  		t.Fatalf("Stored header not found")
   140  	} else if entry.Hash() != block.Header().Hash() {
   141  		t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header())
   142  	}
   143  	if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry == nil {
   144  		t.Fatalf("Stored body not found")
   145  	} else if types.DeriveSha(types.Transactions(entry.Transactions), newHasher()) != types.DeriveSha(block.Transactions(), newHasher()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) {
   146  		t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body())
   147  	}
   148  	// Delete the block and verify the execution
   149  	DeleteBlock(db, block.Hash(), block.NumberU64())
   150  	if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
   151  		t.Fatalf("Deleted block returned: %v", entry)
   152  	}
   153  	if entry := ReadHeader(db, block.Hash(), block.NumberU64()); entry != nil {
   154  		t.Fatalf("Deleted header returned: %v", entry)
   155  	}
   156  	if entry := ReadBody(db, block.Hash(), block.NumberU64()); entry != nil {
   157  		t.Fatalf("Deleted body returned: %v", entry)
   158  	}
   159  }
   160  
   161  // Tests that partial block contents don't get reassembled into full blocks.
   162  func TestPartialBlockStorage(t *testing.T) {
   163  	db := NewMemoryDatabase()
   164  	block := types.NewBlockWithHeader(&types.Header{
   165  		Extra:       []byte("test block"),
   166  		UncleHash:   types.EmptyUncleHash,
   167  		TxHash:      types.EmptyRootHash,
   168  		ReceiptHash: types.EmptyRootHash,
   169  	})
   170  	// Store a header and check that it's not recognized as a block
   171  	WriteHeader(db, block.Header())
   172  	if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
   173  		t.Fatalf("Non existent block returned: %v", entry)
   174  	}
   175  	DeleteHeader(db, block.Hash(), block.NumberU64())
   176  
   177  	// Store a body and check that it's not recognized as a block
   178  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   179  	if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
   180  		t.Fatalf("Non existent block returned: %v", entry)
   181  	}
   182  	DeleteBody(db, block.Hash(), block.NumberU64())
   183  
   184  	// Store a header and a body separately and check reassembly
   185  	WriteHeader(db, block.Header())
   186  	WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
   187  
   188  	if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry == nil {
   189  		t.Fatalf("Stored block not found")
   190  	} else if entry.Hash() != block.Hash() {
   191  		t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
   192  	}
   193  }
   194  
   195  // Tests block storage and retrieval operations.
   196  func TestBadBlockStorage(t *testing.T) {
   197  	db := NewMemoryDatabase()
   198  
   199  	// Create a test block to move around the database and make sure it's really new
   200  	block := types.NewBlockWithHeader(&types.Header{
   201  		Number:      big.NewInt(1),
   202  		Extra:       []byte("bad block"),
   203  		UncleHash:   types.EmptyUncleHash,
   204  		TxHash:      types.EmptyRootHash,
   205  		ReceiptHash: types.EmptyRootHash,
   206  	})
   207  	if entry := ReadBadBlock(db, block.Hash()); entry != nil {
   208  		t.Fatalf("Non existent block returned: %v", entry)
   209  	}
   210  	// Write and verify the block in the database
   211  	WriteBadBlock(db, block)
   212  	if entry := ReadBadBlock(db, block.Hash()); entry == nil {
   213  		t.Fatalf("Stored block not found")
   214  	} else if entry.Hash() != block.Hash() {
   215  		t.Fatalf("Retrieved block mismatch: have %v, want %v", entry, block)
   216  	}
   217  	// Write one more bad block
   218  	blockTwo := types.NewBlockWithHeader(&types.Header{
   219  		Number:      big.NewInt(2),
   220  		Extra:       []byte("bad block two"),
   221  		UncleHash:   types.EmptyUncleHash,
   222  		TxHash:      types.EmptyRootHash,
   223  		ReceiptHash: types.EmptyRootHash,
   224  	})
   225  	WriteBadBlock(db, blockTwo)
   226  
   227  	// Write the block one again, should be filtered out.
   228  	WriteBadBlock(db, block)
   229  	badBlocks := ReadAllBadBlocks(db)
   230  	if len(badBlocks) != 2 {
   231  		t.Fatalf("Failed to load all bad blocks")
   232  	}
   233  
   234  	// Write a bunch of bad blocks, all the blocks are should sorted
   235  	// in reverse order. The extra blocks should be truncated.
   236  	for _, n := range rand.Perm(100) {
   237  		block := types.NewBlockWithHeader(&types.Header{
   238  			Number:      big.NewInt(int64(n)),
   239  			Extra:       []byte("bad block"),
   240  			UncleHash:   types.EmptyUncleHash,
   241  			TxHash:      types.EmptyRootHash,
   242  			ReceiptHash: types.EmptyRootHash,
   243  		})
   244  		WriteBadBlock(db, block)
   245  	}
   246  	badBlocks = ReadAllBadBlocks(db)
   247  	if len(badBlocks) != badBlockToKeep {
   248  		t.Fatalf("The number of persised bad blocks in incorrect %d", len(badBlocks))
   249  	}
   250  	for i := 0; i < len(badBlocks)-1; i++ {
   251  		if badBlocks[i].NumberU64() < badBlocks[i+1].NumberU64() {
   252  			t.Fatalf("The bad blocks are not sorted #[%d](%d) < #[%d](%d)", i, i+1, badBlocks[i].NumberU64(), badBlocks[i+1].NumberU64())
   253  		}
   254  	}
   255  
   256  	// Delete all bad blocks
   257  	DeleteBadBlocks(db)
   258  	badBlocks = ReadAllBadBlocks(db)
   259  	if len(badBlocks) != 0 {
   260  		t.Fatalf("Failed to delete bad blocks")
   261  	}
   262  }
   263  
   264  // Tests block total difficulty storage and retrieval operations.
   265  func TestTdStorage(t *testing.T) {
   266  	db := NewMemoryDatabase()
   267  
   268  	// Create a test TD to move around the database and make sure it's really new
   269  	hash, td := common.Hash{}, big.NewInt(314)
   270  	if entry := ReadTd(db, hash, 0); entry != nil {
   271  		t.Fatalf("Non existent TD returned: %v", entry)
   272  	}
   273  	// Write and verify the TD in the database
   274  	WriteTd(db, hash, 0, td)
   275  	if entry := ReadTd(db, hash, 0); entry == nil {
   276  		t.Fatalf("Stored TD not found")
   277  	} else if entry.Cmp(td) != 0 {
   278  		t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td)
   279  	}
   280  	// Delete the TD and verify the execution
   281  	DeleteTd(db, hash, 0)
   282  	if entry := ReadTd(db, hash, 0); entry != nil {
   283  		t.Fatalf("Deleted TD returned: %v", entry)
   284  	}
   285  }
   286  
   287  // Tests that canonical numbers can be mapped to hashes and retrieved.
   288  func TestCanonicalMappingStorage(t *testing.T) {
   289  	db := NewMemoryDatabase()
   290  
   291  	// Create a test canonical number and assinged hash to move around
   292  	hash, number := common.Hash{0: 0xff}, uint64(314)
   293  	if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
   294  		t.Fatalf("Non existent canonical mapping returned: %v", entry)
   295  	}
   296  	// Write and verify the TD in the database
   297  	WriteCanonicalHash(db, hash, number)
   298  	if entry := ReadCanonicalHash(db, number); entry == (common.Hash{}) {
   299  		t.Fatalf("Stored canonical mapping not found")
   300  	} else if entry != hash {
   301  		t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash)
   302  	}
   303  	// Delete the TD and verify the execution
   304  	DeleteCanonicalHash(db, number)
   305  	if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
   306  		t.Fatalf("Deleted canonical mapping returned: %v", entry)
   307  	}
   308  }
   309  
   310  // Tests that head headers and head blocks can be assigned, individually.
   311  func TestHeadStorage(t *testing.T) {
   312  	db := NewMemoryDatabase()
   313  
   314  	blockHead := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block header")})
   315  	blockFull := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block full")})
   316  	blockFast := types.NewBlockWithHeader(&types.Header{Extra: []byte("test block fast")})
   317  
   318  	// Check that no head entries are in a pristine database
   319  	if entry := ReadHeadHeaderHash(db); entry != (common.Hash{}) {
   320  		t.Fatalf("Non head header entry returned: %v", entry)
   321  	}
   322  	if entry := ReadHeadBlockHash(db); entry != (common.Hash{}) {
   323  		t.Fatalf("Non head block entry returned: %v", entry)
   324  	}
   325  	if entry := ReadHeadFastBlockHash(db); entry != (common.Hash{}) {
   326  		t.Fatalf("Non fast head block entry returned: %v", entry)
   327  	}
   328  	// Assign separate entries for the head header and block
   329  	WriteHeadHeaderHash(db, blockHead.Hash())
   330  	WriteHeadBlockHash(db, blockFull.Hash())
   331  	WriteHeadFastBlockHash(db, blockFast.Hash())
   332  
   333  	// Check that both heads are present, and different (i.e. two heads maintained)
   334  	if entry := ReadHeadHeaderHash(db); entry != blockHead.Hash() {
   335  		t.Fatalf("Head header hash mismatch: have %v, want %v", entry, blockHead.Hash())
   336  	}
   337  	if entry := ReadHeadBlockHash(db); entry != blockFull.Hash() {
   338  		t.Fatalf("Head block hash mismatch: have %v, want %v", entry, blockFull.Hash())
   339  	}
   340  	if entry := ReadHeadFastBlockHash(db); entry != blockFast.Hash() {
   341  		t.Fatalf("Fast head block hash mismatch: have %v, want %v", entry, blockFast.Hash())
   342  	}
   343  }
   344  
   345  // Tests that receipts associated with a single block can be stored and retrieved.
   346  func TestBlockReceiptStorage(t *testing.T) {
   347  	db := NewMemoryDatabase()
   348  
   349  	// Create a live block since we need metadata to reconstruct the receipt
   350  	tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
   351  	tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
   352  
   353  	body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
   354  
   355  	// Create the two receipts to manage afterwards
   356  	receipt1 := &types.Receipt{
   357  		Status:            types.ReceiptStatusFailed,
   358  		CumulativeGasUsed: 1,
   359  		Logs: []*types.Log{
   360  			{Address: common.BytesToAddress([]byte{0x11})},
   361  			{Address: common.BytesToAddress([]byte{0x01, 0x11})},
   362  		},
   363  		TxHash:          tx1.Hash(),
   364  		ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
   365  		GasUsed:         111111,
   366  	}
   367  	receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
   368  
   369  	receipt2 := &types.Receipt{
   370  		PostState:         common.Hash{2}.Bytes(),
   371  		CumulativeGasUsed: 2,
   372  		Logs: []*types.Log{
   373  			{Address: common.BytesToAddress([]byte{0x22})},
   374  			{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   375  		},
   376  		TxHash:          tx2.Hash(),
   377  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   378  		GasUsed:         222222,
   379  	}
   380  	receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
   381  	receipts := []*types.Receipt{receipt1, receipt2}
   382  
   383  	// Check that no receipt entries are in a pristine database
   384  	hash := common.BytesToHash([]byte{0x03, 0x14})
   385  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
   386  		t.Fatalf("non existent receipts returned: %v", rs)
   387  	}
   388  	// Insert the body that corresponds to the receipts
   389  	WriteBody(db, hash, 0, body)
   390  
   391  	// Insert the receipt slice into the database and check presence
   392  	WriteReceipts(db, hash, 0, receipts)
   393  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
   394  		t.Fatalf("no receipts returned")
   395  	} else {
   396  		if err := checkReceiptsRLP(rs, receipts); err != nil {
   397  			t.Fatalf(err.Error())
   398  		}
   399  		// check that the raw data does not contain the quorumExtraData array (since the prepared receipts do not have any quorumExtraData)
   400  		receiptData := ReadReceiptsRLP(db, hash, 0)
   401  		_, extraData, err := rlp.SplitList(receiptData)
   402  		assert.NoError(t, err)
   403  		assert.Empty(t, extraData)
   404  	}
   405  	// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
   406  	DeleteBody(db, hash, 0)
   407  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
   408  		t.Fatalf("receipts returned when body was deleted: %v", rs)
   409  	}
   410  	// Ensure that receipts without metadata can be returned without the block body too
   411  	if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
   412  		t.Fatalf(err.Error())
   413  	}
   414  	// Sanity check that body alone without the receipt is a full purge
   415  	WriteBody(db, hash, 0, body)
   416  
   417  	DeleteReceipts(db, hash, 0)
   418  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
   419  		t.Fatalf("deleted receipts returned: %v", rs)
   420  	}
   421  }
   422  
   423  func TestBlockReceiptStorageWithLegacyMPSV1EncodingWithMPSData(t *testing.T) {
   424  	db := NewMemoryDatabase()
   425  
   426  	// Create a live block since we need metadata to reconstruct the receipt
   427  	tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
   428  	tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
   429  	tx2.SetPrivate()
   430  
   431  	body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
   432  
   433  	// Create the two receipts to manage afterwards
   434  	receipt1 := &types.Receipt{
   435  		Status:            types.ReceiptStatusFailed,
   436  		CumulativeGasUsed: 1,
   437  		Logs: []*types.Log{
   438  			{Address: common.BytesToAddress([]byte{0x11})},
   439  			{Address: common.BytesToAddress([]byte{0x01, 0x11})},
   440  		},
   441  		TxHash:          tx1.Hash(),
   442  		ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
   443  		GasUsed:         111111,
   444  	}
   445  	receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
   446  
   447  	psiReceipt2 := &types.Receipt{
   448  		PostState:         common.Hash{2}.Bytes(),
   449  		CumulativeGasUsed: 2,
   450  		Logs: []*types.Log{
   451  			{Address: common.BytesToAddress([]byte{0x22})},
   452  			{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   453  		},
   454  		TxHash:          tx2.Hash(),
   455  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   456  		GasUsed:         222222,
   457  	}
   458  
   459  	receipt2 := &types.Receipt{
   460  		PostState:         common.Hash{2}.Bytes(),
   461  		CumulativeGasUsed: 2,
   462  		Logs: []*types.Log{
   463  			{Address: common.BytesToAddress([]byte{0x22})},
   464  			{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   465  		},
   466  		TxHash:          tx2.Hash(),
   467  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   468  		GasUsed:         222222,
   469  		QuorumReceiptExtraData: types.QuorumReceiptExtraData{
   470  			PSReceipts: map[types.PrivateStateIdentifier]*types.Receipt{types.PrivateStateIdentifier("psi1"): psiReceipt2},
   471  		},
   472  	}
   473  	receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
   474  	receipts := []*types.Receipt{receipt1, receipt2}
   475  
   476  	// Check that no receipt entries are in a pristine database
   477  	hash := common.BytesToHash([]byte{0x03, 0x14})
   478  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
   479  		t.Fatalf("non existent receipts returned: %v", rs)
   480  	}
   481  	// Insert the body that corresponds to the receipts
   482  	WriteBody(db, hash, 0, body)
   483  
   484  	// Insert the receipt slice into the database and check presence
   485  	WriteReceiptsMPSV1(db, hash, 0, receipts)
   486  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
   487  		t.Fatalf("no receipts returned")
   488  	} else {
   489  		if err := checkReceiptsRLP(rs, receipts); err != nil {
   490  			t.Fatalf(err.Error())
   491  		}
   492  		rec2 := rs[1]
   493  		assert.Len(t, rec2.PSReceipts, 1)
   494  		psRec2 := rec2.PSReceipts[types.PrivateStateIdentifier("psi1")]
   495  		assert.NotNil(t, psRec2)
   496  	}
   497  	// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
   498  	DeleteBody(db, hash, 0)
   499  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
   500  		t.Fatalf("receipts returned when body was deleted: %v", rs)
   501  	}
   502  	// Ensure that receipts without metadata can be returned without the block body too
   503  	if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
   504  		t.Fatalf(err.Error())
   505  	}
   506  }
   507  
   508  func TestBlockReceiptStorageWithLegacyMPSV1EncodingWithoutMPSData(t *testing.T) {
   509  	db := NewMemoryDatabase()
   510  
   511  	// Create a live block since we need metadata to reconstruct the receipt
   512  	tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
   513  	tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
   514  	tx2.SetPrivate()
   515  
   516  	body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
   517  
   518  	// Create the two receipts to manage afterwards
   519  	receipt1 := &types.Receipt{
   520  		Status:            types.ReceiptStatusFailed,
   521  		CumulativeGasUsed: 1,
   522  		Logs: []*types.Log{
   523  			{Address: common.BytesToAddress([]byte{0x11})},
   524  			{Address: common.BytesToAddress([]byte{0x01, 0x11})},
   525  		},
   526  		TxHash:          tx1.Hash(),
   527  		ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
   528  		GasUsed:         111111,
   529  	}
   530  	receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
   531  
   532  	receipt2 := &types.Receipt{
   533  		PostState:         common.Hash{2}.Bytes(),
   534  		CumulativeGasUsed: 2,
   535  		Logs: []*types.Log{
   536  			{Address: common.BytesToAddress([]byte{0x22})},
   537  			{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   538  		},
   539  		TxHash:          tx2.Hash(),
   540  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   541  		GasUsed:         222222,
   542  	}
   543  	receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
   544  	receipts := []*types.Receipt{receipt1, receipt2}
   545  
   546  	// Check that no receipt entries are in a pristine database
   547  	hash := common.BytesToHash([]byte{0x03, 0x14})
   548  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
   549  		t.Fatalf("non existent receipts returned: %v", rs)
   550  	}
   551  	// Insert the body that corresponds to the receipts
   552  	WriteBody(db, hash, 0, body)
   553  
   554  	// Insert the receipt slice into the database and check presence
   555  	WriteReceiptsMPSV1(db, hash, 0, receipts)
   556  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
   557  		t.Fatalf("no receipts returned")
   558  	} else {
   559  		if err := checkReceiptsRLP(rs, receipts); err != nil {
   560  			t.Fatalf(err.Error())
   561  		}
   562  		rec2 := rs[1]
   563  		assert.Len(t, rec2.PSReceipts, 0)
   564  	}
   565  	// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
   566  	DeleteBody(db, hash, 0)
   567  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
   568  		t.Fatalf("receipts returned when body was deleted: %v", rs)
   569  	}
   570  	// Ensure that receipts without metadata can be returned without the block body too
   571  	if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
   572  		t.Fatalf(err.Error())
   573  	}
   574  }
   575  
   576  // Tests that receipts associated with a single block can be stored and retrieved.
   577  func TestBlockReceiptStorageWithQuorumExtraData(t *testing.T) {
   578  	db := NewMemoryDatabase()
   579  
   580  	// Create a live block since we need metadata to reconstruct the receipt
   581  	tx1 := types.NewTransaction(1, common.HexToAddress("0x1"), big.NewInt(1), 1, big.NewInt(1), nil)
   582  	tx2 := types.NewTransaction(2, common.HexToAddress("0x2"), big.NewInt(2), 2, big.NewInt(2), nil)
   583  	tx2.SetPrivate()
   584  
   585  	body := &types.Body{Transactions: types.Transactions{tx1, tx2}}
   586  
   587  	// Create the two receipts to manage afterwards
   588  	receipt1 := &types.Receipt{
   589  		Status:            types.ReceiptStatusFailed,
   590  		CumulativeGasUsed: 1,
   591  		Logs: []*types.Log{
   592  			{Address: common.BytesToAddress([]byte{0x11})},
   593  			{Address: common.BytesToAddress([]byte{0x01, 0x11})},
   594  		},
   595  		TxHash:          tx1.Hash(),
   596  		ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
   597  		GasUsed:         111111,
   598  	}
   599  	receipt1.Bloom = types.CreateBloom(types.Receipts{receipt1})
   600  
   601  	psiReceipt2 := &types.Receipt{
   602  		PostState:         common.Hash{2}.Bytes(),
   603  		CumulativeGasUsed: 2,
   604  		Logs: []*types.Log{
   605  			{Address: common.BytesToAddress([]byte{0x22})},
   606  			{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   607  		},
   608  		TxHash:          tx2.Hash(),
   609  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   610  		GasUsed:         222222,
   611  		QuorumReceiptExtraData: types.QuorumReceiptExtraData{
   612  			RevertReason: []byte("arbitraryvalue"),
   613  		},
   614  	}
   615  
   616  	receipt2 := &types.Receipt{
   617  		PostState:         common.Hash{2}.Bytes(),
   618  		CumulativeGasUsed: 2,
   619  		Logs: []*types.Log{
   620  			{Address: common.BytesToAddress([]byte{0x22})},
   621  			{Address: common.BytesToAddress([]byte{0x02, 0x22})},
   622  		},
   623  		TxHash:          tx2.Hash(),
   624  		ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
   625  		GasUsed:         222222,
   626  		QuorumReceiptExtraData: types.QuorumReceiptExtraData{
   627  			RevertReason: []byte("arbitraryvalue"),
   628  			PSReceipts:   map[types.PrivateStateIdentifier]*types.Receipt{types.PrivateStateIdentifier("psi1"): psiReceipt2},
   629  		},
   630  	}
   631  	receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2})
   632  	receipts := []*types.Receipt{receipt1, receipt2}
   633  
   634  	// Check that no receipt entries are in a pristine database
   635  	hash := common.BytesToHash([]byte{0x03, 0x14})
   636  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
   637  		t.Fatalf("non existent receipts returned: %v", rs)
   638  	}
   639  	// Insert the body that corresponds to the receipts
   640  	WriteBody(db, hash, 0, body)
   641  
   642  	// Insert the receipt slice into the database and check presence
   643  	WriteReceipts(db, hash, 0, receipts)
   644  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
   645  		t.Fatalf("no receipts returned")
   646  	} else {
   647  		if err := checkReceiptsRLP(rs, receipts); err != nil {
   648  			t.Fatalf(err.Error())
   649  		}
   650  		rec2 := rs[1]
   651  		assert.Len(t, rec2.PSReceipts, 1)
   652  		assert.Equal(t, rec2.RevertReason, []byte("arbitraryvalue"))
   653  		psRec2 := rec2.PSReceipts[types.PrivateStateIdentifier("psi1")]
   654  		assert.Equal(t, psRec2.RevertReason, []byte("arbitraryvalue"))
   655  	}
   656  	// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
   657  	DeleteBody(db, hash, 0)
   658  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
   659  		t.Fatalf("receipts returned when body was deleted: %v", rs)
   660  	}
   661  	// Ensure that receipts without metadata can be returned without the block body too
   662  	if err := checkReceiptsRLP(ReadRawReceipts(db, hash, 0), receipts); err != nil {
   663  		t.Fatalf(err.Error())
   664  	}
   665  	// Sanity check that body alone without the receipt is a full purge
   666  	WriteBody(db, hash, 0, body)
   667  
   668  	DeleteReceipts(db, hash, 0)
   669  	if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
   670  		t.Fatalf("deleted receipts returned: %v", rs)
   671  	}
   672  }
   673  
   674  func checkReceiptsRLP(have, want types.Receipts) error {
   675  	if len(have) != len(want) {
   676  		return fmt.Errorf("receipts sizes mismatch: have %d, want %d", len(have), len(want))
   677  	}
   678  	for i := 0; i < len(want); i++ {
   679  		rlpHave, err := rlp.EncodeToBytes(have[i])
   680  		if err != nil {
   681  			return err
   682  		}
   683  		rlpWant, err := rlp.EncodeToBytes(want[i])
   684  		if err != nil {
   685  			return err
   686  		}
   687  		if !bytes.Equal(rlpHave, rlpWant) {
   688  			return fmt.Errorf("receipt #%d: receipt mismatch: have %s, want %s", i, hex.EncodeToString(rlpHave), hex.EncodeToString(rlpWant))
   689  		}
   690  	}
   691  	return nil
   692  }
   693  
   694  func TestAncientStorage(t *testing.T) {
   695  	// Freezer style fast import the chain.
   696  	frdir, err := ioutil.TempDir("", "")
   697  	if err != nil {
   698  		t.Fatalf("failed to create temp freezer dir: %v", err)
   699  	}
   700  	defer os.Remove(frdir)
   701  
   702  	db, err := NewDatabaseWithFreezer(NewMemoryDatabase(), frdir, "")
   703  	if err != nil {
   704  		t.Fatalf("failed to create database with ancient backend")
   705  	}
   706  	// Create a test block
   707  	block := types.NewBlockWithHeader(&types.Header{
   708  		Number:      big.NewInt(0),
   709  		Extra:       []byte("test block"),
   710  		UncleHash:   types.EmptyUncleHash,
   711  		TxHash:      types.EmptyRootHash,
   712  		ReceiptHash: types.EmptyRootHash,
   713  	})
   714  	// Ensure nothing non-existent will be read
   715  	hash, number := block.Hash(), block.NumberU64()
   716  	if blob := ReadHeaderRLP(db, hash, number); len(blob) > 0 {
   717  		t.Fatalf("non existent header returned")
   718  	}
   719  	if blob := ReadBodyRLP(db, hash, number); len(blob) > 0 {
   720  		t.Fatalf("non existent body returned")
   721  	}
   722  	if blob := ReadReceiptsRLP(db, hash, number); len(blob) > 0 {
   723  		t.Fatalf("non existent receipts returned")
   724  	}
   725  	if blob := ReadTdRLP(db, hash, number); len(blob) > 0 {
   726  		t.Fatalf("non existent td returned")
   727  	}
   728  	// Write and verify the header in the database
   729  	WriteAncientBlock(db, block, nil, big.NewInt(100))
   730  	if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 {
   731  		t.Fatalf("no header returned")
   732  	}
   733  	if blob := ReadBodyRLP(db, hash, number); len(blob) == 0 {
   734  		t.Fatalf("no body returned")
   735  	}
   736  	if blob := ReadReceiptsRLP(db, hash, number); len(blob) == 0 {
   737  		t.Fatalf("no receipts returned")
   738  	}
   739  	if blob := ReadTdRLP(db, hash, number); len(blob) == 0 {
   740  		t.Fatalf("no td returned")
   741  	}
   742  	// Use a fake hash for data retrieval, nothing should be returned.
   743  	fakeHash := common.BytesToHash([]byte{0x01, 0x02, 0x03})
   744  	if blob := ReadHeaderRLP(db, fakeHash, number); len(blob) != 0 {
   745  		t.Fatalf("invalid header returned")
   746  	}
   747  	if blob := ReadBodyRLP(db, fakeHash, number); len(blob) != 0 {
   748  		t.Fatalf("invalid body returned")
   749  	}
   750  	if blob := ReadReceiptsRLP(db, fakeHash, number); len(blob) != 0 {
   751  		t.Fatalf("invalid receipts returned")
   752  	}
   753  	if blob := ReadTdRLP(db, fakeHash, number); len(blob) != 0 {
   754  		t.Fatalf("invalid td returned")
   755  	}
   756  }
   757  
   758  func TestCanonicalHashIteration(t *testing.T) {
   759  	var cases = []struct {
   760  		from, to uint64
   761  		limit    int
   762  		expect   []uint64
   763  	}{
   764  		{1, 8, 0, nil},
   765  		{1, 8, 1, []uint64{1}},
   766  		{1, 8, 10, []uint64{1, 2, 3, 4, 5, 6, 7}},
   767  		{1, 9, 10, []uint64{1, 2, 3, 4, 5, 6, 7, 8}},
   768  		{2, 9, 10, []uint64{2, 3, 4, 5, 6, 7, 8}},
   769  		{9, 10, 10, nil},
   770  	}
   771  	// Test empty db iteration
   772  	db := NewMemoryDatabase()
   773  	numbers, _ := ReadAllCanonicalHashes(db, 0, 10, 10)
   774  	if len(numbers) != 0 {
   775  		t.Fatalf("No entry should be returned to iterate an empty db")
   776  	}
   777  	// Fill database with testing data.
   778  	for i := uint64(1); i <= 8; i++ {
   779  		WriteCanonicalHash(db, common.Hash{}, i)
   780  		WriteTd(db, common.Hash{}, i, big.NewInt(10)) // Write some interferential data
   781  	}
   782  	for i, c := range cases {
   783  		numbers, _ := ReadAllCanonicalHashes(db, c.from, c.to, c.limit)
   784  		if !reflect.DeepEqual(numbers, c.expect) {
   785  			t.Fatalf("Case %d failed, want %v, got %v", i, c.expect, numbers)
   786  		}
   787  	}
   788  }
   789  
   790  func WriteReceiptsMPSV1(db ethdb.KeyValueWriter, hash common.Hash, number uint64, receipts types.Receipts) {
   791  	// Convert the receipts into their storage form and serialize them
   792  	storageReceipts := make([]*types.ReceiptForStorageMPSV1, len(receipts))
   793  	for i, receipt := range receipts {
   794  		storageReceipts[i] = (*types.ReceiptForStorageMPSV1)(receipt)
   795  	}
   796  	bytes, err := rlp.EncodeToBytes(storageReceipts)
   797  	if err != nil {
   798  		log.Crit("Failed to encode block receipts", "err", err)
   799  	}
   800  	// Store the flattened receipt slice
   801  	if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil {
   802  		log.Crit("Failed to store block receipts", "err", err)
   803  	}
   804  }