func set_miner(p string) { if p == "" { fmt.Println("Specify MinerID string or one of the numberic values:") for i := range common.MinerIds { fmt.Printf("%3d - %s\n", i, common.MinerIds[i][0]) } return } if p == "off" { common.LockCfg() common.CFG.Beeps.MinerID = "" common.UnlockCfg() fmt.Printf("Mining monitor disabled\n") return } v, e := strconv.ParseUint(p, 10, 32) common.LockCfg() if e != nil { common.CFG.Beeps.MinerID = p } else if int(v) < len(common.MinerIds) { common.CFG.Beeps.MinerID = common.MinerIds[v][1] } else { fmt.Println("The number is too big. Max is", len(common.MinerIds)-1) } fmt.Printf("Current miner ID: '%s'\n", common.CFG.Beeps.MinerID) common.UnlockCfg() }
func NetCloseAll() { println("Closing network") common.NetworkClosed = true time.Sleep(1e9) // give one second for WebUI requests to complete common.LockCfg() common.SetListenTCP(false, false) common.UnlockCfg() Mutex_net.Lock() if InConsActive > 0 || OutConsActive > 0 { for _, v := range OpenCons { v.Disconnect() } } Mutex_net.Unlock() for { Mutex_net.Lock() all_done := InConsActive == 0 && OutConsActive == 0 Mutex_net.Unlock() if all_done { return } time.Sleep(1e7) } for TCPServerStarted { time.Sleep(1e7) // give one second for all the pending messages to get processed } }
func NetworkTick() { common.CountSafe("NetTicks") if common.CFG.Net.ListenTCP { if !TCPServerStarted { TCPServerStarted = true go tcp_server() } } Mutex_net.Lock() conn_cnt := OutConsActive Mutex_net.Unlock() if next_drop_slowest.IsZero() { next_drop_slowest = time.Now().Add(DropSlowestEvery) } else if conn_cnt >= atomic.LoadUint32(&common.CFG.Net.MaxOutCons) { // Having max number of outgoing connections, check to drop the slowest one if time.Now().After(next_drop_slowest) { drop_slowest_peer() next_drop_slowest = time.Now().Add(DropSlowestEvery) } } // hammering protection - expire recently disconnected if next_clean_hammers.IsZero() { next_clean_hammers = time.Now().Add(HammeringMinReconnect) } else if time.Now().After(next_clean_hammers) { HammeringMutex.Lock() for k, t := range RecentlyDisconencted { if time.Now().Sub(t) >= HammeringMinReconnect { delete(RecentlyDisconencted, k) } } HammeringMutex.Unlock() next_clean_hammers = time.Now().Add(HammeringMinReconnect) } for conn_cnt < atomic.LoadUint32(&common.CFG.Net.MaxOutCons) { adrs := GetBestPeers(16, true) if len(adrs) == 0 { common.LockCfg() if common.CFG.ConnectOnly == "" && common.DebugLevel > 0 { println("no new peers", len(OpenCons), conn_cnt) } common.UnlockCfg() break } DoNetwork(adrs[rand.Int31n(int32(len(adrs)))]) Mutex_net.Lock() conn_cnt = OutConsActive Mutex_net.Unlock() } }
func NetworkTick() { common.CountSafe("NetTicks") if common.CFG.Net.ListenTCP { if !TCPServerStarted { TCPServerStarted = true go tcp_server() } } Mutex_net.Lock() conn_cnt := OutConsActive Mutex_net.Unlock() if next_drop_slowest.IsZero() { next_drop_slowest = time.Now().Add(DropSlowestEvery) } else if conn_cnt >= atomic.LoadUint32(&common.CFG.Net.MaxOutCons) { // Having max number of outgoing connections, check to drop the slowest one if time.Now().After(next_drop_slowest) { drop_slowest_peer() next_drop_slowest = time.Now().Add(DropSlowestEvery) } } for conn_cnt < atomic.LoadUint32(&common.CFG.Net.MaxOutCons) { adrs := GetBestPeers(16, true) if len(adrs) == 0 { common.LockCfg() if common.CFG.ConnectOnly == "" && common.DebugLevel > 0 { println("no new peers", len(OpenCons), conn_cnt) } common.UnlockCfg() break } DoNetwork(adrs[rand.Int31n(int32(len(adrs)))]) Mutex_net.Lock() conn_cnt = OutConsActive Mutex_net.Unlock() } }
func p_home(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } // The handler also gets called for /favicon.ico if r.URL.Path != "/" { http.NotFound(w, r) } s := load_template("home.html") wallet.BalanceMutex.Lock() if len(wallet.MyBalance) > 0 { wal := load_template("home_wal.html") wal = strings.Replace(wal, "{TOTAL_BTC}", fmt.Sprintf("%.8f", float64(wallet.LastBalance)/1e8), 1) wal = strings.Replace(wal, "{UNSPENT_OUTS}", fmt.Sprint(len(wallet.MyBalance)), 1) s = strings.Replace(s, "<!--WALLET-->", wal, 1) } else { if wallet.MyWallet == nil { s = strings.Replace(s, "<!--WALLET-->", "You have no wallet", 1) } else { s = strings.Replace(s, "<!--WALLET-->", "Your balance is <b>zero</b>", 1) } } wallet.BalanceMutex.Unlock() s = strings.Replace(s, "<--NETWORK_HASHRATE-->", usif.GetNetworkHashRate(), 1) s = strings.Replace(s, "<!--NEW_BLOCK_BEEP-->", fmt.Sprint(common.CFG.Beeps.NewBlock), 1) common.LockCfg() dat, _ := json.Marshal(&common.CFG) common.UnlockCfg() s = strings.Replace(s, "{CONFIG_FILE}", strings.Replace(string(dat), ",\"", ", \"", -1), 1) write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func NetCloseAll() { println("Closing network") common.LockCfg() common.CFG.Net.ListenTCP = false common.UnlockCfg() Mutex_net.Lock() if InConsActive > 0 || OutConsActive > 0 { for _, v := range OpenCons { v.Disconnect() } } Mutex_net.Unlock() for { Mutex_net.Lock() all_done := InConsActive == 0 && OutConsActive == 0 Mutex_net.Unlock() if all_done { return } time.Sleep(1e7) } }
func p_home(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } // The handler also gets called for /favicon.ico if r.URL.Path != "/" { http.NotFound(w, r) } s := load_template("home.html") s = strings.Replace(s, "<--NETWORK_HASHRATE-->", usif.GetNetworkHashRate(), 1) s = strings.Replace(s, "<!--NEW_BLOCK_BEEP-->", fmt.Sprint(common.CFG.Beeps.NewBlock), 1) common.LockCfg() dat, _ := json.Marshal(&common.CFG) common.UnlockCfg() s = strings.Replace(s, "{CONFIG_FILE}", strings.Replace(string(dat), ",\"", ", \"", -1), 1) write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func p_home(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } s := load_template("home.html") wallet.LockBal() if len(wallet.MyBalance) > 0 { wal := load_template("home_wal.html") wal = strings.Replace(wal, "{TOTAL_BTC}", fmt.Sprintf("%.8f", float64(wallet.LastBalance)/1e8), 1) wal = strings.Replace(wal, "{UNSPENT_OUTS}", fmt.Sprint(len(wallet.MyBalance)), 1) s = strings.Replace(s, "<!--WALLET-->", wal, 1) } else { if wallet.MyWallet == nil { s = strings.Replace(s, "<!--WALLET-->", "You have no wallet", 1) } else { s = strings.Replace(s, "<!--WALLET-->", "Your balance is <b>zero</b>", 1) } } wallet.UnlockBal() common.Last.Mutex.Lock() s = strings.Replace(s, "{LAST_BLOCK_HASH}", common.Last.Block.BlockHash.String(), 1) s = strings.Replace(s, "{LAST_BLOCK_HEIGHT}", fmt.Sprint(common.Last.Block.Height), 1) s = strings.Replace(s, "{LAST_BLOCK_TIME}", time.Unix(int64(common.Last.Block.Timestamp), 0).Format("2006/01/02 15:04:05"), 1) s = strings.Replace(s, "{LAST_BLOCK_DIFF}", common.NumberToString(btc.GetDifficulty(common.Last.Block.Bits)), 1) s = strings.Replace(s, "{LAST_BLOCK_RCVD}", time.Now().Sub(common.Last.Time).String(), 1) common.Last.Mutex.Unlock() s = strings.Replace(s, "{BLOCKS_CACHED}", fmt.Sprint(len(network.CachedBlocks)), 1) s = strings.Replace(s, "{KNOWN_PEERS}", fmt.Sprint(network.PeerDB.Count()), 1) s = strings.Replace(s, "{NODE_UPTIME}", time.Now().Sub(common.StartTime).String(), 1) s = strings.Replace(s, "{NET_BLOCK_QSIZE}", fmt.Sprint(len(network.NetBlocks)), 1) s = strings.Replace(s, "{NET_TX_QSIZE}", fmt.Sprint(len(network.NetTxs)), 1) network.Mutex_net.Lock() s = strings.Replace(s, "{OPEN_CONNS_TOTAL}", fmt.Sprint(len(network.OpenCons)), 1) s = strings.Replace(s, "{OPEN_CONNS_OUT}", fmt.Sprint(network.OutConsActive), 1) s = strings.Replace(s, "{OPEN_CONNS_IN}", fmt.Sprint(network.InConsActive), 1) network.Mutex_net.Unlock() common.LockBw() common.TickRecv() common.TickSent() s = strings.Replace(s, "{DL_SPEED_NOW}", fmt.Sprint(common.DlBytesPrevSec>>10), 1) s = strings.Replace(s, "{DL_SPEED_MAX}", fmt.Sprint(common.DownloadLimit>>10), 1) s = strings.Replace(s, "{DL_TOTAL}", common.BytesToString(common.DlBytesTotal), 1) s = strings.Replace(s, "{UL_SPEED_NOW}", fmt.Sprint(common.UlBytesPrevSec>>10), 1) s = strings.Replace(s, "{UL_SPEED_MAX}", fmt.Sprint(common.UploadLimit>>10), 1) s = strings.Replace(s, "{UL_TOTAL}", common.BytesToString(common.UlBytesTotal), 1) common.UnlockBw() network.ExternalIpMutex.Lock() for ip, cnt := range network.ExternalIp4 { s = strings.Replace(s, "{ONE_EXTERNAL_IP}", fmt.Sprintf("%dx%d.%d.%d.%d {ONE_EXTERNAL_IP}", cnt, byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)), 1) } network.ExternalIpMutex.Unlock() s = strings.Replace(s, "{ONE_EXTERNAL_IP}", "", 1) var ms runtime.MemStats runtime.ReadMemStats(&ms) s = strings.Replace(s, "{HEAP_SIZE_MB}", fmt.Sprint(ms.Alloc>>20), 1) s = strings.Replace(s, "{SYSMEM_USED_MB}", fmt.Sprint(ms.Sys>>20), 1) s = strings.Replace(s, "{ECDSA_VERIFY_COUNT}", fmt.Sprint(btc.EcdsaVerifyCnt), 1) common.LockCfg() dat, _ := json.Marshal(&common.CFG) common.UnlockCfg() s = strings.Replace(s, "{CONFIG_FILE}", strings.Replace(string(dat), ",\"", ", \"", -1), 1) write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func p_miners(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } m := make(map[string]omv, 20) var unkn, om omv cnt := 0 common.Last.Mutex.Lock() end := common.Last.Block common.Last.Mutex.Unlock() var lastts int64 var diff float64 var totbts uint64 current_mid := -1 now := time.Now().Unix() common.LockCfg() minerid := common.CFG.Beeps.MinerID common.UnlockCfg() next_diff_change := 2016 - end.Height%2016 for ; end != nil; cnt++ { if now-int64(end.Timestamp()) > int64(common.CFG.MiningStatHours)*3600 { break } lastts = int64(end.Timestamp()) bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash) if e != nil { return } diff += btc.GetDifficulty(end.Bits()) miner, mid := common.BlocksMiner(bl) if miner != "" { om = m[miner] om.cnt++ om.bts += uint64(len(bl)) om.mid = mid m[miner] = om if current_mid == -1 && minerid == common.MinerIds[mid][1] { current_mid = mid } } else { unkn.cnt++ unkn.bts += uint64(len(bl)) } totbts += uint64(len(bl)) end = end.Parent } if cnt == 0 { write_html_head(w, r) w.Write([]byte(fmt.Sprint("No blocks in last ", common.CFG.MiningStatHours, " hours"))) write_html_tail(w) return } srt := make(onemiernstat, len(m)) i := 0 for k, v := range m { srt[i].name = k srt[i].omv = v i++ } sort.Sort(srt) mnrs := load_template("miners.html") onerow := load_template("miners_row.html") diff /= float64(cnt) bph := float64(cnt) / float64(common.CFG.MiningStatHours) hrate := bph / 6 * diff * 7158278.826667 mnrs = strings.Replace(mnrs, "{MINING_HOURS}", fmt.Sprint(common.CFG.MiningStatHours), 1) mnrs = strings.Replace(mnrs, "{BLOCKS_COUNT}", fmt.Sprint(cnt), 1) mnrs = strings.Replace(mnrs, "{FIRST_BLOCK_TIME}", time.Unix(lastts, 0).Format("2006-01-02 15:04:05"), 1) mnrs = strings.Replace(mnrs, "{AVG_BLOCKS_PER_HOUR}", fmt.Sprintf("%.2f", bph), 1) mnrs = strings.Replace(mnrs, "{AVG_DIFFICULTY}", common.NumberToString(diff), 1) mnrs = strings.Replace(mnrs, "{AVG_HASHDATE}", common.HashrateToString(hrate), 1) mnrs = strings.Replace(mnrs, "{AVG_BLOCKSIZE}", fmt.Sprintf("%.1fKB", float64(totbts)/float64(cnt)/1000), 1) mnrs = strings.Replace(mnrs, "{DIFF_CHANGE_IN}", fmt.Sprint(next_diff_change), 1) mnrs = strings.Replace(mnrs, "{MINER_MON_IDX}", fmt.Sprint(current_mid), 1) for i := range srt { s := onerow s = strings.Replace(s, "{MINER_NAME}", srt[i].name, 1) s = strings.Replace(s, "{BLOCK_COUNT}", fmt.Sprint(srt[i].cnt), 1) s = strings.Replace(s, "{TOTAL_PERCENT}", fmt.Sprintf("%.0f", 100*float64(srt[i].cnt)/float64(cnt)), 1) s = strings.Replace(s, "{MINER_HASHRATE}", common.HashrateToString(hrate*float64(srt[i].cnt)/float64(cnt)), 1) s = strings.Replace(s, "{AVG_BLOCK_SIZE}", fmt.Sprintf("%.1fKB", float64(srt[i].bts)/float64(srt[i].cnt)/1000), 1) s = strings.Replace(s, "{MINER_ID}", fmt.Sprint(srt[i].mid), -1) mnrs = templ_add(mnrs, "<!--MINER_ROW-->", s) } onerow = strings.Replace(onerow, "{MINER_NAME}", "<i>Unknown</i>", 1) onerow = strings.Replace(onerow, "{BLOCK_COUNT}", fmt.Sprint(unkn.cnt), 1) onerow = strings.Replace(onerow, "{TOTAL_PERCENT}", fmt.Sprintf("%.0f", 100*float64(unkn.cnt)/float64(cnt)), 1) onerow = strings.Replace(onerow, "{MINER_HASHRATE}", common.HashrateToString(hrate*float64(unkn.cnt)/float64(cnt)), 1) onerow = strings.Replace(onerow, "{AVG_BLOCK_SIZE}", fmt.Sprintf("%.1fKB", float64(unkn.bts)/float64(unkn.cnt)/1000), 1) onerow = strings.Replace(onerow, "{MINER_ID}", "-1", -1) mnrs = templ_add(mnrs, "<!--MINER_ROW-->", onerow) write_html_head(w, r) w.Write([]byte(mnrs)) 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 p_cfg(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } common.LockCfg() defer common.UnlockCfg() if checksid(r) && len(r.Form["txponoff"]) > 0 { common.CFG.TXPool.Enabled = !common.CFG.TXPool.Enabled http.Redirect(w, r, "txs", http.StatusFound) return } if checksid(r) && len(r.Form["txronoff"]) > 0 { common.CFG.TXRoute.Enabled = !common.CFG.TXRoute.Enabled http.Redirect(w, r, "txs", http.StatusFound) return } if checksid(r) && len(r.Form["lonoff"]) > 0 { common.CFG.Net.ListenTCP = !common.CFG.Net.ListenTCP http.Redirect(w, r, "net", http.StatusFound) return } if checksid(r) && len(r.Form["drop"]) > 0 { network.DropPeer(r.Form["drop"][0]) http.Redirect(w, r, "net", http.StatusFound) return } if checksid(r) && len(r.Form["savecfg"]) > 0 { dat, _ := json.Marshal(&common.CFG) if dat != nil { ioutil.WriteFile(common.ConfigFile, dat, 0660) } http.Redirect(w, r, "/", http.StatusFound) return } if checksid(r) && len(r.Form["beepblock"]) > 0 { common.CFG.Beeps.NewBlock = !common.CFG.Beeps.NewBlock http.Redirect(w, r, "/", http.StatusFound) return } if checksid(r) && len(r.Form["freemem"]) > 0 { debug.FreeOSMemory() http.Redirect(w, r, "/", http.StatusFound) return } if r.Method == "POST" && len(r.Form["configjson"]) > 0 { e := json.Unmarshal([]byte(r.Form["configjson"][0]), &common.CFG) if e == nil { common.Reset() } if len(r.Form["save"]) > 0 { dat, _ := json.Marshal(&common.CFG) if dat != nil { ioutil.WriteFile(common.ConfigFile, dat, 0660) } } http.Redirect(w, r, "/", http.StatusFound) return } if r.Method == "POST" && len(r.Form["walletdata"]) > 0 && len(r.Form["walletfname"]) > 0 { fn := r.Form["walletfname"][0] if fn == "" { fn = wallet.DefaultFileName } fn = common.GocoinHomeDir + "wallet" + string(os.PathSeparator) + fn ioutil.WriteFile(fn, []byte(r.Form["walletdata"][0]), 0660) wallet.LoadWallet(fn) http.Redirect(w, r, "/wal", http.StatusFound) return } if r.Method == "POST" && len(r.Form["shutdown"]) > 0 { usif.Exit_now = true w.Write([]byte("Your node should shut down soon")) return } if checksid(r) && len(r.Form["mid"]) > 0 { v, e := strconv.ParseUint(r.Form["mid"][0], 10, 32) if e == nil && v < uint64(len(common.MinerIds)) { common.CFG.Beeps.MinerID = common.MinerIds[v][1] } else { common.CFG.Beeps.MinerID = "" } http.Redirect(w, r, "miners", http.StatusFound) return } }
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 bip100_voting := make(map[string]uint) bip100x := regexp.MustCompile("/BV{0,1}[0-9]+[M]{0,1}/") 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 } bt, _ := btc.NewBlock(bl) cbasetx, cbtxlen := btc.NewTx(bl[bt.TxOffset:]) tot_blocks++ tot_blocks_len += len(bl) diff += btc.GetDifficulty(block.Bits()) common.LockCfg() if common.CFG.Beeps.MinerID != "" && bytes.Contains(bl[bt.TxOffset:bt.TxOffset+cbtxlen], []byte(common.CFG.Beeps.MinerID)) { 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) } common.UnlockCfg() res := bip100x.Find(cbasetx.TxIn[0].ScriptSig) if res != nil { bip100_voting[string(res)]++ nimer, _ := common.TxMiner(cbasetx) fmt.Println(" block", end.Height, "by", nimer, "voting", string(res), " total:", bip100_voting[string(res)]) } 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 p_miners(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } common.ReloadMiners() m := make(map[string]omv, 20) var om omv cnt := 0 common.Last.Mutex.Lock() end := common.Last.Block common.Last.Mutex.Unlock() var lastts int64 var diff float64 var totbts uint64 var totfees uint64 current_mid := -1 now := time.Now().Unix() common.LockCfg() minerid := common.CFG.Beeps.MinerID common.UnlockCfg() next_diff_change := 2016 - end.Height%2016 block_versions := make(map[uint32]uint) // bip100 bip100_voting := make(map[string]uint) //var bip100, bip100v uint64 bip100x := regexp.MustCompile("/BV{0,1}[0-9]+[M]{0,1}/") //bip100rx := regexp.MustCompile("/B[0-9]+[M]{0,1}/") for ; end != nil; cnt++ { if now-int64(end.Timestamp()) > int64(common.CFG.MiningStatHours)*3600 { break } lastts = int64(end.Timestamp()) bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash) if e != nil { return } block, e := btc.NewBlock(bl) cbasetx, _ := btc.NewTx(bl[block.TxOffset:]) block_versions[binary.LittleEndian.Uint32(bl[0:4])]++ diff += btc.GetDifficulty(end.Bits()) miner, mid := common.TxMiner(cbasetx) if mid == -1 { miner = "<i>" + miner + "</i>" } om = m[miner] om.cnt++ om.bts += uint64(len(bl)) om.mid = mid // Blocks reward var rew uint64 for o := range cbasetx.TxOut { rew += cbasetx.TxOut[o].Value } om.fees += rew - btc.GetBlockReward(end.Height) // bip-100 res := bip100x.Find(cbasetx.TxIn[0].ScriptSig) if res != nil { bip100_voting[string(res)]++ } m[miner] = om if mid != -1 && current_mid == -1 && minerid == string(common.MinerIds[mid].Tag) { current_mid = mid } totbts += uint64(len(bl)) end = end.Parent } if cnt == 0 { write_html_head(w, r) w.Write([]byte(fmt.Sprint("No blocks in last ", common.CFG.MiningStatHours, " hours"))) write_html_tail(w) return } srt := make(onemiernstat, len(m)) i := 0 for k, v := range m { srt[i].name = k srt[i].omv = v i++ } sort.Sort(srt) mnrs := load_template("miners.html") onerow := load_template("miners_row.html") diff /= float64(cnt) bph := float64(cnt) / float64(common.CFG.MiningStatHours) hrate := bph / 6 * diff * 7158278.826667 mnrs = strings.Replace(mnrs, "{MINING_HOURS}", fmt.Sprint(common.CFG.MiningStatHours), 1) mnrs = strings.Replace(mnrs, "{BLOCKS_COUNT}", fmt.Sprint(cnt), 1) mnrs = strings.Replace(mnrs, "{FIRST_BLOCK_TIME}", time.Unix(lastts, 0).Format("2006-01-02 15:04:05"), 1) mnrs = strings.Replace(mnrs, "{AVG_BLOCKS_PER_HOUR}", fmt.Sprintf("%.2f", bph), 1) mnrs = strings.Replace(mnrs, "{AVG_DIFFICULTY}", common.NumberToString(diff), 1) mnrs = strings.Replace(mnrs, "{AVG_HASHDATE}", common.HashrateToString(hrate), 1) mnrs = strings.Replace(mnrs, "{AVG_BLOCKSIZE}", fmt.Sprintf("%.1fKB", float64(totbts)/float64(cnt)/1000), 1) mnrs = strings.Replace(mnrs, "{DIFF_CHANGE_IN}", fmt.Sprint(next_diff_change), 1) mnrs = strings.Replace(mnrs, "{MINER_MON_IDX}", fmt.Sprint(current_mid), 1) for i := range srt { s := onerow s = strings.Replace(s, "{MINER_NAME}", srt[i].name, 1) s = strings.Replace(s, "{BLOCK_COUNT}", fmt.Sprint(srt[i].cnt), 1) s = strings.Replace(s, "{TOTAL_PERCENT}", fmt.Sprintf("%.0f", 100*float64(srt[i].cnt)/float64(cnt)), 1) s = strings.Replace(s, "{MINER_HASHRATE}", common.HashrateToString(hrate*float64(srt[i].cnt)/float64(cnt)), 1) s = strings.Replace(s, "{AVG_BLOCK_SIZE}", fmt.Sprintf("%.1fKB", float64(srt[i].bts)/float64(srt[i].cnt)/1000), 1) s = strings.Replace(s, "{MINER_ID}", fmt.Sprint(srt[i].mid), -1) s = strings.Replace(s, "<!--TOTAL_FEES-->", btc.UintToBtc(srt[i].fees), -1) s = strings.Replace(s, "<!--FEE_PER_BYTE-->", fmt.Sprint(srt[i].fees/srt[i].bts), -1) mnrs = templ_add(mnrs, "<!--MINER_ROW-->", s) totfees += srt[i].fees } mnrs = strings.Replace(mnrs, "<!--TOTAL_MINING_FEES-->", btc.UintToBtc(totfees), 1) mnrs = strings.Replace(mnrs, "<!--AVERAGE_FEE_PER_BYTE-->", fmt.Sprint(totfees/totbts), 1) var bv string for k, v := range block_versions { if bv != "" { bv += ", " } bv += fmt.Sprintf("%d (%d%%) x <b>v%d</b>", v, 100*int(v)/cnt, k) } mnrs = strings.Replace(mnrs, "<!--BLOCK_VERSIONS-->", bv, 1) // bip100 bv = "" for k, v := range bip100_voting { if bv != "" { bv += " + " } bv += fmt.Sprintf("%sx%d", k, v) } mnrs = strings.Replace(mnrs, "<!--BLOCKSIZE_VOTES-->", bv, 1) write_html_head(w, r) w.Write([]byte(mnrs)) write_html_tail(w) }
func NetworkTick() { if common.IsListenTCP() { if !TCPServerStarted { TCPServerStarted = true go tcp_server() } } // Push GetHeaders if not in progress Mutex_net.Lock() var cnt_headers_in_progress int var max_headers_got_cnt int var _v *OneConnection for _, v := range OpenCons { v.Mutex.Lock() if !v.X.AllHeadersReceived || v.X.GetHeadersInProgress { cnt_headers_in_progress++ } else if !v.X.LastHeadersEmpty { if _v == nil || v.X.TotalNewHeadersCount > max_headers_got_cnt { max_headers_got_cnt = v.X.TotalNewHeadersCount _v = v } } v.Mutex.Unlock() } conn_cnt := OutConsActive Mutex_net.Unlock() if cnt_headers_in_progress == 0 { if _v != nil { common.CountSafe("GetHeadersPush") /*println("No headers_in_progress, so take it from", _v.ConnID, _v.X.TotalNewHeadersCount, _v.X.LastHeadersEmpty)*/ _v.Mutex.Lock() _v.X.AllHeadersReceived = false _v.Mutex.Unlock() } else { common.CountSafe("GetHeadersNone") } } if common.CFG.DropPeers.DropEachMinutes != 0 { if next_drop_peer.IsZero() { next_drop_peer = time.Now().Add(common.DropSlowestEvery) } else if time.Now().After(next_drop_peer) { drop_worst_peer() next_drop_peer = time.Now().Add(common.DropSlowestEvery) } } // hammering protection - expire recently disconnected if next_clean_hammers.IsZero() { next_clean_hammers = time.Now().Add(HammeringMinReconnect) } else if time.Now().After(next_clean_hammers) { HammeringMutex.Lock() for k, t := range RecentlyDisconencted { if time.Now().Sub(t) >= HammeringMinReconnect { delete(RecentlyDisconencted, k) } } HammeringMutex.Unlock() next_clean_hammers = time.Now().Add(HammeringMinReconnect) } for conn_cnt < atomic.LoadUint32(&common.CFG.Net.MaxOutCons) { var segwit_conns uint32 if common.CFG.Net.MinSegwitCons > 0 { Mutex_net.Lock() for _, cc := range OpenCons { if (cc.Node.Services & SERVICE_SEGWIT) != 0 { segwit_conns++ } } Mutex_net.Unlock() } adrs := peersdb.GetBestPeers(128, func(ad *peersdb.PeerAddr) bool { if segwit_conns < common.CFG.Net.MinSegwitCons && (ad.Services&SERVICE_SEGWIT) == 0 { return true } return ConnectionActive(ad) }) if len(adrs) == 0 { common.LockCfg() if common.CFG.ConnectOnly == "" && common.DebugLevel > 0 { println("no new peers", len(OpenCons), conn_cnt) } common.UnlockCfg() break } DoNetwork(adrs[rand.Int31n(int32(len(adrs)))]) Mutex_net.Lock() conn_cnt = OutConsActive Mutex_net.Unlock() } }
func p_home(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } // The handler also gets called for /favicon.ico if r.URL.Path != "/" { http.NotFound(w, r) } s := load_template("home.html") wallet.BalanceMutex.Lock() if len(wallet.MyBalance) > 0 { wal := load_template("home_wal.html") wal = strings.Replace(wal, "{TOTAL_BTC}", fmt.Sprintf("%.8f", float64(wallet.LastBalance)/1e8), 1) wal = strings.Replace(wal, "{UNSPENT_OUTS}", fmt.Sprint(len(wallet.MyBalance)), 1) s = strings.Replace(s, "<!--WALLET-->", wal, 1) } else { if wallet.MyWallet == nil { s = strings.Replace(s, "<!--WALLET-->", "You have no wallet", 1) } else { s = strings.Replace(s, "<!--WALLET-->", "Your balance is <b>zero</b>", 1) } } wallet.BalanceMutex.Unlock() common.Last.Mutex.Lock() s = strings.Replace(s, "{LAST_BLOCK_HASH}", common.Last.Block.BlockHash.String(), 1) s = strings.Replace(s, "{LAST_BLOCK_HEIGHT}", fmt.Sprint(common.Last.Block.Height), 1) s = strings.Replace(s, "{LAST_BLOCK_TIME}", time.Unix(int64(common.Last.Block.Timestamp()), 0).Format("2006/01/02 15:04:05"), 1) s = strings.Replace(s, "{LAST_BLOCK_DIFF}", common.NumberToString(btc.GetDifficulty(common.Last.Block.Bits())), 1) s = strings.Replace(s, "{LAST_BLOCK_RCVD}", time.Now().Sub(common.Last.Time).String(), 1) common.Last.Mutex.Unlock() s = strings.Replace(s, "<--NETWORK_HASHRATE-->", usif.GetNetworkHashRate(), 1) s = strings.Replace(s, "{BLOCKS_CACHED}", fmt.Sprint(len(network.CachedBlocks)), 1) s = strings.Replace(s, "{KNOWN_PEERS}", fmt.Sprint(network.PeerDB.Count()), 1) s = strings.Replace(s, "{NODE_UPTIME}", time.Now().Sub(common.StartTime).String(), 1) s = strings.Replace(s, "{NET_BLOCK_QSIZE}", fmt.Sprint(len(network.NetBlocks)), 1) s = strings.Replace(s, "{NET_TX_QSIZE}", fmt.Sprint(len(network.NetTxs)), 1) network.Mutex_net.Lock() s = strings.Replace(s, "{OPEN_CONNS_TOTAL}", fmt.Sprint(len(network.OpenCons)), 1) s = strings.Replace(s, "{OPEN_CONNS_OUT}", fmt.Sprint(network.OutConsActive), 1) s = strings.Replace(s, "{OPEN_CONNS_IN}", fmt.Sprint(network.InConsActive), 1) network.Mutex_net.Unlock() common.LockBw() common.TickRecv() common.TickSent() s = strings.Replace(s, "{DL_SPEED_NOW}", fmt.Sprint(common.DlBytesPrevSec>>10), 1) s = strings.Replace(s, "{DL_SPEED_MAX}", fmt.Sprint(common.DownloadLimit>>10), 1) s = strings.Replace(s, "{DL_TOTAL}", common.BytesToString(common.DlBytesTotal), 1) s = strings.Replace(s, "{UL_SPEED_NOW}", fmt.Sprint(common.UlBytesPrevSec>>10), 1) s = strings.Replace(s, "{UL_SPEED_MAX}", fmt.Sprint(common.UploadLimit>>10), 1) s = strings.Replace(s, "{UL_TOTAL}", common.BytesToString(common.UlBytesTotal), 1) common.UnlockBw() network.ExternalIpMutex.Lock() for ip, rec := range network.ExternalIp4 { ips := fmt.Sprintf("<b title=\"%d times. Last seen %d min ago\">%d.%d.%d.%d</b> ", rec[0], (uint(time.Now().Unix())-rec[1])/60, byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)) s = templ_add(s, "<!--ONE_EXTERNAL_IP-->", ips) } network.ExternalIpMutex.Unlock() al, sy := sys.MemUsed() s = strings.Replace(s, "<!--HEAP_SIZE_MB-->", fmt.Sprint(al>>20), 1) s = strings.Replace(s, "<!--HEAPSYS_MB-->", fmt.Sprint(sy>>20), 1) s = strings.Replace(s, "<!--WDB_EXTRA_MB-->", fmt.Sprint(qdb.ExtraMemoryConsumed>>20), 1) s = strings.Replace(s, "{ECDSA_VERIFY_COUNT}", fmt.Sprint(btc.EcdsaVerifyCnt), 1) s = strings.Replace(s, "<!--NEW_BLOCK_BEEP-->", fmt.Sprint(common.CFG.Beeps.NewBlock), 1) common.LockCfg() dat, _ := json.Marshal(&common.CFG) common.UnlockCfg() s = strings.Replace(s, "{CONFIG_FILE}", strings.Replace(string(dat), ",\"", ", \"", -1), 1) write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func p_cfg(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } common.LockCfg() defer common.UnlockCfg() if r.Method == "POST" { if len(r.Form["configjson"]) > 0 { e := json.Unmarshal([]byte(r.Form["configjson"][0]), &common.CFG) if e == nil { common.Reset() } if len(r.Form["save"]) > 0 { common.SaveConfig() } http.Redirect(w, r, "/", http.StatusFound) return } if len(r.Form["walletdata"]) > 0 && len(r.Form["walletfname"]) > 0 { fn := r.Form["walletfname"][0] if fn != "" { fn = common.CFG.Walletdir + string(os.PathSeparator) + fn ioutil.WriteFile(fn, []byte(r.Form["walletdata"][0]), 0660) wallet.LoadWallet(fn) } http.Redirect(w, r, "/wal", http.StatusFound) return } if len(r.Form["shutdown"]) > 0 { usif.Exit_now = true w.Write([]byte("Your node should shut down soon")) return } return } // for any other GET we need a matching session-id if !checksid(r) { new_session_id(w) return } if len(r.Form["txponoff"]) > 0 { common.CFG.TXPool.Enabled = !common.CFG.TXPool.Enabled http.Redirect(w, r, "txs", http.StatusFound) return } if len(r.Form["txronoff"]) > 0 { common.CFG.TXRoute.Enabled = !common.CFG.TXRoute.Enabled http.Redirect(w, r, "txs", http.StatusFound) return } if len(r.Form["lonoff"]) > 0 { common.SetListenTCP(!common.IsListenTCP(), true) http.Redirect(w, r, "net", http.StatusFound) return } if len(r.Form["drop"]) > 0 { network.DropPeer(r.Form["drop"][0]) http.Redirect(w, r, "net", http.StatusFound) return } if len(r.Form["savecfg"]) > 0 { dat, _ := json.Marshal(&common.CFG) if dat != nil { ioutil.WriteFile(common.ConfigFile, dat, 0660) } http.Redirect(w, r, "/", http.StatusFound) return } if len(r.Form["beepblock"]) > 0 { common.CFG.Beeps.NewBlock = !common.CFG.Beeps.NewBlock http.Redirect(w, r, "/", http.StatusFound) return } if len(r.Form["freemem"]) > 0 { sys.FreeMem() http.Redirect(w, r, "/", http.StatusFound) return } if len(r.Form["mid"]) > 0 { v, e := strconv.ParseUint(r.Form["mid"][0], 10, 32) if e == nil && v < uint64(len(common.MinerIds)) { common.CFG.Beeps.MinerID = string(common.MinerIds[v].Tag) } else { common.CFG.Beeps.MinerID = "" } http.Redirect(w, r, "miners", http.StatusFound) return } }