Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the performance of eth_getLogs #583

Merged
merged 13 commits into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions core/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,12 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
ReceiptHash: types.EmptyRootHash,
}
hash = header.Hash()
WriteHeader(db, header)
WriteCanonicalHash(db, hash, n)
rawdb.WriteHeader(db, header)
rawdb.WriteCanonicalHash(db, hash, n)
WriteTd(db, hash, n, big.NewInt(int64(n+1)))
if full || n == 0 {
block := types.NewBlockWithHeader(header)
WriteBody(db, hash, n, block.Body())
rawdb.WriteBody(db, hash, n, block.Body())
WriteBlockReceipts(db, hash, n, nil)
}
}
Expand Down
37 changes: 10 additions & 27 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
contractValidator "github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/core/vm"
Expand Down Expand Up @@ -437,9 +438,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
}
currentBlock := bc.CurrentBlock()
currentFastBlock := bc.CurrentFastBlock()
if err := WriteHeadBlockHash(bc.db, currentBlock.Hash()); err != nil {
log.Crit("Failed to reset head full block", "err", err)
}
rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash())
if err := WriteHeadFastBlockHash(bc.db, currentFastBlock.Hash()); err != nil {
log.Crit("Failed to reset head fast block", "err", err)
}
Expand Down Expand Up @@ -586,9 +585,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
if err := bc.hc.WriteTd(genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()); err != nil {
log.Crit("Failed to write genesis block TD", "err", err)
}
if err := WriteBlock(bc.db, genesis); err != nil {
log.Crit("Failed to write genesis block", "err", err)
}
rawdb.WriteBlock(bc.db, genesis)
bc.genesisBlock = genesis
bc.insert(bc.genesisBlock, false)
bc.currentBlock.Store(bc.genesisBlock)
Expand Down Expand Up @@ -685,17 +682,9 @@ func (bc *BlockChain) insert(block *types.Block, writeBlock bool) {
updateHeads := GetCanonicalHash(bc.db, block.NumberU64()) != block.Hash()

// Add the block to the canonical chain number scheme and mark as the head
if err := WriteCanonicalHash(bc.db, block.Hash(), block.NumberU64()); err != nil {
log.Crit("Failed to insert block number", "err", err)
}
if err := WriteHeadBlockHash(bc.db, block.Hash()); err != nil {
log.Crit("Failed to insert head block hash", "err", err)
}
if writeBlock {
if err := WriteBlock(bc.db, block); err != nil {
log.Crit("Failed to insert block", "err", err)
}
}
JukLee0ira marked this conversation as resolved.
Show resolved Hide resolved
rawdb.WriteCanonicalHash(bc.db, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(bc.db, block.Hash())
rawdb.WriteBlock(bc.db, block)
bc.currentBlock.Store(block)

// save cache BlockSigners
Expand Down Expand Up @@ -1044,7 +1033,7 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash {
newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1)
bc.currentBlock.Store(newBlock)
WriteHeadBlockHash(bc.db, newBlock.Hash())
rawdb.WriteHeadBlockHash(bc.db, newBlock.Hash())
}
}
}
Expand Down Expand Up @@ -1134,9 +1123,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
return i, fmt.Errorf("failed to set receipts data: %v", err)
}
// Write all the data out into the database
if err := WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()); err != nil {
return i, fmt.Errorf("failed to write block body: %v", err)
}
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
if err := WriteBlockReceipts(batch, block.Hash(), block.NumberU64(), receipts); err != nil {
return i, fmt.Errorf("failed to write block receipts: %v", err)
}
Expand Down Expand Up @@ -1196,9 +1183,7 @@ func (bc *BlockChain) WriteBlockWithoutState(block *types.Block, td *big.Int) (e
if err := bc.hc.WriteTd(block.Hash(), block.NumberU64(), td); err != nil {
return err
}
if err := WriteBlock(bc.db, block); err != nil {
return err
}
rawdb.WriteBlock(bc.db, block)
return nil
}

Expand Down Expand Up @@ -1226,9 +1211,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
}
// Write other block data using a batch.
batch := bc.db.NewBatch()
if err := WriteBlock(batch, block); err != nil {
return NonStatTy, err
}
rawdb.WriteBlock(batch, block)
root, err := state.Commit(bc.chainConfig.IsEIP158(block.Number()))
if err != nil {
return NonStatTy, err
Expand Down
4 changes: 2 additions & 2 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
}
blockchain.mu.Lock()
WriteTd(blockchain.db, block.Hash(), block.NumberU64(), new(big.Int).Add(block.Difficulty(), blockchain.GetTdByHash(block.ParentHash())))
WriteBlock(blockchain.db, block)
rawdb.WriteBlock(blockchain.db, block)
statedb.Commit(true)
blockchain.mu.Unlock()
}
Expand All @@ -148,7 +148,7 @@ func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error
// Manually insert the header into the database, but don't reorganise (allows subsequent testing)
blockchain.mu.Lock()
WriteTd(blockchain.db, header.Hash(), header.Number.Uint64(), new(big.Int).Add(header.Difficulty, blockchain.GetTdByHash(header.ParentHash)))
WriteHeader(blockchain.db, header)
rawdb.WriteHeader(blockchain.db, header)
blockchain.mu.Unlock()
}
return nil
Expand Down
7 changes: 4 additions & 3 deletions core/chain_indexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ package core

