aboutsummaryrefslogtreecommitdiffstats
path: root/core/blockchain.go
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2018-11-15 13:30:50 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:53 +0800
commitb26e4c9adaa2952a63bf811f991a3e6fb9fc5646 (patch)
tree84f78ba24e34b4ae6bca777fd6edc659bb16feb9 /core/blockchain.go
parent426fdd07f71aea7de2fe8ca010f17afaf774c047 (diff)
downloaddexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.tar
dexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.tar.gz
dexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.tar.bz2
dexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.tar.lz
dexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.tar.xz
dexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.tar.zst
dexon-b26e4c9adaa2952a63bf811f991a3e6fb9fc5646.zip
core: refactor validator and fix light node sync (#25)
Remove custom Dexon validator by adding a new `ValidateWitnessData` method into the validator interface. This allow us to properly detect know blocks. This also allow other gdex "light" client to sync compaction chain. Also, setup a standalone RPC node for handling RPC reqeusts.
Diffstat (limited to 'core/blockchain.go')
-rw-r--r--core/blockchain.go121
1 files changed, 25 insertions, 96 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index 67bfacb0a..4f3eefc1d 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -237,79 +237,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
return bc, nil
}
-func NewBlockChainWithDexonValidator(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
- if cacheConfig == nil {
- cacheConfig = &CacheConfig{
- TrieNodeLimit: 256 * 1024 * 1024,
- TrieTimeLimit: 5 * time.Minute,
- }
- }
- bodyCache, _ := lru.New(bodyCacheLimit)
- bodyRLPCache, _ := lru.New(bodyCacheLimit)
- receiptsCache, _ := lru.New(receiptsCacheLimit)
- blockCache, _ := lru.New(blockCacheLimit)
- futureBlocks, _ := lru.New(maxFutureBlocks)
- badBlocks, _ := lru.New(badBlockLimit)
-
- bc := &BlockChain{
- chainConfig: chainConfig,
- cacheConfig: cacheConfig,
- db: db,
- triegc: prque.New(nil),
- stateCache: state.NewDatabase(db),
- quit: make(chan struct{}),
- bodyCache: bodyCache,
- bodyRLPCache: bodyRLPCache,
- receiptsCache: receiptsCache,
- blockCache: blockCache,
- futureBlocks: futureBlocks,
- engine: engine,
- vmConfig: vmConfig,
- badBlocks: badBlocks,
- pendingBlocks: make(map[uint64]struct {
- block *types.Block
- receipts types.Receipts
- }),
- confirmedBlocks: make(map[uint32]map[coreCommon.Hash]*blockInfo),
- addressNonce: make(map[uint32]map[common.Address]uint64),
- addressCost: make(map[uint32]map[common.Address]*big.Int),
- addressCounter: make(map[uint32]map[common.Address]uint64),
- chainLastHeight: make(map[uint32]uint64),
- }
- bc.SetValidator(NewDexonBlockValidator(chainConfig, bc, engine))
- bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))
-
- var err error
- bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt)
- if err != nil {
- return nil, err
- }
- bc.genesisBlock = bc.GetBlockByNumber(0)
- if bc.genesisBlock == nil {
- return nil, ErrNoGenesis
- }
- if err := bc.loadLastState(); err != nil {
- return nil, err
- }
- // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
- for hash := range BadHashes {
- if header := bc.GetHeaderByHash(hash); header != nil {
- // get the canonical block corresponding to the offending header's number
- headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64())
- // make sure the headerByNumber (if present) is in our current canonical chain
- if headerByNumber != nil && headerByNumber.Hash() == header.Hash() {
- log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash)
- bc.SetHead(header.Number.Uint64() - 1)
- log.Error("Chain rewind was successful, resuming normal operation")
- }
- }
- }
-
- // Take ownership of this particular state
- go bc.update()
- return bc, nil
-}
-
func (bc *BlockChain) getProcInterrupt() bool {
return atomic.LoadInt32(&bc.procInterrupt) == 1
}
@@ -1600,7 +1527,15 @@ func (bc *BlockChain) ProcessPendingBlock(block *types.Block, witness *coreTypes
return n, err
}
-func (bc *BlockChain) processPendingBlock(block *types.Block, witness *coreTypes.Witness) (*common.Hash, []interface{}, []*types.Log, error) {
+func (bc *BlockChain) processPendingBlock(
+ block *types.Block, witness *coreTypes.Witness) (*common.Hash, []interface{}, []*types.Log, error) {
+ // Pre-checks passed, start the full block imports
+ bc.wg.Add(1)
+ defer bc.wg.Done()
+
+ bc.chainmu.Lock()
+ defer bc.chainmu.Unlock()
+
// A queued approach to delivering events. This is generally
// faster than direct delivery and requires much less mutex
// acquiring.
@@ -1611,12 +1546,6 @@ func (bc *BlockChain) processPendingBlock(block *types.Block, witness *coreTypes
coalescedLogs []*types.Log
)
- var witnessData types.WitnessData
- if err := rlp.Decode(bytes.NewReader(witness.Data), &witnessData); err != nil {
- log.Error("Witness rlp decode failed", "error", err)
- panic(err)
- }
-
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, block.Number()), []*types.Block{block})
@@ -1626,19 +1555,18 @@ func (bc *BlockChain) processPendingBlock(block *types.Block, witness *coreTypes
}
bstart := time.Now()
- currentBlock := bc.CurrentBlock()
- if witness.Height > currentBlock.NumberU64() && witness.Height != 0 {
- if bc.pendingBlocks[witness.Height].block.Root() != witnessData.Root {
- return nil, nil, nil, fmt.Errorf("invalid witness root %s vs %s",
- bc.pendingBlocks[witness.Height].block.Root().String(), witnessData.Root.String())
- }
+ var witnessData types.WitnessData
+ if err := rlp.Decode(bytes.NewReader(witness.Data), &witnessData); err != nil {
+ log.Error("Witness rlp decode failed", "error", err)
+ panic(err)
+ }
- if bc.pendingBlocks[witness.Height].block.ReceiptHash() != witnessData.ReceiptHash {
- return nil, nil, nil, fmt.Errorf("invalid witness receipt hash %s vs %s",
- bc.pendingBlocks[witness.Height].block.ReceiptHash().String(), witnessData.ReceiptHash.String())
- }
+ if err := bc.Validator().ValidateWitnessData(witness.Height, witnessData); err != nil {
+ return nil, nil, nil, fmt.Errorf("valiadte witness data error: %v", err)
}
+ currentBlock := bc.CurrentBlock()
+
var parentBlock *types.Block
var pendingState *state.StateDB
var err error
@@ -1680,12 +1608,6 @@ func (bc *BlockChain) processPendingBlock(block *types.Block, witness *coreTypes
return nil, nil, nil, fmt.Errorf("finalize error: %v", err)
}
- // Validate the state using the default validator
- err = bc.Validator().ValidateState(block, nil, pendingState, receipts, *usedGas)
- if err != nil {
- bc.reportBlock(block, receipts, err)
- return nil, nil, nil, fmt.Errorf("valiadte state error: %v", err)
- }
proctime := time.Since(bstart)
// commit state to refresh stateCache
@@ -1790,6 +1712,13 @@ func (bc *BlockChain) GetPendingBlock() *types.Block {
return bc.pendingBlocks[bc.lastPendingHeight].block
}
+func (bc *BlockChain) GetPendingBlockByNumber(number uint64) *types.Block {
+ bc.pendingBlockMu.RLock()
+ defer bc.pendingBlockMu.RUnlock()
+
+ return bc.pendingBlocks[number].block
+}
+
func (bc *BlockChain) GetPending() (*types.Block, *state.StateDB) {
block := bc.GetPendingBlock()
s, err := state.New(block.Header().Root, bc.stateCache)