// 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} }
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} }
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) }
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) }
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() }
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) }
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 }
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.") }
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() } }
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) }
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) }
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.") }