import (
"fmt"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"math/big"
"math/rand"
"testing"
"time"

"github.com/XinFinOrg/XDPoSChain/core/rawdb"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
)
Expand Down Expand Up @@ -94,8 +95,8 @@ func testChainIndexer(t *testing.T, count int) {
if number > 0 {
header.ParentHash = GetCanonicalHash(db, number-1)
}
WriteHeader(db, header)
WriteCanonicalHash(db, header.Hash(), number)
rawdb.WriteHeader(db, header)
rawdb.WriteCanonicalHash(db, header.Hash(), number)
}
// Start indexer with an already existing chain
for i := uint64(0); i <= 100; i++ {
Expand Down
68 changes: 0 additions & 68 deletions core/database_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,6 @@ func GetBloomBits(db DatabaseReader, bit uint, section uint64, head common.Hash)
return db.Get(key)
}

// WriteCanonicalHash stores the canonical hash for the given block number.
func WriteCanonicalHash(db ethdb.KeyValueWriter, hash common.Hash, number uint64) error {
key := append(append(headerPrefix, encodeBlockNumber(number)...), numSuffix...)
if err := db.Put(key, hash.Bytes()); err != nil {
log.Crit("Failed to store number to hash mapping", "err", err)
}
return nil
}

// WriteHeadHeaderHash stores the head header's hash.
func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) error {
if err := db.Put(headHeaderKey, hash.Bytes()); err != nil {
Expand All @@ -373,14 +364,6 @@ func WriteHeadHeaderHash(db ethdb.KeyValueWriter, hash common.Hash) error {
return nil
}

// WriteHeadBlockHash stores the head block's hash.
func WriteHeadBlockHash(db ethdb.KeyValueWriter, hash common.Hash) error {
if err := db.Put(headBlockKey, hash.Bytes()); err != nil {
log.Crit("Failed to store last block's hash", "err", err)
}
return nil
}

// WriteHeadFastBlockHash stores the fast head block's hash.
func WriteHeadFastBlockHash(db ethdb.KeyValueWriter, hash common.Hash) error {
if err := db.Put(headFastKey, hash.Bytes()); err != nil {
Expand All @@ -398,44 +381,6 @@ func WriteTrieSyncProgress(db ethdb.KeyValueWriter, count uint64) error {
return nil
}

// WriteHeader serializes a block header into the database.
func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) error {
data, err := rlp.EncodeToBytes(header)
if err != nil {
return err
}
hash := header.Hash().Bytes()
num := header.Number.Uint64()
encNum := encodeBlockNumber(num)
key := append(blockHashPrefix, hash...)
if err := db.Put(key, encNum); err != nil {
log.Crit("Failed to store hash to number mapping", "err", err)
}
key = append(append(headerPrefix, encNum...), hash...)
if err := db.Put(key, data); err != nil {
log.Crit("Failed to store header", "err", err)
}
return nil
}

// WriteBody serializes the body of a block into the database.
func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *types.Body) error {
data, err := rlp.EncodeToBytes(body)
if err != nil {
return err
}
return WriteBodyRLP(db, hash, number, data)
}

// WriteBodyRLP writes a serialized body of a block into the database.
func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) error {
key := append(append(bodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
if err := db.Put(key, rlp); err != nil {
log.Crit("Failed to store block body", "err", err)
}
return nil
}

// WriteTd serializes the total difficulty of a block into the database.
func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) error {
data, err := rlp.EncodeToBytes(td)
Expand All @@ -449,19 +394,6 @@ func WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.I
return nil
}

// WriteBlock serializes a block into the database, header and body separately.
func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) error {
// Store the body first to retain database consistency
if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil {
return err
}
// Store the header too, signaling full block ownership
if err := WriteHeader(db, block.Header()); err != nil {
return err
}
return nil
}

// WriteBlockReceipts stores all the transaction receipts belonging to a block
// as a single receipt slice. This is used during chain reorganisations for
// rescheduling dropped transactions.
Expand Down
40 changes: 10 additions & 30 deletions core/database_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ func TestHeaderStorage(t *testing.T) {
t.Fatalf("Non existent header returned: %v", entry)
}
// Write and verify the header in the database
if err := WriteHeader(db, header); err != nil {
t.Fatalf("Failed to write header into database: %v", err)
}
rawdb.WriteHeader(db, header)
if entry := GetHeader(db, header.Hash(), header.Number.Uint64()); entry == nil {
t.Fatalf("Stored header not found")
} else if entry.Hash() != header.Hash() {
Expand Down Expand Up @@ -78,9 +76,7 @@ func TestBodyStorage(t *testing.T) {
t.Fatalf("Non existent body returned: %v", entry)
}
// Write and verify the body in the database
if err := WriteBody(db, hash, 0, body); err != nil {
t.Fatalf("Failed to write body into database: %v", err)
}
rawdb.WriteBody(db, hash, 0, body)
if entry := GetBody(db, hash, 0); entry == nil {
t.Fatalf("Stored body not found")
} else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(types.Transactions(body.Transactions)) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(body.Uncles) {
Expand Down Expand Up @@ -124,9 +120,7 @@ func TestBlockStorage(t *testing.T) {
t.Fatalf("Non existent body returned: %v", entry)
}
// Write and verify the block in the database
if err := WriteBlock(db, block); err != nil {
t.Fatalf("Failed to write block into database: %v", err)
}
rawdb.WriteBlock(db, block)
if entry := GetBlock(db, block.Hash(), block.NumberU64()); entry == nil {
t.Fatalf("Stored block not found")
} else if entry.Hash() != block.Hash() {
Expand Down Expand Up @@ -165,30 +159,22 @@ func TestPartialBlockStorage(t *testing.T) {
ReceiptHash: types.EmptyRootHash,
})
// Store a header and check that it's not recognized as a block
if err := WriteHeader(db, block.Header()); err != nil {
t.Fatalf("Failed to write header into database: %v", err)
}
rawdb.WriteHeader(db, block.Header())
if entry := GetBlock(db, block.Hash(), block.NumberU64()); entry != nil {
t.Fatalf("Non existent block returned: %v", entry)
}
DeleteHeader(db, block.Hash(), block.NumberU64())

// Store a body and check that it's not recognized as a block
if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil {
t.Fatalf("Failed to write body into database: %v", err)
}
rawdb.WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
if entry := GetBlock(db, block.Hash(), block.NumberU64()); entry != nil {
t.Fatalf("Non existent block returned: %v", entry)
}
DeleteBody(db, block.Hash(), block.NumberU64())

// Store a header and a body separately and check reassembly
if err := WriteHeader(db, block.Header()); err != nil {
t.Fatalf("Failed to write header into database: %v", err)
}
if err := WriteBody(db, block.Hash(), block.NumberU64(), block.Body()); err != nil {
t.Fatalf("Failed to write body into database: %v", err)
}
rawdb.WriteHeader(db, block.Header())
rawdb.WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
if entry := GetBlock(db, block.Hash(), block.NumberU64()); entry == nil {
t.Fatalf("Stored block not found")
} else if entry.Hash() != block.Hash() {
Expand Down Expand Up @@ -231,9 +217,7 @@ func TestCanonicalMappingStorage(t *testing.T) {
t.Fatalf("Non existent canonical mapping returned: %v", entry)
}
// Write and verify the TD in the database
if err := WriteCanonicalHash(db, hash, number); err != nil {
t.Fatalf("Failed to write canonical mapping into database: %v", err)
}
rawdb.WriteCanonicalHash(db, hash, number)
if entry := GetCanonicalHash(db, number); entry == (common.Hash{}) {
t.Fatalf("Stored canonical mapping not found")
} else if entry != hash {
Expand Down Expand Up @@ -268,9 +252,7 @@ func TestHeadStorage(t *testing.T) {
if err := WriteHeadHeaderHash(db, blockHead.Hash()); err != nil {
t.Fatalf("Failed to write head header hash: %v", err)
}
if err := WriteHeadBlockHash(db, blockFull.Hash()); err != nil {
t.Fatalf("Failed to write head block hash: %v", err)
}
rawdb.WriteHeadBlockHash(db, blockFull.Hash())
if err := WriteHeadFastBlockHash(db, blockFast.Hash()); err != nil {
t.Fatalf("Failed to write fast head block hash: %v", err)
}
Expand Down Expand Up @@ -304,9 +286,7 @@ func TestLookupStorage(t *testing.T) {
}
}
// Insert all the transactions into the database, and verify contents
if err := WriteBlock(db, block); err != nil {
t.Fatalf("failed to write block contents: %v", err)
}
rawdb.WriteBlock(db, block)
if err := WriteTxLookupEntries(db, block); err != nil {
t.Fatalf("failed to write transactions: %v", err)
}
Expand Down
12 changes: 3 additions & 9 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,12 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
if err := WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty); err != nil {
return nil, err
}
if err := WriteBlock(db, block); err != nil {
return nil, err
}
rawdb.WriteBlock(db, block)
if err := WriteBlockReceipts(db, block.Hash(), block.NumberU64(), nil); err != nil {
return nil, err
}
if err := WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
return nil, err
}
if err := WriteHeadBlockHash(db, block.Hash()); err != nil {
return nil, err
}
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(db, block.Hash())
if err := WriteHeadHeaderHash(db, block.Hash()); err != nil {
return nil, err
}
Expand Down
Loading