aboutsummaryrefslogtreecommitdiffstats
path: root/core/blockchain.go
diff options
context:
space:
mode:
authorBojie Wu <bojie@dexon.org>2018-10-09 13:28:45 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-06-12 17:27:17 +0800
commit3f320c9048198d14bc44413861efcbc5665324b1 (patch)
treed0ae47cd428ba4fa21546efcd1ac4ab50933d600 /core/blockchain.go
parente0c84599b660438d34972ceb494d36f83c26d430 (diff)
downloadgo-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.tar
go-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.tar.gz
go-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.tar.bz2
go-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.tar.lz
go-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.tar.xz
go-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.tar.zst
go-tangerine-3f320c9048198d14bc44413861efcbc5665324b1.zip
app: add cache mechanism to increase performance
Diffstat (limited to 'core/blockchain.go')
-rw-r--r--core/blockchain.go178
1 files changed, 77 insertions, 101 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index 80d4b2f08..429b3a4cc 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -30,7 +30,7 @@ import (
coreCommon "github.com/dexon-foundation/dexon-consensus-core/common"
coreTypes "github.com/dexon-foundation/dexon-consensus-core/core/types"
- lru "github.com/hashicorp/golang-lru"
+ "github.com/hashicorp/golang-lru"
"github.com/dexon-foundation/dexon/common"
"github.com/dexon-foundation/dexon/common/math"
@@ -142,9 +142,11 @@ type BlockChain struct {
badBlocks *lru.Cache // Bad block cache
shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block.
- confirmedBlockMu sync.Mutex
- confirmedBlocks map[coreCommon.Hash]*coreTypes.Block
- chainConfirmedBlocks map[uint32][]*coreTypes.Block
+ confirmedBlocks map[coreCommon.Hash]*blockInfo
+ addressNonce map[common.Address]uint64
+ addressCost map[common.Address]*big.Int
+ addressCounter map[common.Address]uint64
+ chainLastHeight map[uint32]uint64
pendingBlocks map[uint64]struct {
block *types.Block
@@ -171,28 +173,30 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
badBlocks, _ := lru.New(badBlockLimit)
bc := &BlockChain{
- chainConfig: chainConfig,
- cacheConfig: cacheConfig,
- db: db,
- triegc: prque.New(nil),
- stateCache: state.NewDatabase(db),
- stateCache: state.NewDatabaseWithCache(db, cacheConfig.TrieCleanLimit),
- quit: make(chan struct{}),
- shouldPreserve: shouldPreserve,
- bodyCache: bodyCache,
- bodyRLPCache: bodyRLPCache,
- receiptsCache: receiptsCache,
- blockCache: blockCache,
- futureBlocks: futureBlocks,
- engine: engine,
- vmConfig: vmConfig,
- badBlocks: badBlocks,
- confirmedBlocks: make(map[coreCommon.Hash]*coreTypes.Block),
- chainConfirmedBlocks: make(map[uint32][]*coreTypes.Block),
+ chainConfig: chainConfig,
+ cacheConfig: cacheConfig,
+ db: db,
+ triegc: prque.New(nil),
+ stateCache: state.NewDatabaseWithCache(db, cacheConfig.TrieCleanLimit),
+ quit: make(chan struct{}),
+ shouldPreserve: shouldPreserve,
+ bodyCache: bodyCache,
+ bodyRLPCache: bodyRLPCache,
+ receiptsCache: receiptsCache,
+ blockCache: blockCache,
+ futureBlocks: futureBlocks,
+ engine: engine,
+ vmConfig: vmConfig,
+ badBlocks: badBlocks,
+ confirmedBlocks: make(map[coreCommon.Hash]*blockInfo),
pendingBlocks: make(map[uint64]struct {
block *types.Block
receipts types.Receipts
}),
+ addressNonce: make(map[common.Address]uint64),
+ addressCost: make(map[common.Address]*big.Int),
+ addressCounter: make(map[common.Address]uint64),
+ chainLastHeight: make(map[uint32]uint64),
}
bc.SetValidator(NewDexonBlockValidator(chainConfig, bc, engine))
bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
@@ -236,105 +240,79 @@ func (bc *BlockChain) GetVMConfig() *vm.Config {
return &bc.vmConfig
}
-func (bc *BlockChain) AddConfirmedBlock(block *coreTypes.Block) {
- bc.confirmedBlockMu.Lock()
- defer bc.confirmedBlockMu.Unlock()
-
- bc.confirmedBlocks[block.Hash] = block
- chainBlocks := bc.chainConfirmedBlocks[block.Position.ChainID]
- bc.chainConfirmedBlocks[block.Position.ChainID] = append(chainBlocks, block)
+type blockInfo struct {
+ addresses map[common.Address]interface{}
+ block *coreTypes.Block
}
-func (bc *BlockChain) RemoveConfirmedBlock(hash coreCommon.Hash) {
- bc.confirmedBlockMu.Lock()
- defer bc.confirmedBlockMu.Unlock()
-
- block := bc.confirmedBlocks[hash]
- delete(bc.confirmedBlocks, block.Hash)
-
- chainBlocks := bc.chainConfirmedBlocks[block.Position.ChainID]
- bc.chainConfirmedBlocks[block.Position.ChainID] = chainBlocks[1:]
- if len(bc.chainConfirmedBlocks[block.Position.ChainID]) == 0 {
- delete(bc.chainConfirmedBlocks, block.Position.ChainID)
+func (bc *BlockChain) AddConfirmedBlock(block *coreTypes.Block) error {
+ var transactions types.Transactions
+ err := rlp.Decode(bytes.NewReader(block.Payload), &transactions)
+ if err != nil {
+ return err
}
-}
-
-func (bc *BlockChain) GetConfirmedBlockByHash(hash coreCommon.Hash) *coreTypes.Block {
- bc.confirmedBlockMu.Lock()
- defer bc.confirmedBlockMu.Unlock()
-
- return bc.confirmedBlocks[hash]
-}
-
-func (bc *BlockChain) GetConfirmedTxsByAddress(chainID uint32, address common.Address) (types.Transactions, error) {
- bc.confirmedBlockMu.Lock()
- defer bc.confirmedBlockMu.Unlock()
- var addressTxs types.Transactions
- for _, block := range bc.chainConfirmedBlocks[chainID] {
- var transactions types.Transactions
- err := rlp.Decode(bytes.NewReader(block.Payload), &transactions)
+ addressMap := map[common.Address]interface{}{}
+ for _, tx := range transactions {
+ msg, err := tx.AsMessage(types.MakeSigner(bc.Config(), new(big.Int)))
if err != nil {
- return nil, err
+ return err
}
+ addressMap[msg.From()] = nil
- for _, tx := range transactions {
- msg, err := tx.AsMessage(types.MakeSigner(bc.chainConfig, new(big.Int)))
- if err != nil {
- return nil, err
- }
+ // get latest nonce in block
+ bc.addressNonce[msg.From()] = msg.Nonce()
- if msg.From() == address {
- addressTxs = append(addressTxs, tx)
- }
+ // calculate max cost in confirmed blocks
+ if bc.addressCost[msg.From()] == nil {
+ bc.addressCost[msg.From()] = tx.Cost()
+ } else {
+ bc.addressCost[msg.From()] = new(big.Int).Add(bc.addressCost[msg.From()], tx.Cost())
}
}
- return addressTxs, nil
-}
-func (bc *BlockChain) GetLastNonceFromConfirmedBlocks(chainID uint32, address common.Address) (uint64, bool, error) {
- chainBlocks, exist := bc.chainConfirmedBlocks[chainID]
- if !exist {
- return 0, true, nil
+ for addr := range addressMap {
+ bc.addressCounter[addr]++
}
- for i := len(chainBlocks) - 1; i >= 0; i-- {
- var transactions types.Transactions
- err := rlp.Decode(bytes.NewReader(chainBlocks[i].Payload), &transactions)
- if err != nil {
- return 0, true, err
- }
-
- for _, tx := range transactions {
- msg, err := tx.AsMessage(types.MakeSigner(bc.chainConfig, new(big.Int)))
- if err != nil {
- return 0, true, err
- }
+ bc.confirmedBlocks[block.Hash] = &blockInfo{
+ addresses: addressMap,
+ block: block,
+ }
+ bc.chainLastHeight[block.Position.ChainID] = block.Position.Height
+ return nil
+}
- if msg.From() == address {
- return msg.Nonce(), false, nil
- }
+func (bc *BlockChain) RemoveConfirmedBlock(hash coreCommon.Hash) {
+ blockInfo := bc.confirmedBlocks[hash]
+ for addr := range blockInfo.addresses {
+ bc.addressCounter[addr]--
+ if bc.addressCounter[addr] == 0 {
+ delete(bc.addressCounter, addr)
+ delete(bc.addressCost, addr)
+ delete(bc.addressNonce, addr)
}
}
- return 0, true, nil
+ delete(bc.confirmedBlocks, hash)
}
-func (bc *BlockChain) GetChainLastConfirmedHeight(chainID uint32) (uint64, bool) {
- bc.confirmedBlockMu.Lock()
- defer bc.confirmedBlockMu.Unlock()
+func (bc *BlockChain) GetConfirmedBlockByHash(hash coreCommon.Hash) *coreTypes.Block {
+ return bc.confirmedBlocks[hash].block
+}
- chainBlocks := bc.chainConfirmedBlocks[chainID]
- size := len(chainBlocks)
- if size == 0 {
- return 0, true
- }
+func (bc *BlockChain) GetLastNonceInConfirmedBlocks(address common.Address) (uint64, bool) {
+ nonce, exist := bc.addressNonce[address]
+ return nonce, exist
+}
- return chainBlocks[size-1].Position.Height, false
+func (bc *BlockChain) GetCostInConfirmedBlocks(address common.Address) (*big.Int, bool) {
+ cost, exist := bc.addressCost[address]
+ return cost, exist
}
-func (bc *BlockChain) GetConfirmedBlocksByChainID(chainID uint32) []*coreTypes.Block {
- return bc.chainConfirmedBlocks[chainID]
+func (bc *BlockChain) GetChainLastConfirmedHeight(chainID uint32) uint64 {
+ return bc.chainLastHeight[chainID]
}
// loadLastState loads the last known chain state from the database. This method
@@ -1615,11 +1593,10 @@ func (bc *BlockChain) processPendingBlock(block *types.Block, witness *coreTypes
proctime := time.Since(bstart)
// commit state to refresh stateCache
- root, err := pendingState.Commit(true)
+ _, err = pendingState.Commit(true)
if err != nil {
return 0, nil, nil, fmt.Errorf("pendingState commit error: %v", err)
}
- log.Info("Commit pending root", "hash", root)
// add into pending blocks
bc.pendingBlocks[block.NumberU64()] = struct {
@@ -1641,7 +1618,6 @@ func (bc *BlockChain) processPendingBlock(block *types.Block, witness *coreTypes
}
// Write the block to the chain and get the status.
- log.Debug("Insert pending block", "height", pendingHeight)
status, err := bc.WriteBlockWithState(pendingIns.block, pendingIns.receipts, s)
if err != nil {
return 0, events, coalescedLogs, fmt.Errorf("WriteBlockWithState error: %v", err)