Exemple #1
0
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
	}

	MemBlockChainMutex.Lock()
	if prv, pres := MemBlockChain.BlockIndex[bl.Hash.BIdx()]; pres {
		MemBlockChainMutex.Unlock()
		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 {
			MemBlockChainMutex.Unlock()
			er = errors.New(fmt.Sprint("CheckBlock: Incorrect proof of work at block", prevblk.Height+1))
			return
		}
	}

	cur := new(chain.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
	MemBlockChainMutex.Unlock()

	LastBlock.Mutex.Lock()
	if cur.Height > LastBlock.node.Height {
		LastBlock.node = cur
	}
	LastBlock.Mutex.Unlock()

	return
}
Exemple #2
0
func walk(ch *chain.Chain, hash, hdr []byte, height, blen, txs uint32) {
	bh := btc.NewUint256(hash)
	if _, ok := bidx[bh.Hash]; ok {
		println("walk: ", bh.String(), "already in")
		return
	}
	v := new(chain.BlockTreeNode)
	v.BlockHash = bh
	v.Height = height
	v.BlockSize = blen
	v.TxCount = txs
	copy(v.BlockHeader[:], hdr)
	bidx[bh.Hash] = v
	cnt++
}
Exemple #3
0
// 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
}
Exemple #4
0
// 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
}