github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/client/usif/webui/mining.go (about) 1 package webui 2 3 import ( 4 "fmt" 5 "sort" 6 "time" 7 8 // "bytes" 9 // "regexp" 10 "encoding/binary" 11 "encoding/json" 12 "net/http" 13 14 "github.com/piotrnar/gocoin/client/common" 15 "github.com/piotrnar/gocoin/lib/btc" 16 ) 17 18 type OneMinedBlock struct { 19 Height uint32 20 Version uint32 21 Length int 22 Fees uint64 23 Strings string 24 } 25 26 type omv struct { 27 unknown_miner bool 28 bts uint64 29 fees uint64 30 blocks []OneMinedBlock 31 //ebad_cnt int 32 //nya_cnt int 33 } 34 35 type onemiernstat []struct { 36 name string 37 omv 38 } 39 40 func (x onemiernstat) Len() int { 41 return len(x) 42 } 43 44 func (x onemiernstat) Less(i, j int) bool { 45 if len(x[i].blocks) == len(x[j].blocks) { 46 return x[i].name < x[j].name // Same numbers: sort by name 47 } 48 return len(x[i].blocks) > len(x[j].blocks) 49 } 50 51 func (x onemiernstat) Swap(i, j int) { 52 x[i], x[j] = x[j], x[i] 53 } 54 55 func p_miners(w http.ResponseWriter, r *http.Request) { 56 if !ipchecker(r) { 57 return 58 } 59 60 write_html_head(w, r) 61 w.Write([]byte(load_template("miners.html"))) 62 write_html_tail(w) 63 } 64 65 func json_blkver(w http.ResponseWriter, r *http.Request) { 66 if !ipchecker(r) { 67 return 68 } 69 70 w.Header()["Content-Type"] = []string{"application/json"} 71 72 common.Last.Mutex.Lock() 73 end := common.Last.Block 74 common.Last.Mutex.Unlock() 75 76 w.Write([]byte("[")) 77 if end != nil { 78 max_cnt := 2 * 2016 //common.BlockChain.Consensus.Window 79 for { 80 w.Write([]byte(fmt.Sprint("[", end.Height, ",", binary.LittleEndian.Uint32(end.BlockHeader[0:4]), "]"))) 81 end = end.Parent 82 if end == nil || max_cnt <= 1 { 83 break 84 } 85 max_cnt-- 86 w.Write([]byte(",")) 87 } 88 } 89 w.Write([]byte("]")) 90 } 91 92 func json_miners(w http.ResponseWriter, r *http.Request) { 93 if !ipchecker(r) { 94 return 95 } 96 97 type one_miner_row struct { 98 Unknown bool 99 Name string 100 Blocks int 101 TotalFees, TotalBytes uint64 102 MinedBlocks []OneMinedBlock 103 //BUcnt, NYAcnt int 104 } 105 106 type the_mining_stats struct { 107 MiningStatHours uint 108 BlockCount uint 109 FirstBlockTime int64 110 AvgBlocksPerHour float64 111 AvgDifficulty float64 112 AvgHashrate float64 113 NextDiffChange uint32 114 Miners []one_miner_row 115 } 116 117 common.ReloadMiners() 118 119 m := make(map[string]omv, 20) 120 var om omv 121 cnt := uint(0) 122 common.Last.Mutex.Lock() 123 end := common.Last.Block 124 common.Last.Mutex.Unlock() 125 var lastts int64 126 var diff float64 127 now := time.Now().Unix() 128 129 next_diff_change := 2016 - end.Height%2016 130 131 //eb_ad_x := regexp.MustCompile("/EB[0-9]+/AD[0-9]+/") 132 133 for ; end != nil; cnt++ { 134 if now-int64(end.Timestamp()) > int64(common.CFG.Stat.MiningHrs)*3600 { 135 break 136 } 137 lastts = int64(end.Timestamp()) 138 bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash) 139 if e != nil { 140 break 141 } 142 143 block, e := btc.NewBlock(bl) 144 if e != nil { 145 break 146 } 147 148 cbasetx, _ := btc.NewTx(bl[block.TxOffset:]) 149 150 strs := string(cbasetx.TxIn[0].ScriptSig) 151 152 diff += btc.GetDifficulty(end.Bits()) 153 miner, mid := common.TxMiner(cbasetx) 154 om = m[miner] 155 om.bts += uint64(len(bl)) 156 om.unknown_miner = (mid == -1) 157 158 // Blocks reward 159 var rew uint64 160 for o := range cbasetx.TxOut { 161 rew += cbasetx.TxOut[o].Value 162 } 163 fees := rew - btc.GetBlockReward(end.Height) 164 if int64(fees) > 0 { // solution for a possibility of a miner not claiming the reward (see block #501726) 165 om.fees += fees 166 } 167 om.blocks = append(om.blocks, OneMinedBlock{Height: end.Height, 168 Version: block.Version(), Length: len(bl), Fees: fees, Strings: strs}) 169 170 /*if eb_ad_x.Find(cbasetx.TxIn[0].ScriptSig) != nil { 171 om.ebad_cnt++ 172 } 173 174 if bytes.Index(cbasetx.TxIn[0].ScriptSig, []byte("/NYA/")) != -1 { 175 om.nya_cnt++ 176 }*/ 177 178 m[miner] = om 179 180 end = end.Parent 181 } 182 183 if cnt == 0 { 184 w.Write([]byte("{}")) 185 return 186 } 187 188 srt := make(onemiernstat, len(m)) 189 i := 0 190 for k, v := range m { 191 srt[i].name = k 192 srt[i].omv = v 193 i++ 194 } 195 sort.Sort(srt) 196 197 var stats the_mining_stats 198 199 diff /= float64(cnt) 200 bph := float64(cnt) / float64(common.CFG.Stat.MiningHrs) 201 hrate := bph / 6 * diff * 7158278.826667 202 203 stats.MiningStatHours = common.CFG.Stat.MiningHrs 204 stats.BlockCount = cnt 205 stats.FirstBlockTime = lastts 206 stats.AvgBlocksPerHour = bph 207 stats.AvgDifficulty = diff 208 stats.AvgHashrate = hrate 209 stats.NextDiffChange = next_diff_change 210 211 stats.Miners = make([]one_miner_row, len(srt)) 212 for i := range srt { 213 stats.Miners[i].Unknown = srt[i].unknown_miner 214 stats.Miners[i].Name = srt[i].name 215 stats.Miners[i].Blocks = len(srt[i].blocks) 216 stats.Miners[i].TotalFees = srt[i].fees 217 stats.Miners[i].TotalBytes = srt[i].bts 218 stats.Miners[i].MinedBlocks = srt[i].blocks 219 //stats.Miners[i].BUcnt = srt[i].ebad_cnt 220 //stats.Miners[i].NYAcnt = srt[i].nya_cnt 221 } 222 223 bx, er := json.Marshal(stats) 224 if er == nil { 225 w.Header()["Content-Type"] = []string{"application/json"} 226 w.Write(bx) 227 } else { 228 println(er.Error()) 229 } 230 231 }