diff options
Diffstat (limited to 'blockpool/blockpool.go')
-rw-r--r-- | blockpool/blockpool.go | 112 |
1 files changed, 68 insertions, 44 deletions
diff --git a/blockpool/blockpool.go b/blockpool/blockpool.go index 3b3de928d..f442259e0 100644 --- a/blockpool/blockpool.go +++ b/blockpool/blockpool.go @@ -132,6 +132,7 @@ type node struct { block *types.Block hashBy string blockBy string + peers map[string]bool td *big.Int } @@ -376,13 +377,14 @@ func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId st var nodes []*node hash, ok = next() - bestpeer.lock.Lock() + bestpeer.lock.RLock() plog.Debugf("AddBlockHashes: peer <%s> starting from [%s] (peer head: %s)", peerId, hex(bestpeer.parentHash), hex(bestpeer.currentBlockHash)) // first check if we are building the head section of a peer's chain if bestpeer.parentHash == hash { if self.hasBlock(bestpeer.currentBlockHash) { + bestpeer.lock.RUnlock() return } /* @@ -396,6 +398,7 @@ func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId st if entry := self.get(bestpeer.currentBlockHash); entry == nil { plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s) head section starting from [%s] ", peerId, hex(bestpeer.currentBlockHash), hex(bestpeer.parentHash)) // if head block is not yet in the pool, create entry and start node list for section + node := &node{ hash: bestpeer.currentBlockHash, block: bestpeer.currentBlock, @@ -421,7 +424,7 @@ func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId st } // the switch channel signals peerswitch event switchC := bestpeer.switchC - bestpeer.lock.Unlock() + bestpeer.lock.RUnlock() // iterate over hashes coming from peer (first round we have hash set above) LOOP: @@ -547,8 +550,10 @@ LOOP: In this case no activation should happen */ if parent != nil && !peerswitch { - self.activateChain(parent, bestpeer, nil) + bestpeer.lock.RLock() + self.activateChain(parent, bestpeer, bestpeer.switchC, nil) plog.DebugDetailf("AddBlockHashes: peer <%s> (head: %s): parent section [%s]", peerId, hex(bestpeer.currentBlockHash), sectionhex(parent)) + bestpeer.lock.RUnlock() } /* @@ -622,53 +627,60 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { self.status.lock.Unlock() entry := self.get(hash) + blockIsCurrentHead := false + sender.lock.RLock() + currentBlockHash := sender.currentBlockHash + currentBlock := sender.currentBlock + currentBlockC := sender.currentBlockC + switchC := sender.switchC + sender.lock.RUnlock() // a peer's current head block is appearing the first time - if hash == sender.currentBlockHash { - if sender.currentBlock == nil { - plog.Debugf("AddBlock: add head block %s for peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) + if hash == currentBlockHash { + // this happens when block came in a newblock message but + // also if sent in a blockmsg (for instance, if we requested, only if we + // dont apply on blockrequests the restriction of flood control) + blockIsCurrentHead = true + if currentBlock == nil { + sender.lock.Lock() sender.setChainInfoFromBlock(block) + sender.lock.Unlock() self.status.lock.Lock() self.status.values.BlockHashes++ self.status.values.Blocks++ self.status.values.BlocksInPool++ self.status.lock.Unlock() - } else { - plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(sender.currentBlockHash)) // signal to head section process - sender.currentBlockC <- block + select { + case currentBlockC <- block: + case <-switchC: + } + } else { + plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(currentBlockHash)) } } else { - plog.DebugDetailf("AddBlock: block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) - - sender.lock.Lock() - // update peer chain info if more recent than what we registered - if block.Td != nil && block.Td.Cmp(sender.td) > 0 { - sender.td = block.Td - sender.currentBlockHash = block.Hash() - sender.parentHash = block.ParentHash() - sender.currentBlock = block - sender.headSection = nil - } - sender.lock.Unlock() + plog.DebugDetailf("AddBlock: block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(currentBlockHash)) /* @zelig !!! - requested 5 hashes from both A & B. A responds sooner then B, process blocks. Close section. - delayed B sends you block ... UNREQUESTED. Blocked - if entry == nil { - plog.DebugDetailf("AddBlock: unrequested block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) - sender.addError(ErrUnrequestedBlock, "%x", hash) - - self.status.lock.Lock() - self.status.badPeers[peerId]++ - self.status.lock.Unlock() - return - } + requested 5 hashes from both A & B. A responds sooner then B, process blocks. Close section. + delayed B sends you block ... UNREQUESTED. Blocked + if entry == nil { + plog.DebugDetailf("AddBlock: unrequested block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) + sender.addError(ErrUnrequestedBlock, "%x", hash) + + self.status.lock.Lock() + self.status.badPeers[peerId]++ + self.status.lock.Unlock() + return + } */ } + if entry == nil { + // FIXME: here check the cache find or create node - + // put peer as blockBy! return } @@ -676,10 +688,22 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { node.lock.Lock() defer node.lock.Unlock() + // register peer on node as source + if node.peers == nil { + node.peers = make(map[string]bool) + } + FoundBlockCurrentHead, found := node.peers[sender.id] + if !found || FoundBlockCurrentHead { + // if found but not FoundBlockCurrentHead, then no update + // necessary (||) + node.peers[sender.id] = blockIsCurrentHead + // for those that are false, TD will update their head + // for those that are true, TD is checked ! + // this is checked at the time of TD calculation in checkTD + } // check if block already received if node.block != nil { plog.DebugDetailf("AddBlock: block %s from peer <%s> (head: %s) already sent by <%s> ", hex(hash), peerId, hex(sender.currentBlockHash), node.blockBy) - return } // check if block is already inserted in the blockchain @@ -690,6 +714,8 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { /* @zelig needs discussing + Viktor: pow check can be delayed in a go routine and therefore cache + creation is not blocking // validate block for PoW if !self.verifyPoW(block) { plog.Warnf("AddBlock: invalid PoW on block %s from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) @@ -705,7 +731,6 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { node.block = block node.blockBy = peerId - node.td = block.Td // optional field self.status.lock.Lock() self.status.values.Blocks++ @@ -719,11 +744,7 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { It activates the section process on incomplete sections with peer. It relinks orphaned sections with their parent if root block (and its parent hash) is known. */ -func (self *BlockPool) activateChain(sec *section, p *peer, connected map[common.Hash]*section) { - - p.lock.RLock() - switchC := p.switchC - p.lock.RUnlock() +func (self *BlockPool) activateChain(sec *section, p *peer, switchC chan bool, connected map[common.Hash]*section) { var i int @@ -766,14 +787,17 @@ LOOP: // check if block's actual TD (calculated after successful insertChain) is identical to TD advertised for peer's head block. func (self *BlockPool) checkTD(nodes ...*node) { for _, n := range nodes { - if n.td != nil { + // skip check if queued future block + if n.td != nil && !n.block.Queued() { plog.DebugDetailf("peer td %v =?= block td %v", n.td, n.block.Td) + /* @zelig: Commented out temp untill the rest of the network has been fixed. if n.td.Cmp(n.block.Td) != 0 { - //self.peers.peerError(n.blockBy, ErrIncorrectTD, "on block %x", n.hash) - //self.status.lock.Lock() - //self.status.badPeers[n.blockBy]++ - //self.status.lock.Unlock() + self.peers.peerError(n.blockBy, ErrIncorrectTD, "on block %x", n.hash) + self.status.lock.Lock() + self.status.badPeers[n.blockBy]++ + self.status.lock.Unlock() } + */ } } } |