From f546b486bf444d9601cf97b934b2974a9b4d58f8 Mon Sep 17 00:00:00 2001 From: zelig Date: Wed, 8 Apr 2015 03:34:20 +0100 Subject: [PATCH] introduce peers registry on nodes - TestPeerPromotionByTdOnBlock renamed and skipped for now test should pass iff if TD is updated based on an agreement - senders register in AddBlock, flag records if they are coming from newblock message (and therefore advertise their TD with the block) or block message (TODO: latter are stored on the cache and updated by checkTD call; protocol should also call AddBlock on newblock messages by non-best peers) - remove TD update from optional TD field in addBlock: this is no longer part of the eth protocol spec -> TODO: reflect in wiki - only initialise peer map if at least two --- blockpool/blockpool.go | 70 +++++++++++++++++++++-------------------- blockpool/peers_test.go | 12 +++---- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/blockpool/blockpool.go b/blockpool/blockpool.go index 9871c5036..f9c8a64ab 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 } @@ -396,6 +397,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, @@ -622,10 +624,14 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { self.status.lock.Unlock() entry := self.get(hash) - - // a peer's current head block is appearing the first time + blockIsCurrentHead := false sender.lock.Lock() + // a peer's current head block is appearing the first time if hash == sender.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 sender.currentBlock == nil { plog.Debugf("AddBlock: add head block %s for peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) sender.setChainInfoFromBlock(block) @@ -643,46 +649,29 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { plog.DebugDetailf("AddBlock: head block %s for peer <%s> (head: %s) already known", hex(hash), peerId, hex(sender.currentBlockHash)) // signal to head section process } - // self.wg.Add(1) - // go func() { - // timeout := time.After(1 * time.Second) - // select { - // case sender.currentBlockC <- block: - // case <-timeout: - // } - // self.wg.Done() - // }() - } else { plog.DebugDetailf("AddBlock: block %s received from peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash)) - // 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 - } - /* @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) + 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 - } + self.status.lock.Lock() + self.status.badPeers[peerId]++ + self.status.lock.Unlock() + return + } */ } sender.lock.Unlock() if entry == nil { + // FIXME: here check the cache find or create node - + // put peer as blockBy! return } @@ -690,10 +679,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 @@ -704,6 +705,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)) @@ -718,8 +721,7 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) { */ node.block = block - node.blockBy = peerId - node.td = block.Td // optional field + // node.blockBy = peerId self.status.lock.Lock() self.status.values.Blocks++ diff --git a/blockpool/peers_test.go b/blockpool/peers_test.go index 62e059337..e32bb6fc8 100644 --- a/blockpool/peers_test.go +++ b/blockpool/peers_test.go @@ -144,7 +144,8 @@ func TestAddPeer(t *testing.T) { blockPool.Stop() } -func TestPeerPromotionByOptionalTdOnBlock(t *testing.T) { +func TestPeerPromotionByTdOnBlock(t *testing.T) { + t.Skip() test.LogInit() _, blockPool, blockPoolTester := newTestBlockPool(t) blockPoolTester.blockChain[0] = nil @@ -168,13 +169,8 @@ func TestPeerPromotionByOptionalTdOnBlock(t *testing.T) { best = peer2.AddPeer() peer2.serveBlocks(3, 4) peer2.serveBlockHashes(4, 3, 2, 1) - hashes := blockPoolTester.hashPool.IndexesToHashes([]int{2, 3}) - peer1.waitBlocksRequests(3) - blockPool.AddBlock(&types.Block{ - HeaderHash: common.Hash(hashes[1]), - ParentHeaderHash: common.Hash(hashes[0]), - Td: common.Big3, - }, "peer1") + // hashes := blockPoolTester.hashPool.IndexesToHashes([]int{2, 3}) + peer1.serveBlocks(2, 3) blockPool.RemovePeer("peer2") if blockPool.peers.best.id != "peer1" {