Improved chain manager, improved block processor, fixed tests
* ChainManager allows cached future blocks for later processing * BlockProcessor allows a 4 second window on future blocks * Fixed tests
This commit is contained in:
		| @@ -260,7 +260,7 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header) error { | ||||
| 	} | ||||
|  | ||||
| 	// Allow future blocks up to 10 seconds | ||||
| 	if int64(block.Time)+10 > time.Now().Unix() { | ||||
| 	if int64(block.Time) > time.Now().Unix()+4 { | ||||
| 		return BlockFutureErr | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -22,10 +22,11 @@ func TestNumber(t *testing.T) { | ||||
| 	bp, chain := proc() | ||||
| 	block1 := chain.NewBlock(common.Address{}) | ||||
| 	block1.Header().Number = big.NewInt(3) | ||||
| 	block1.Header().Time-- | ||||
|  | ||||
| 	err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header()) | ||||
| 	if err != BlockNumberErr { | ||||
| 		t.Errorf("expected block number error") | ||||
| 		t.Errorf("expected block number error %v", err) | ||||
| 	} | ||||
|  | ||||
| 	block1 = chain.NewBlock(common.Address{}) | ||||
|   | ||||
| @@ -109,6 +109,7 @@ func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Dat | ||||
| // Effectively a fork factory | ||||
| func newChainManager(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager { | ||||
| 	bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: GenesisBlock(db), eventMux: eventMux} | ||||
| 	bc.futureBlocks = NewBlockCache(1000) | ||||
| 	if block == nil { | ||||
| 		bc.Reset() | ||||
| 	} else { | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
| 	"io" | ||||
| 	"math/big" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/core/state" | ||||
| @@ -95,7 +96,8 @@ type ChainManager struct { | ||||
| 	transState *state.StateDB | ||||
| 	txState    *state.ManagedState | ||||
|  | ||||
| 	cache *BlockCache | ||||
| 	cache        *BlockCache | ||||
| 	futureBlocks *BlockCache | ||||
|  | ||||
| 	quit chan struct{} | ||||
| } | ||||
| @@ -107,6 +109,7 @@ func NewChainManager(blockDb, stateDb common.Database, mux *event.TypeMux) *Chai | ||||
| 	// Take ownership of this particular state | ||||
| 	bc.txState = state.ManageState(bc.State().Copy()) | ||||
|  | ||||
| 	bc.futureBlocks = NewBlockCache(254) | ||||
| 	bc.makeCache() | ||||
|  | ||||
| 	go bc.update() | ||||
| @@ -433,6 +436,19 @@ type queueEvent struct { | ||||
| 	splitCount     int | ||||
| } | ||||
|  | ||||
| func (self *ChainManager) procFutureBlocks() { | ||||
| 	self.futureBlocks.mu.Lock() | ||||
|  | ||||
| 	blocks := make([]*types.Block, len(self.futureBlocks.blocks)) | ||||
| 	for i, hash := range self.futureBlocks.hashes { | ||||
| 		blocks[i] = self.futureBlocks.Get(hash) | ||||
| 	} | ||||
| 	self.futureBlocks.mu.Unlock() | ||||
|  | ||||
| 	types.BlockBy(types.Number).Sort(blocks) | ||||
| 	self.InsertChain(blocks) | ||||
| } | ||||
|  | ||||
| func (self *ChainManager) InsertChain(chain types.Blocks) error { | ||||
| 	//self.tsmu.Lock() | ||||
| 	//defer self.tsmu.Unlock() | ||||
| @@ -452,12 +468,27 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if err == BlockEqualTSErr { | ||||
| 				//queue[i] = ChainSideEvent{block, logs} | ||||
| 				// XXX silently discard it? | ||||
| 			block.Td = new(big.Int) | ||||
| 			// Do not penelise on future block. We'll need a block queue eventually that will queue | ||||
| 			// future block for future use | ||||
| 			if err == BlockFutureErr { | ||||
| 				self.futureBlocks.Push(block) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if IsParentErr(err) && self.futureBlocks.Has(block.ParentHash()) { | ||||
| 				self.futureBlocks.Push(block) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			/* | ||||
| 				if err == BlockEqualTSErr { | ||||
| 					//queue[i] = ChainSideEvent{block, logs} | ||||
| 					// XXX silently discard it? | ||||
| 					continue | ||||
| 				} | ||||
| 			*/ | ||||
|  | ||||
| 			h := block.Header() | ||||
| 			chainlogger.Errorf("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes()[:4]) | ||||
| 			chainlogger.Errorln(err) | ||||
| @@ -513,6 +544,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { | ||||
| 		} | ||||
| 		self.mu.Unlock() | ||||
|  | ||||
| 		self.futureBlocks.Delete(block.Hash()) | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	if len(chain) > 0 && glog.V(logger.Info) { | ||||
| @@ -527,7 +560,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { | ||||
|  | ||||
| func (self *ChainManager) update() { | ||||
| 	events := self.eventMux.Subscribe(queueEvent{}) | ||||
|  | ||||
| 	futureTimer := time.NewTicker(5 * time.Second) | ||||
| out: | ||||
| 	for { | ||||
| 		select { | ||||
| @@ -553,6 +586,8 @@ out: | ||||
| 					self.eventMux.Post(event) | ||||
| 				} | ||||
| 			} | ||||
| 		case <-futureTimer.C: | ||||
| 			self.procFutureBlocks() | ||||
| 		case <-self.quit: | ||||
| 			break out | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user