aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorBojie Wu <bojie@dexon.org>2018-10-09 13:28:45 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:52 +0800
commit7c1386d928acd050684f435e49149696bcc0a637 (patch)
treedb7141013bd1aa9e2349aa8b161d6529ff25cd40 /core
parentd44a8b7003df87c7e7662a7ac86fb351872cd371 (diff)
downloaddexon-7c1386d928acd050684f435e49149696bcc0a637.tar
dexon-7c1386d928acd050684f435e49149696bcc0a637.tar.gz
dexon-7c1386d928acd050684f435e49149696bcc0a637.tar.bz2
dexon-7c1386d928acd050684f435e49149696bcc0a637.tar.lz
dexon-7c1386d928acd050684f435e49149696bcc0a637.tar.xz
dexon-7c1386d928acd050684f435e49149696bcc0a637.tar.zst
dexon-7c1386d928acd050684f435e49149696bcc0a637.zip
app: add cache mechanism to increase performance
Diffstat (limited to 'core')
-rw-r--r--core/blockchain.go178
-rw-r--r--core/types/block.go35
-rw-r--r--core/types/gen_header_json.go75
3 files changed, 136 insertions, 152 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)
diff --git a/core/types/block.go b/core/types/block.go
index 9e42a776a..07fc55358 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -75,25 +75,26 @@ type WitnessData struct {
// Header represents a block header in the Ethereum blockchain.
type Header struct {
- ParentHash common.Hash `json:"parentHash" gencodec:"required"`
- UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
- Coinbase common.Address `json:"miner" gencodec:"required"`
- Root common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
- ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
- Bloom Bloom `json:"logsBloom" gencodec:"required"`
- Difficulty *big.Int `json:"difficulty" gencodec:"required"`
- Number *big.Int `json:"number" gencodec:"required"`
- GasLimit uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed uint64 `json:"gasUsed" gencodec:"required"`
- Time uint64 `json:"timestamp" gencodec:"required"`
- Extra []byte `json:"extraData" gencodec:"required"`
+ ParentHash common.Hash `json:"parentHash" gencodec:"required"`
+ UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
+ Coinbase common.Address `json:"miner" gencodec:"required"`
+ Root common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
+ ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
+ Bloom Bloom `json:"logsBloom" gencodec:"required"`
+ Difficulty *big.Int `json:"difficulty" gencodec:"required"`
+ Number *big.Int `json:"number" gencodec:"required"`
+ GasLimit uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed uint64 `json:"gasUsed" gencodec:"required"`
+ Time uint64 `json:"timestamp" gencodec:"required"`
+ Extra []byte `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
- Randomness []byte `json:"randomness" gencodec:"required"`
- Position coreTypes.Position `json:"position" gencodec:"required"`
- Round uint64 `json:"round" gencodec:"required"`
- DexconMeta []byte `json:"dexconMeta" gencodec:"required"`
+ Randomness []byte `json:"randomness" gencodec:"required"`
+ Position coreTypes.Position `json:"position" gencodec:"required"`
+ Round uint64 `json:"round" gencodec:"required"`
+ DexconMeta []byte `json:"dexconMeta" gencodec:"required"`
+ BlockReward *big.Int `json:"blockReward" gencodec:"required"`
}
// field type overrides for gencodec
diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go
index 31796bf5b..b49d48f14 100644
--- a/core/types/gen_header_json.go
+++ b/core/types/gen_header_json.go
@@ -17,25 +17,26 @@ var _ = (*headerMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
- ParentHash common.Hash `json:"parentHash" gencodec:"required"`
- UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
- Coinbase common.Address `json:"miner" gencodec:"required"`
- Root common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
- ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
- Bloom Bloom `json:"logsBloom" gencodec:"required"`
- Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
- Number *hexutil.Big `json:"number" gencodec:"required"`
- GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
- Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
+ ParentHash common.Hash `json:"parentHash" gencodec:"required"`
+ UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
+ Coinbase common.Address `json:"miner" gencodec:"required"`
+ Root common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
+ ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
+ Bloom Bloom `json:"logsBloom" gencodec:"required"`
+ Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
+ Number *hexutil.Big `json:"number" gencodec:"required"`
+ GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
+ Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
+ Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
- Randomness hexutil.Bytes `json:"randomness" gencodec:"required"`
- Position types.Position `json:"position" gencodec:"required"`
- Round hexutil.Uint64 `json:"round" gencodec:"required"`
- DexconMeta hexutil.Bytes `json:"dexconMeta" gencodec:"required"`
+ Randomness hexutil.Bytes `json:"randomness" gencodec:"required"`
+ Position types.Position `json:"position" gencodec:"required"`
+ Round hexutil.Uint64 `json:"round" gencodec:"required"`
+ DexconMeta hexutil.Bytes `json:"dexconMeta" gencodec:"required"`
+ BlockReward *big.Int `json:"blockReward" gencodec:"required"`
Hash common.Hash `json:"hash"`
}
var enc Header
@@ -58,6 +59,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.Position = h.Position
enc.Round = hexutil.Uint64(h.Round)
enc.DexconMeta = h.DexconMeta
+ enc.BlockReward = h.BlockReward
enc.Hash = h.Hash()
return json.Marshal(&enc)
}
@@ -65,25 +67,26 @@ func (h Header) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
- ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
- UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
- Coinbase *common.Address `json:"miner" gencodec:"required"`
- Root *common.Hash `json:"stateRoot" gencodec:"required"`
- TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
- ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
- Bloom *Bloom `json:"logsBloom" gencodec:"required"`
- Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
- Number *hexutil.Big `json:"number" gencodec:"required"`
- GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
- Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
+ ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
+ UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
+ Coinbase *common.Address `json:"miner" gencodec:"required"`
+ Root *common.Hash `json:"stateRoot" gencodec:"required"`
+ TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
+ ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
+ Bloom *Bloom `json:"logsBloom" gencodec:"required"`
+ Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
+ Number *hexutil.Big `json:"number" gencodec:"required"`
+ GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
+ GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
+ Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
+ Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *BlockNonce `json:"nonce"`
- Randomness *hexutil.Bytes `json:"randomness" gencodec:"required"`
- Position *types.Position `json:"position" gencodec:"required"`
- Round *hexutil.Uint64 `json:"round" gencodec:"required"`
- DexconMeta *hexutil.Bytes `json:"dexconMeta" gencodec:"required"`
+ Randomness *hexutil.Bytes `json:"randomness" gencodec:"required"`
+ Position *types.Position `json:"position" gencodec:"required"`
+ Round *hexutil.Uint64 `json:"round" gencodec:"required"`
+ DexconMeta *hexutil.Bytes `json:"dexconMeta" gencodec:"required"`
+ BlockReward *big.Int `json:"blockReward" gencodec:"required"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
@@ -163,5 +166,9 @@ func (h *Header) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'dexconMeta' for Header")
}
h.DexconMeta = *dec.DexconMeta
+ if dec.BlockReward == nil {
+ return errors.New("missing required field 'blockReward' for Header")
+ }
+ h.BlockReward = dec.BlockReward
return nil
}