예제 #1
0
func (ch *Chain) ParseTillBlock(end *BlockTreeNode) {
	var b []byte
	var er error
	var trusted bool

	prv := time.Now().UnixNano()
	for !AbortNow && ch.BlockTreeEnd != end {
		cur := time.Now().UnixNano()
		if cur-prv >= 10e9 {
			fmt.Println("ParseTillBlock ...", ch.BlockTreeEnd.Height, "/", end.Height)
			prv = cur
		}

		nxt := ch.BlockTreeEnd.FindPathTo(end)
		if nxt == nil {
			break
		}

		b, trusted, er = ch.Blocks.BlockGet(nxt.BlockHash)
		if er != nil {
			panic("Db.BlockGet(): " + er.Error())
		}

		bl, er := btc.NewBlock(b)
		if er != nil {
			ch.DeleteBranch(nxt)
			break
		}

		er = bl.BuildTxList()
		if er != nil {
			ch.DeleteBranch(nxt)
			break
		}

		bl.Trusted = trusted

		changes, er := ch.ProcessBlockTransactions(bl, nxt.Height, end.Height)
		if er != nil {
			println("ProcessBlockTransactions", nxt.Height, er.Error())
			ch.DeleteBranch(nxt)
			break
		}
		if !trusted {
			ch.Blocks.BlockTrusted(bl.Hash.Hash[:])
		}

		ch.Unspent.CommitBlockTxs(changes, bl.Hash.Hash[:])

		ch.BlockTreeEnd = nxt
	}

	if !AbortNow && ch.BlockTreeEnd != end {
		end, _ = ch.BlockTreeRoot.FindFarthestNode()
		fmt.Println("ParseTillBlock failed - now go to", end.Height)
		ch.MoveToBlock(end)
	}
	ch.Unspent.Sync()
	ch.Save()
}
예제 #2
0
파일: data.go 프로젝트: niniwzw/gocoin
// This function is called from a net conn thread
func netBlockReceived(conn *OneConnection, b []byte) {
	bl, e := btc.NewBlock(b)
	if e != nil {
		conn.DoS("BrokenBlock")
		println("NewBlock:", e.Error())
		return
	}

	idx := bl.Hash.BIdx()
	MutexRcv.Lock()
	if rb, got := ReceivedBlocks[idx]; got {
		rb.Cnt++
		MutexRcv.Unlock()
		common.CountSafe("BlockSameRcvd")
		return
	}
	orb := &OneReceivedBlock{Time: time.Now()}
	if bip, ok := conn.GetBlockInProgress[idx]; ok {
		orb.TmDownload = orb.Time.Sub(bip.start)
		conn.Mutex.Lock()
		delete(conn.GetBlockInProgress, idx)
		conn.Mutex.Unlock()
	} else {
		common.CountSafe("UnxpectedBlockRcvd")
	}
	ReceivedBlocks[idx] = orb
	MutexRcv.Unlock()

	NetBlocks <- &BlockRcvd{Conn: conn, Block: bl}
}
예제 #3
0
파일: hdrs.go 프로젝트: niniwzw/gocoin
func (c *one_net_conn) headers(d []byte) {
	var hdr [81]byte
	b := bytes.NewReader(d)
	cnt, er := btc.ReadVLen(b)
	if er != nil {
		return
	}
	if cnt == 0 /*|| LastBlock.node.Height>=150e3*/ {
		SetAllHeadersDone(true)
		return
	}
	for i := uint64(0); i < cnt; i++ {
		if _, er = b.Read(hdr[:]); er != nil {
			return
		}
		if hdr[80] != 0 {
			fmt.Println(LastBlock.node.Height, "Unexpected value of txn_count")
			continue
		}
		bl, er := btc.NewBlock(hdr[:])
		if er == nil {
			er = chkblock(bl)
			if er != nil {
				fmt.Println(er.Error())
				os.Exit(1)
			}
		} else {
			fmt.Println(LastBlock.node.Height, er.Error())
		}
	}
	//fmt.Println("Height:", LastBlock.node.Height)
}
예제 #4
0
func (ch *Chain) UndoLastBlock() {
	fmt.Println("Undo block", ch.BlockTreeEnd.Height, ch.BlockTreeEnd.BlockHash.String(),
		ch.BlockTreeEnd.BlockSize>>10, "KB")

	raw, _, _ := ch.Blocks.BlockGet(ch.BlockTreeEnd.BlockHash)

	bl, _ := btc.NewBlock(raw)
	bl.BuildTxList()

	ch.Unspent.UndoBlockTxs(bl, ch.BlockTreeEnd.Parent.BlockHash.Hash[:])
	ch.BlockTreeEnd = ch.BlockTreeEnd.Parent
}
예제 #5
0
파일: mining.go 프로젝트: niniwzw/gocoin
func BlocksMiner(bl []byte) (string, int) {
	for i, m := range MinerIds {
		if MinedBy(bl, m.Tag) {
			return m.Name, i
		}
	}
	bt, _ := btc.NewBlock(bl)
	cbtx, _ := btc.NewTx(bl[bt.TxOffset:])
	adr := btc.NewAddrFromPkScript(cbtx.TxOut[0].Pk_script, Testnet)
	if adr != nil {
		return adr.String(), -1
	}
	return "", -1
}
예제 #6
0
파일: main.go 프로젝트: niniwzw/gocoin
func defrag_db() {
	if (usif.DefragBlocksDB & 1) != 0 {
		qdb.SetDefragPercent(1)
		fmt.Print("Defragmenting UTXO database")
		for {
			if !common.BlockChain.Unspent.Idle() {
				break
			}
			fmt.Print(".")
		}
		fmt.Println("done")
	}

	if (usif.DefragBlocksDB & 2) != 0 {
		fmt.Println("Creating empty database in", common.GocoinHomeDir+"defrag", "...")
		os.RemoveAll(common.GocoinHomeDir + "defrag")
		defragdb := chain.NewBlockDB(common.GocoinHomeDir + "defrag")
		fmt.Println("Defragmenting the database...")
		blk := common.BlockChain.BlockTreeRoot
		for {
			blk = blk.FindPathTo(common.BlockChain.BlockTreeEnd)
			if blk == nil {
				fmt.Println("Database defragmenting finished successfully")
				fmt.Println("To use the new DB, move the two new files to a parent directory and restart the client")
				break
			}
			if (blk.Height & 0xff) == 0 {
				fmt.Printf("%d / %d blocks written (%d%%)\r", blk.Height, common.BlockChain.BlockTreeEnd.Height,
					100*blk.Height/common.BlockChain.BlockTreeEnd.Height)
			}
			bl, trusted, er := common.BlockChain.Blocks.BlockGet(blk.BlockHash)
			if er != nil {
				fmt.Println("FATAL ERROR during BlockGet:", er.Error())
				break
			}
			nbl, er := btc.NewBlock(bl)
			if er != nil {
				fmt.Println("FATAL ERROR during NewBlock:", er.Error())
				break
			}
			nbl.Trusted = trusted
			defragdb.BlockAdd(blk.Height, nbl)
		}
		defragdb.Sync()
		defragdb.Close()
	}
}
예제 #7
0
파일: balance.go 프로젝트: niniwzw/gocoin
func GetRawTransaction(BlockHeight uint32, txid *btc.Uint256, txf io.Writer) bool {
	// Find the block with the indicated Height in the main tree
	common.BlockChain.BlockIndexAccess.Lock()
	n := common.Last.Block
	if n.Height < BlockHeight {
		println(n.Height, BlockHeight)
		common.BlockChain.BlockIndexAccess.Unlock()
		panic("This should not happen")
	}
	for n.Height > BlockHeight {
		n = n.Parent
	}
	common.BlockChain.BlockIndexAccess.Unlock()

	bd, _, e := common.BlockChain.Blocks.BlockGet(n.BlockHash)
	if e != nil {
		println("BlockGet", n.BlockHash.String(), BlockHeight, e.Error())
		println("This should not happen - please, report a bug.")
		println("You can probably fix it by launching the client with -rescan")
		os.Exit(1)
	}

	bl, e := btc.NewBlock(bd)
	if e != nil {
		println("NewBlock: ", e.Error())
		os.Exit(1)
	}

	e = bl.BuildTxList()
	if e != nil {
		println("BuildTxList:", e.Error())
		os.Exit(1)
	}

	// Find the transaction we need and store it in the file
	for i := range bl.Txs {
		if bl.Txs[i].Hash.Equal(txid) {
			txf.Write(bl.Txs[i].Serialize())
			return true
		}
	}
	return false
}
예제 #8
0
파일: blocks.go 프로젝트: niniwzw/gocoin
func p_blocks(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	blks := load_template("blocks.html")
	onerow := load_template("blocks_row.html")

	common.Last.Mutex.Lock()
	end := common.Last.Block
	common.Last.Mutex.Unlock()

	for cnt := uint32(0); end != nil && cnt < atomic.LoadUint32(&common.CFG.WebUI.ShowBlocks); cnt++ {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			return
		}
		cbasetx, _ := btc.NewTx(bl[block.TxOffset:])
		s := onerow

		s = strings.Replace(s, "{BLOCK_NUMBER}", fmt.Sprint(end.Height), 1)
		s = strings.Replace(s, "{BLOCK_TIMESTAMP}",
			time.Unix(int64(block.BlockTime()), 0).Format("Mon 15:04:05"), 1)
		s = strings.Replace(s, "{BLOCK_HASH}", end.BlockHash.String(), 1)
		s = strings.Replace(s, "{BLOCK_TXS}", fmt.Sprint(block.TxCount), 1)
		s = strings.Replace(s, "{BLOCK_SIZE}", fmt.Sprintf("%.1f", float64(len(bl))/1000), 1)
		var rew uint64
		for o := range cbasetx.TxOut {
			rew += cbasetx.TxOut[o].Value
		}
		s = strings.Replace(s, "{BLOCK_REWARD}", fmt.Sprintf("%.2f", float64(rew)/1e8), 1)
		mi, _ := common.BlocksMiner(bl)
		if len(mi) > 10 {
			mi = mi[:10]
		}
		s = strings.Replace(s, "{BLOCK_MINER}", mi, 1)

		network.MutexRcv.Lock()
		rb := network.ReceivedBlocks[end.BlockHash.BIdx()]
		network.MutexRcv.Unlock()

		if rb.TmDownload != 0 {
			s = strings.Replace(s, "{TIME_TO_DOWNLOAD}", fmt.Sprint(int(rb.TmDownload/time.Millisecond)), 1)
		} else {
			s = strings.Replace(s, "{TIME_TO_DOWNLOAD}", "", 1)
		}
		if rb.TmAccept != 0 {
			s = strings.Replace(s, "{TIME_TO_ACCEPT}", fmt.Sprint(int(rb.TmAccept/time.Millisecond)), 1)
		} else {
			s = strings.Replace(s, "{TIME_TO_ACCEPT}", "", 1)
		}
		if rb.Cnt != 0 {
			s = strings.Replace(s, "{WASTED_BLOCKS}", fmt.Sprint(rb.Cnt), 1)
		} else {
			s = strings.Replace(s, "{WASTED_BLOCKS}", "", 1)
		}

		blks = templ_add(blks, "<!--BLOCK_ROW-->", s)

		end = end.Parent
	}

	write_html_head(w, r)
	w.Write([]byte(blks))
	write_html_tail(w)
}
예제 #9
0
파일: init.go 프로젝트: niniwzw/gocoin
func import_blockchain(dir string) {
	trust := !textui.AskYesNo("Do you want to verify scripts while importing (will be slow)?")

	BlockDatabase := blockdb.NewBlockDB(dir, common.Magic)
	chain := chain.NewChain(common.GocoinHomeDir, common.GenesisBlock, false)

	var bl *btc.Block
	var er error
	var dat []byte
	var totbytes, perbytes uint64

	chain.DoNotSync = true

	fmt.Println("Be patient while importing Satoshi's database... ")
	start := time.Now().UnixNano()
	prv := start
	for {
		now := time.Now().UnixNano()
		if now-prv >= 10e9 {
			stat(now-start, now-prv, totbytes, perbytes, chain.BlockTreeEnd.Height)
			prv = now // show progress each 10 seconds
			perbytes = 0
		}

		dat, er = BlockDatabase.FetchNextBlock()
		if dat == nil || er != nil {
			println("END of DB file")
			break
		}

		bl, er = btc.NewBlock(dat[:])
		if er != nil {
			println("Block inconsistent:", er.Error())
			break
		}

		bl.Trusted = trust

		er, _, _ = chain.CheckBlock(bl)

		if er != nil {
			if er.Error() != "Genesis" {
				println("CheckBlock failed:", er.Error())
				//os.Exit(1) // Such a thing should not happen, so let's better abort here.
			}
			continue
		}

		er = chain.AcceptBlock(bl)
		if er != nil {
			println("AcceptBlock failed:", er.Error())
			//os.Exit(1) // Such a thing should not happen, so let's better abort here.
		}

		totbytes += uint64(len(bl.Raw))
		perbytes += uint64(len(bl.Raw))
	}

	stop := time.Now().UnixNano()
	stat(stop-start, stop-prv, totbytes, perbytes, chain.BlockTreeEnd.Height)

	fmt.Println("Satoshi's database import finished in", (stop-start)/1e9, "seconds")

	fmt.Println("Now saving the new database...")
	chain.Sync()
	chain.Save()
	chain.Close()
	fmt.Println("Database saved. No more imports should be needed.")
	fmt.Println("It is advised to close and restart the node now, to free some mem.")
}
예제 #10
0
파일: blks.go 프로젝트: niniwzw/gocoin
func (c *one_net_conn) block(d []byte) {
	atomic.AddUint64(&DlBytesDownloaded, uint64(len(d)))

	BlocksMutex.Lock()
	defer BlocksMutex.Unlock()
	h := btc.NewSha2Hash(d[:80])

	c.Lock()
	c.last_blk_rcvd = time.Now()
	c.Unlock()

	bip := BlocksInProgress[h.Hash]
	if bip == nil || !bip.Conns[c.id] {
		COUNTER("BNOT")
		//fmt.Println(h.String(), "- already received", bip)
		return
	}
	//fmt.Println(h.String(), "- new", bip.Height)
	COUNTER("BYES")

	delete(bip.Conns, c.id)
	c.Lock()
	c.inprogress--
	c.Unlock()
	blocksize_update(len(d))

	bl, er := btc.NewBlock(d)
	if er != nil {
		fmt.Println(c.Ip(), "-", er.Error())
		c.setbroken(true)
		return
	}

	bl.BuildTxList()
	if !bytes.Equal(btc.GetMerkel(bl.Txs), bl.MerkleRoot()) {
		fmt.Println(c.Ip(), " - MerkleRoot mismatch at block", bip.Height)
		c.setbroken(true)
		return
	}

	delete(BlocksToGet, bip.Height)
	delete(BlocksInProgress, h.Hash)
	if len(BlocksInProgress) == 0 {
		EmptyInProgressCnt++
	}

	//println("got-", bip.Height, BlocksComplete+1)
	if BlocksComplete+1 == bip.Height {
		BlocksComplete++
		BlockQueue <- bl
		for {
			bl = BlocksCached[BlocksComplete+1]
			if bl == nil {
				break
			}
			BlocksComplete++
			delete(BlocksCached, BlocksComplete)
			BlocksCachedSize -= uint64(len(bl.Raw))
			BlockQueue <- bl
		}
	} else {
		BlocksCached[bip.Height] = bl
		BlocksCachedSize += uint64(len(d))
	}
}
예제 #11
0
파일: miners.go 프로젝트: niniwzw/gocoin
func do_mining(s string) {
	var totbtc, hrs uint64
	if s != "" {
		hrs, _ = strconv.ParseUint(s, 10, 64)
	}
	if hrs == 0 {
		hrs = uint64(common.CFG.MiningStatHours)
	}
	fmt.Println("Looking back", hrs, "hours...")
	lim := uint32(time.Now().Add(-time.Hour * time.Duration(hrs)).Unix())
	common.Last.Mutex.Lock()
	bte := common.Last.Block
	end := bte
	common.Last.Mutex.Unlock()
	cnt, diff := 0, float64(0)
	tot_blocks, tot_blocks_len := 0, 0
	for end.Timestamp() >= lim {
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			println(cnt, e.Error())
			return
		}
		block, e := btc.NewBlock(bl)
		if e != nil {
			println("btc.NewBlock failed", e.Error())
			return
		}
		tot_blocks++
		tot_blocks_len += len(bl)
		diff += btc.GetDifficulty(block.Bits())
		if common.MinedByUs(bl) {
			block.BuildTxList()
			totbtc += block.Txs[0].TxOut[0].Value
			cnt++
			fmt.Printf("%4d) %6d %s %s  %5.2f => %5.2f BTC total, %d txs, %.1f KB\n",
				cnt, end.Height, end.BlockHash.String(),
				time.Unix(int64(end.Timestamp()), 0).Format("2006-01-02 15:04:05"),
				float64(block.Txs[0].TxOut[0].Value)/1e8, float64(totbtc)/1e8,
				len(block.Txs), float64(len(bl))/1e3)
		}
		end = end.Parent
	}
	if tot_blocks == 0 {
		fmt.Println("There are no blocks from the last", hrs, "hour(s)")
		return
	}
	diff /= float64(tot_blocks)
	common.LockCfg()
	if common.CFG.Beeps.MinerID != "" {
		fmt.Printf("%.8f BTC mined by %s, in %d blocks for the last %d hours\n",
			float64(totbtc)/1e8, common.CFG.Beeps.MinerID, cnt, hrs)
	}
	common.UnlockCfg()
	if cnt > 0 {
		fmt.Printf("Projected weekly income : %.0f BTC,  estimated hashrate : %s\n",
			7*24*float64(totbtc)/float64(hrs)/1e8,
			common.HashrateToString(float64(cnt)/float64(6*hrs)*diff*7158278.826667))
	}
	bph := float64(tot_blocks) / float64(hrs)
	fmt.Printf("Total network hashrate : %s @ average diff %.0f  (%.2f bph)\n",
		common.HashrateToString(bph/6*diff*7158278.826667), diff, bph)
	fmt.Printf("Average block size was %.1f KB,  next difficulty change in %d blocks\n",
		float64(tot_blocks_len/tot_blocks)/1e3, 2016-bte.Height%2016)
}