diff options
author | obscuren <geffobscura@gmail.com> | 2014-09-24 17:41:57 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-09-24 17:41:57 +0800 |
commit | ba43364f36db690528cc62196969414ef5e98833 (patch) | |
tree | be633c76ab7876e40337606625f524e82b11567a /block_pool.go | |
parent | 57dc435f9b928f5de2a49736a2c71a7bf611289a (diff) | |
download | dexon-ba43364f36db690528cc62196969414ef5e98833.tar.gz dexon-ba43364f36db690528cc62196969414ef5e98833.tar.zst dexon-ba43364f36db690528cc62196969414ef5e98833.zip |
tmp
Diffstat (limited to 'block_pool.go')
-rw-r--r-- | block_pool.go | 101 |
1 files changed, 95 insertions, 6 deletions
diff --git a/block_pool.go b/block_pool.go index 6753308b6..f3a863429 100644 --- a/block_pool.go +++ b/block_pool.go @@ -1,17 +1,23 @@ package eth import ( + "bytes" + "container/list" + "fmt" "math" "math/big" "sync" + "time" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" ) type block struct { - peer *Peer - block *ethchain.Block + peer *Peer + block *ethchain.Block + reqAt time.Time + requested int } type BlockPool struct { @@ -22,7 +28,8 @@ type BlockPool struct { hashPool [][]byte pool map[string]*block - td *big.Int + td *big.Int + quit chan bool } func NewBlockPool(eth *Ethereum) *BlockPool { @@ -30,6 +37,7 @@ func NewBlockPool(eth *Ethereum) *BlockPool { eth: eth, pool: make(map[string]*block), td: ethutil.Big0, + quit: make(chan bool), } } @@ -47,7 +55,7 @@ func (self *BlockPool) HasCommonHash(hash []byte) bool { func (self *BlockPool) AddHash(hash []byte) { if self.pool[string(hash)] == nil { - self.pool[string(hash)] = &block{nil, nil} + self.pool[string(hash)] = &block{nil, nil, time.Now(), 0} self.hashPool = append([][]byte{hash}, self.hashPool...) } @@ -58,12 +66,34 @@ func (self *BlockPool) SetBlock(b *ethchain.Block, peer *Peer) { if self.pool[hash] == nil && !self.eth.BlockChain().HasBlock(b.Hash()) { self.hashPool = append(self.hashPool, b.Hash()) - self.pool[hash] = &block{peer, b} + self.pool[hash] = &block{peer, b, time.Now(), 0} } else if self.pool[hash] != nil { self.pool[hash].block = b } } +func (self *BlockPool) getParent(block *ethchain.Block) *ethchain.Block { + for _, item := range self.pool { + if item.block != nil { + if bytes.Compare(item.block.Hash(), block.PrevHash) == 0 { + return item.block + } + } + } + + return nil +} + +func (self *BlockPool) GetChainFromBlock(block *ethchain.Block) ethchain.Blocks { + var blocks ethchain.Blocks + + for b := block; b != nil; b = self.getParent(b) { + blocks = append(ethchain.Blocks{b}, blocks...) + } + + return blocks +} + func (self *BlockPool) CheckLinkAndProcess(f func(block *ethchain.Block)) { var blocks ethchain.Blocks @@ -94,8 +124,14 @@ func (self *BlockPool) Take(amount int, peer *Peer) (hashes [][]byte) { j := 0 for i := 0; i < len(self.hashPool) && j < num; i++ { hash := string(self.hashPool[i]) - if self.pool[hash] != nil && (self.pool[hash].peer == nil || self.pool[hash].peer == peer) && self.pool[hash].block == nil { + item := self.pool[hash] + if item != nil && item.block == nil && + (item.peer == nil || + ((time.Since(item.reqAt) > 5*time.Second && item.peer != peer) && self.eth.peers.Len() > 1) || // multiple peers + (time.Since(item.reqAt) > 5*time.Second && self.eth.peers.Len() == 1) /* single peer*/) { self.pool[hash].peer = peer + self.pool[hash].reqAt = time.Now() + self.pool[hash].requested++ hashes = append(hashes, self.hashPool[i]) j++ @@ -104,3 +140,56 @@ func (self *BlockPool) Take(amount int, peer *Peer) (hashes [][]byte) { return } + +func (self *BlockPool) Start() { + go self.update() +} + +func (self *BlockPool) Stop() { + close(self.quit) +} + +func (self *BlockPool) update() { + serviceTimer := time.NewTicker(100 * time.Millisecond) + procTimer := time.NewTicker(500 * time.Millisecond) +out: + for { + select { + case <-self.quit: + break out + case <-serviceTimer.C: + // Clean up hashes that can't be fetched + done := true + eachPeer(self.eth.peers, func(p *Peer, v *list.Element) { + if p.statusKnown && p.FetchingHashes() { + done = false + } + }) + + if done { + eachPeer(self.eth.peers, func(p *Peer, v *list.Element) { + if p.statusKnown { + hashes := self.Take(100, p) + if len(hashes) > 0 { + p.FetchBlocks(hashes) + if len(hashes) == 1 { + fmt.Printf("last hash = %x\n", hashes[0]) + } else { + fmt.Println("Requesting", len(hashes), "of", p) + } + } + } + }) + } + case <-procTimer.C: + var err error + self.CheckLinkAndProcess(func(block *ethchain.Block) { + err = self.eth.StateManager().Process(block, false) + }) + + if err != nil { + peerlogger.Infoln(err) + } + } + } +} |