// Handle getheaders protocol command // https://en.bitcoin.it/wiki/Protocol_specification#getheaders func (c *OneConnection) GetHeaders(pl []byte) { h2get, hashstop, e := parseLocatorsPayload(pl) if e != nil || hashstop == nil { println("GetHeaders: error parsing payload from", c.PeerAddr.Ip()) c.DoS("BadGetHdrs") return } if common.DebugLevel > 1 { println("GetHeaders", len(h2get), hashstop.String()) } var best_block, last_block *chain.BlockTreeNode common.BlockChain.BlockIndexAccess.Lock() if len(h2get) > 0 { for i := range h2get { if bl, ok := common.BlockChain.BlockIndex[h2get[i].BIdx()]; ok { if best_block == nil || bl.Height > best_block.Height { best_block = bl } } } } else { best_block = common.BlockChain.BlockIndex[hashstop.BIdx()] } last_block = common.BlockChain.BlockTreeEnd common.BlockChain.BlockIndexAccess.Unlock() var resp []byte var cnt uint32 for cnt < 2000 { best_block = best_block.FindPathTo(last_block) if best_block == nil { break } resp = append(resp, append(best_block.BlockHeader[:], 0)...) // 81st byte is always zero cnt++ } out := new(bytes.Buffer) btc.WriteVlen(out, cnt) out.Write(resp) c.SendRawMsg("headers", out.Bytes()) return }
// Handle getheaders protocol command // https://en.bitcoin.it/wiki/Protocol_specification#getheaders func (c *OneConnection) GetHeaders(pl []byte) { h2get, hashstop, e := parseLocatorsPayload(pl) if e != nil || hashstop == nil { println("GetHeaders: error parsing payload from", c.PeerAddr.Ip()) c.DoS("BadGetHdrs") return } if common.DebugLevel > 1 { println("GetHeaders", len(h2get), hashstop.String()) } var best_block, last_block *chain.BlockTreeNode //common.Last.Mutex.Lock() MutexRcv.Lock() last_block = LastCommitedHeader MutexRcv.Unlock() //common.Last.Mutex.Unlock() common.BlockChain.BlockIndexAccess.Lock() //println("GetHeaders", len(h2get), hashstop.String()) if len(h2get) > 0 { for i := range h2get { if bl, ok := common.BlockChain.BlockIndex[h2get[i].BIdx()]; ok { if best_block == nil || bl.Height > best_block.Height { //println(" ... bbl", i, bl.Height, bl.BlockHash.String()) best_block = bl } } } } else { best_block = common.BlockChain.BlockIndex[hashstop.BIdx()] } if best_block == nil { common.CountSafe("GetHeadersBadBlock") best_block = common.BlockChain.BlockTreeRoot } //best_bl_ch := len(best_block.Childs) //last_block = common.BlockChain.BlockTreeEnd var resp []byte var cnt uint32 defer func() { // If we get a hash of an old orphaned blocks, FindPathTo() will panic, so... if r := recover(); r != nil { common.CountSafe("GetHeadersOrphBlk") /* err, ok := r.(error) if !ok { err = fmt.Errorf("pkg: %v", r) } // This happens the you receive request for headers from an orphaned block fmt.Println("GetHeaders panic recovered:", err.Error()) fmt.Println("Cnt:", cnt, " len(h2get):", len(h2get)) if best_block!=nil { fmt.Println("BestBlock:", best_block.Height, best_block.BlockHash.String(), len(best_block.Childs), best_bl_ch) } if last_block!=nil { fmt.Println("LastBlock:", last_block.Height, last_block.BlockHash.String(), len(last_block.Childs)) } */ } common.BlockChain.BlockIndexAccess.Unlock() // send the response out := new(bytes.Buffer) btc.WriteVlen(out, uint64(cnt)) out.Write(resp) c.SendRawMsg("headers", out.Bytes()) }() for cnt < 2000 { if last_block.Height <= best_block.Height { break } best_block = best_block.FindPathTo(last_block) if best_block == nil { //println("FindPathTo failed", last_block.BlockHash.String(), cnt) //println("resp:", hex.EncodeToString(resp)) break } resp = append(resp, append(best_block.BlockHeader[:], 0)...) // 81st byte is always zero cnt++ } // Note: the deferred function will be called before exiting return }