func chkblock(bl *btc.Block) (er error) { // Check timestamp (must not be higher than now +2 hours) if int64(bl.BlockTime()) > time.Now().Unix()+2*60*60 { er = errors.New("CheckBlock() : block timestamp too far in the future") return } if prv, pres := MemBlockChain.BlockIndex[bl.Hash.BIdx()]; pres { if prv.Parent == nil { // This is genesis block er = errors.New("Genesis") return } else { return } } prevblk, ok := MemBlockChain.BlockIndex[btc.NewUint256(bl.ParentHash()).BIdx()] if !ok { er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found") return } // Check proof of work gnwr := MemBlockChain.GetNextWorkRequired(prevblk, bl.BlockTime()) if bl.Bits() != gnwr { if !Testnet || ((prevblk.Height+1)%2016) != 0 { er = errors.New(fmt.Sprint("CheckBlock: Incorrect proof of work at block", prevblk.Height+1)) } } cur := new(btc.BlockTreeNode) cur.BlockHash = bl.Hash cur.Parent = prevblk cur.Height = prevblk.Height + 1 cur.TxCount = uint32(bl.TxCount) copy(cur.BlockHeader[:], bl.Raw[:80]) prevblk.Childs = append(prevblk.Childs, cur) MemBlockChain.BlockIndex[cur.BlockHash.BIdx()] = cur LastBlock.Mutex.Lock() if cur.Height > LastBlock.node.Height { LastBlock.node = cur } LastBlock.Mutex.Unlock() 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()) common.CountSafe("GetHdrsBadPayload") c.DoS() return } if common.DebugLevel > 1 { println("GetHeaders", len(h2get), hashstop.String()) } var best_block, last_block *btc.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 }
func chkblock(bl *btc.Block) (er error) { // Check timestamp (must not be higher than now +2 hours) if int64(bl.BlockTime) > time.Now().Unix()+2*60*60 { er = errors.New("CheckBlock() : block timestamp too far in the future") return } if prv, pres := MemBlockChain.BlockIndex[bl.Hash.BIdx()]; pres { if prv.Parent == nil { // This is genesis block prv.Timestamp = bl.BlockTime prv.Bits = bl.Bits er = errors.New("Genesis") return } else { return } } prevblk, ok := MemBlockChain.BlockIndex[btc.NewUint256(bl.Parent).BIdx()] if !ok { er = errors.New("CheckBlock: " + bl.Hash.String() + " parent not found") return } // Check proof of work gnwr := MemBlockChain.GetNextWorkRequired(prevblk, bl.BlockTime) if bl.Bits != gnwr { er = errors.New("CheckBlock: incorrect proof of work") } cur := new(btc.BlockTreeNode) cur.BlockHash = bl.Hash cur.Parent = prevblk cur.Height = prevblk.Height + 1 cur.Bits = bl.Bits cur.Timestamp = bl.BlockTime prevblk.Childs = append(prevblk.Childs, cur) MemBlockChain.BlockIndex[cur.BlockHash.BIdx()] = cur LastBlock.Mutex.Lock() if cur.Height > LastBlock.node.Height { LastBlock.node = cur } LastBlock.Mutex.Unlock() return }