Esempio n. 1
0
// 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()
		println("NewBlock:", e.Error())
		return
	}

	idx := bl.Hash.BIdx()
	MutexRcv.Lock()
	if rb, got := ReceivedBlocks[idx]; got {
		rb.Cnt++
		MutexRcv.Unlock()
		common.CountSafe("SameBlockReceived")
		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}
}
Esempio n. 2
0
func netBlockReceived(conn *oneConnection, b []byte) {
	bl, e := btc.NewBlock(b)
	if e != nil {
		conn.DoS()
		println("NewBlock:", e.Error())
		return
	}

	mutex.Lock()
	idx := bl.Hash.BIdx()
	if _, got := receivedBlocks[idx]; got {
		if _, ok := pendingBlocks[idx]; ok {
			panic("wtf?")
		} else {
			BlockDups++
		}
		mutex.Unlock()
		return
	}
	receivedBlocks[idx] = time.Now().UnixNano()
	delete(pendingBlocks, idx)
	mutex.Unlock()

	netBlocks <- &blockRcvd{conn: conn, bl: bl}
}
Esempio n. 3
0
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>=10e3*/ {
		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)
}
Esempio n. 4
0
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 {
		AllHeadersDone = true
		println("AllHeadersDone - terminate conn")
		c.broken = true
		return
	}
	for i := uint64(0); i < cnt; i++ {
		if _, er = b.Read(hdr[:]); er != nil {
			return
		}
		bl, er := btc.NewBlock(hdr[:])
		if er == nil {
			er = chkblock(bl)
			if er != nil {
				println(er.Error())
				os.Exit(1)
			}
		}
	}
	println("Height:", LastBlock.Node.Height)
}
Esempio n. 5
0
func defrag_db() {
	println("Creating empty database in", common.GocoinHomeDir+"defrag", "...")
	os.RemoveAll(common.GocoinHomeDir + "defrag")
	defragdb := btc.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 {
			println("FATAL ERROR during BlockGet:", er.Error())
			break
		}
		nbl, er := btc.NewBlock(bl)
		if er != nil {
			println("FATAL ERROR during NewBlock:", er.Error())
			break
		}
		nbl.Trusted = trusted
		defragdb.BlockAdd(blk.Height, nbl)
	}
	defragdb.Sync()
	defragdb.Close()
}
Esempio n. 6
0
func (c *one_net_conn) block(d []byte) {
	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("UNEX")
		//fmt.Println(h.String(), "- already received", bip)
		return
	}

	delete(bip.Conns, c.id)
	c.Lock()
	c.inprogress--
	c.Unlock()
	atomic.AddUint64(&DlBytesDownloaded, uint64(len(d)))
	blocksize_update(len(d))

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

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

	BlocksCachedSize += uint(len(d))
	BlocksCached[bip.Height] = bl
	delete(BlocksToGet, bip.Height)
	delete(BlocksInProgress, h.Hash)

	//fmt.Println("  got block", height)
}
Esempio n. 7
0
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
}
Esempio n. 8
0
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 := btc.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.")
}
Esempio n. 9
0
func show_balance(p string) {
	if MyWallet == nil {
		println("You have no wallet")
		return
	}
	if len(MyWallet.addrs) == 0 {
		println("You have no addresses")
		return
	}
	os.RemoveAll("balance")
	os.MkdirAll("balance/", 0770)

	utxt, _ := os.Create("balance/unspent.txt")

	unsp := BlockChain.GetAllUnspent(MyWallet.addrs, true)
	var sum uint64
	for i := range unsp {
		sum += unsp[i].Value

		if len(unsp) < 100 {
			fmt.Printf("%7d %s @ %s (%s)\n", 1+BlockChain.BlockTreeEnd.Height-unsp[i].MinedAt,
				unsp[i].String(), MyWallet.addrs[unsp[i].AskIndex].String(),
				MyWallet.label[unsp[i].AskIndex])
		}

		// update the balance/ folder
		if utxt != nil {
			po, e := BlockChain.Unspent.UnspentGet(&unsp[i].TxPrevOut)
			if e != nil {
				println("UnspentGet:", e.Error())
				fmt.Println("This should not happen - please, report a bug.")
				fmt.Println("You can probably fix it by launching the client with -rescan")
				os.Exit(1)
			}

			txid := btc.NewUint256(unsp[i].TxPrevOut.Hash[:])

			// Store the unspent line in balance/unspent.txt
			fmt.Fprintf(utxt, "%s # %.8f BTC / %d / %s (%s)\n", unsp[i].TxPrevOut.String(),
				float64(unsp[i].Value)/1e8, unsp[i].MinedAt,
				MyWallet.addrs[unsp[i].AskIndex].String(), MyWallet.label[unsp[i].AskIndex])

			// store the entire transactiojn in balance/<txid>.tx
			fn := "balance/" + txid.String()[:64] + ".tx"
			txf, _ := os.Open(fn)
			if txf != nil {
				// This file already exist - do no need to redo it
				txf.Close()
				continue
			}

			// Find the block with the indicated Height in the main tree
			BlockChain.BlockIndexAccess.Lock()
			n := BlockChain.BlockTreeEnd
			if n.Height < po.BlockHeight {
				println(n.Height, po.BlockHeight)
				BlockChain.BlockIndexAccess.Unlock()
				panic("This should not happen")
			}
			for n.Height > po.BlockHeight {
				n = n.Parent
			}
			BlockChain.BlockIndexAccess.Unlock()

			bd, _, e := BlockChain.Blocks.BlockGet(n.BlockHash)
			if e != nil {
				println("BlockGet", n.BlockHash.String(), po.BlockHeight, e.Error())
				fmt.Println("This should not happen - please, report a bug.")
				fmt.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, _ = os.Create(fn)
					if txf == nil {
						println("Cannot create ", fn)
						os.Exit(1)
					}
					txf.Write(bl.Txs[i].Serialize())
					txf.Close()
					break
				}
			}
		}
	}
	fmt.Printf("%.8f BTC in total, in %d unspent outputs\n", float64(sum)/1e8, len(unsp))
	if utxt != nil {
		fmt.Println("Your balance data has been saved to the 'balance/' folder.")
		fmt.Println("You nend to move this folder to your wallet PC, to spend the coins.")
		utxt.Close()
	}
}
Esempio n. 10
0
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
		}
		block.BuildTxList()
		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(len(block.Txs)), 1)
		s = strings.Replace(s, "{BLOCK_SIZE}", fmt.Sprintf("%.1f", float64(len(bl))/1000), 1)
		var rew uint64
		for o := range block.Txs[0].TxOut {
			rew += block.Txs[0].TxOut[o].Value
		}
		s = strings.Replace(s, "{BLOCK_REWARD}", fmt.Sprintf("%.2f", float64(rew)/1e8), 1)
		mi, _ := common.BlocksMiner(bl)
		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)
}
Esempio n. 11
0
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)
}
Esempio n. 12
0
func import_blockchain(dir string) {
	trust := !ask_yes_no("Go you want to verify scripts while importing (will be slow)?")

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

	var bl *btc.Block
	var er error
	var dat []byte
	var totbytes 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 {
			prv = now // show progress each 10 seconds
			stat(now-start, totbytes, chain.BlockTreeEnd.Height)
		}

		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 {
			println("CheckBlock failed:", er.Error())
			continue
		}

		er = chain.AcceptBlock(bl)
		if er != nil {
			println("AcceptBlock failed:", er.Error())
			continue
		}

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

	stop := time.Now().UnixNano()
	stat(stop-start, totbytes, 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.Close()
	fmt.Println("Database saved. No more imports should be needed.")
}