當前位置:
首頁 > 科技 > 兄弟連區塊鏈培訓open-ethereum-pool以太坊礦池源碼分析(2)API分析

兄弟連區塊鏈培訓open-ethereum-pool以太坊礦池源碼分析(2)API分析

原標題:兄弟連區塊鏈培訓open-ethereum-pool以太坊礦池源碼分析(2)API分析


兄弟連區塊鏈培訓課程體系設計架構包括了區塊鏈的基礎語言Go語言、區塊鏈後端技術體系、區塊鏈公鏈、區塊鏈分散式應用開發等內容講解,以及到最後的面試指導和項目實戰。課程由清華微軟谷歌名師團隊精心打造,歷時半年時間共同研發而出。


#open-ethereum-pool以太坊礦池-api模塊


##ApiServer相關定義


```go

typeApiConfigstruct{


Enabledbool`json:"enabled"`


Listenstring`json:"listen"`


StatsCollectIntervalstring`json:"statsCollectInterval"`


HashrateWindowstring`json:"hashrateWindow"`


HashrateLargeWindowstring`json:"hashrateLargeWindow"`


LuckWindow[]int`json:"luckWindow"`


Paymentsint64`json:"payments"`


Blocksint64`json:"blocks"`


PurgeOnlybool`json:"purgeOnly"`

PurgeIntervalstring`json:"purgeInterval"`


}


typeApiServerstruct{


config*ApiConfig


backend*storage.RedisClient


hashrateWindowtime.Duration


hashrateLargeWindowtime.Duration


statsatomic.Value


minersmap[string]*Entry


minersMusync.RWMutex

statsIntvtime.Duration


}


typeEntrystruct{


statsmap[string]interface{}


updatedAtint64


}


//代碼位置api/server.go


```


##startApi流程圖


##CollectStats原理

```go


//config.StatsCollectInterval為CollectStats定時器,時間為5秒


//調取:stats,err:=s.backend.CollectStats(s.hashrateWindow,s.config.Blocks,s.config.Payments)


//s.hashrateWindow即cfg.HashrateWindow,即:為每個礦工估計算力的快速時間間隔,30分鐘


//s.config.Blocks即:前端顯示的最大塊數,50個


//s.config.Payments即:前端顯示的最大付款數量,50個


func(r*RedisClient)CollectStats(smallWindowtime.Duration,maxBlocks,maxPaymentsint64)(map[string]interface{},error){


//換算成秒


window:=int64(smallWindow/time.Second)


//創建map

stats:=make(map[string]interface{})


//Redis事務塊


tx:=r.client.Multi()


defertx.Close()


//換算成秒


now:=util.MakeTimestamp()/1000


cmds,err:=tx.Exec(func()error{


//針對min和max參數需要額外說明的是,-inf和+inf分別表示Sorted-Sets中分數的最高值和最低值


//預設情況下,min和max表示的範圍是閉區間範圍,即min<=score<=max內的成員將被返回


//然而我們可以通過在min和max的前面添加"("字元來表示開區間,如(minmax表示min<score<=max,而(min(max表示min<score<max

//-inf<=score<now-window


//Zremrangebyscore命令用於移除有序集中,指定分數(score)區間內的所有成員


//ZREMRANGEBYSCOREeth:hashrate-inf(now-window


//慎重使用


tx.ZRemRangeByScore(r.formatKey("hashrate"),"-inf",fmt.Sprint("(",now-window))


//顯示整個有序集成員


//ZRANGEeth:hashrate0-1WITHSCORES


tx.ZRangeWithScores(r.formatKey("hashrate"),0,-1)


//Hgetall命令用於返回哈希表中,所有的欄位和值


//HGETALLeth:stats

tx.HGetAllMap(r.formatKey("stats"))


//Zrevrange命令返回有序集中,指定區間內的成員


//ZREVRANGEeth:blocks:candidates0-1WITHSCORES


//candidates為候選者


tx.ZRevRangeWithScores(r.formatKey("blocks","candidates"),0,-1)


//同上


//ZREVRANGEeth:blocks:immature0-1WITHSCORES


//immature為未成年


tx.ZRevRangeWithScores(r.formatKey("blocks","immature"),0,-1)


//同上

//ZREVRANGEeth:blocks:matured049WITHSCORES


//matured為成熟


tx.ZRevRangeWithScores(r.formatKey("blocks","matured"),0,maxBlocks-1)


//Zcard命令用於計算集合中元素的數量


//ZCARDeth:blocks:candidates


tx.ZCard(r.formatKey("blocks","candidates"))


//同上


//ZCARDeth:blocks:immature


tx.ZCard(r.formatKey("blocks","immature"))


//同上

//ZCARDeth:blocks:matured


tx.ZCard(r.formatKey("blocks","matured"))


//同上


//ZCARDeth:payments:all


tx.ZCard(r.formatKey("payments","all"))


//同上


//ZREVRANGEeth:payments:all049WITHSCORES


tx.ZRevRangeWithScores(r.formatKey("payments","all"),0,maxPayments-1)


returnnil


})


iferr!=nil{


returnnil,err


}


//Hgetall命令用於返回哈希表中,所有的欄位和值


//HGETALLeth:stats


result,_:=cmds[2].(*redis.StringStringMapCmd).Result()


stats["stats"]=convertStringMap(result)


//Zrevrange命令返回有序集中,指定區間內的成員


//ZREVRANGEeth:blocks:candidates0-1WITHSCORES


//Zcard命令用於計算集合中元素的數量


//ZCARDeth:blocks:candidates


candidates:=convertCandidateResults(cmds[3].(*redis.ZSliceCmd))


stats["candidates"]=candidates


stats["candidatesTotal"]=cmds[6].(*redis.IntCmd).Val()


//ZREVRANGEeth:blocks:immature0-1WITHSCORES


//ZCARDeth:blocks:immature


immature:=convertBlockResults(cmds[4].(*redis.ZSliceCmd))


stats["immature"]=immature


stats["immatureTotal"]=cmds[7].(*redis.IntCmd).Val()


//ZREVRANGEeth:blocks:matured049WITHSCORES


//ZCARDeth:blocks:matured


matured:=convertBlockResults(cmds[5].(*redis.ZSliceCmd))


stats["matured"]=matured


stats["maturedTotal"]=cmds[8].(*redis.IntCmd).Val()


//ZREVRANGEeth:payments:all049WITHSCORES


//ZCARDeth:payments:all


payments:=convertPaymentsResults(cmds[10].(*redis.ZSliceCmd))


stats["payments"]=payments


stats["paymentsTotal"]=cmds[9].(*redis.IntCmd).Val()


//顯示整個有序集成員


//ZRANGEeth:hashrate0-1WITHSCORES


totalHashrate,miners:=convertMinersStats(window,cmds[1].(*redis.ZSliceCmd))


stats["miners"]=miners


stats["minersTotal"]=len(miners)


stats["hashrate"]=totalHashrate


returnstats,nil


}


```


##CollectLuckStats原理


```go


//調取:stats["luck"],err=s.backend.CollectLuckStats(s.config.LuckWindow)


//"luckWindow":[64,128,256],


//Collectstatsforshares/diffratioforthisnumberofblocks


func(r*RedisClient)CollectLuckStats(windows[]int)(map[string]interface{},error){


//創建statsmap


stats:=make(map[string]interface{})


tx:=r.client.Multi()


defertx.Close()


//max即256


max:=int64(windows[len(windows)-1])


cmds,err:=tx.Exec(func()error{


//Zrevrange命令返回有序集中,指定區間內的成員


//ZREVRANGEeth:blocks:immature0-1WITHSCORES


tx.ZRevRangeWithScores(r.formatKey("blocks","immature"),0,-1)


//ZREVRANGEeth:blocks:matured0max-1WITHSCORES


tx.ZRevRangeWithScores(r.formatKey("blocks","matured"),0,max-1)


returnnil


})


iferr!=nil{


returnstats,err


}


//獲取blocks


blocks:=convertBlockResults(cmds[0].(*redis.ZSliceCmd),cmds[1].(*redis.ZSliceCmd))


calcLuck:=func(maxint)(int,float64,float64,float64){


vartotalint


varsharesDiff,uncles,orphansfloat64


fori,block:=rangeblocks{


ifi>(max-1){


break


}


//叔塊


ifblock.Uncle{


uncles++


}


//孤塊


ifblock.Orphan{


orphans++


}


//shares/Diff


sharesDiff+=float64(block.TotalShares)/float64(block.Difficulty)


//total計數


total++


}


iftotal>0{


//單塊平均shares/Diff


sharesDiff/=float64(total)


//uncles率


uncles/=float64(total)


//孤塊率


orphans/=float64(total)


}


//返回total計數,平均shares/Diff,uncles率,孤塊率


returntotal,sharesDiff,uncles,orphans


}


//遍歷windows,逐一計算calcLuck,即最近64塊、128塊、256塊的數據統計


for_,max:=rangewindows{


total,sharesDiff,uncleRate,orphanRate:=calcLuck(max)


row:=map[string]float64{


"luck":sharesDiff,"uncleRate":uncleRate,"orphanRate":orphanRate,


}


//寫入statsmap


stats[strconv.Itoa(total)]=row


//計數不對


iftotal<max{


break


}


}


returnstats,nil


}


funcconvertBlockResults(rows...*redis.ZSliceCmd)[]*BlockData{


varresult[]*BlockData


//遍歷rows


for_,row:=rangerows{


//遍歷blocks


for_,v:=rangerow.Val(){


//"uncleHeight:orphan:nonce:blockHash:timestamp:diff:totalShares:rewardInWei"


block:=BlockData{}


block.Height=int64(v.Score)


block.RoundHeight=block.Height


fields:=strings.Split(v.Member.(string),":")


block.UncleHeight,_=strconv.ParseInt(fields[0],10,64)


block.Uncle=block.UncleHeight>0


block.Orphan,_=strconv.ParseBool(fields[1])


block.Nonce=fields[2]


block.Hash=fields[3]


block.Timestamp,_=strconv.ParseInt(fields[4],10,64)


block.Difficulty,_=strconv.ParseInt(fields[5],10,64)


block.TotalShares,_=strconv.ParseInt(fields[6],10,64)


block.RewardString=fields[7]


block.ImmatureReward=fields[7]


block.immatureKey=v.Member.(string)


result=append(result,&block)


}


}


returnresult


}


```


##purgeStale原理


```go


//config.PurgeInterval為FlushStaleStats定時器,時間為10分鐘


//調取:total,err:=s.backend.FlushStaleStats(s.hashrateWindow,s.hashrateLargeWindow)


//s.hashrateWindow即cfg.HashrateWindow,即:為每個礦工估計算力的快速時間間隔,30分鐘


//s.hashrateLargeWindow即cfg.HashrateLargeWindow,即:長期和精確的hashrate時間間隔,3小時


func(r*RedisClient)FlushStaleStats(window,largeWindowtime.Duration)(int64,error){


//換算成秒


now:=util.MakeTimestamp()/1000


//max即(now-window,即<(now-window


max:=fmt.Sprint("(",now-int64(window/time.Second))


//Zremrangebyscore命令用於移除有序集中,指定分數(score)區間內的所有成員


//ZREMRANGEBYSCOREeth:hashrate-inf(now-window


//慎重使用


total,err:=r.client.ZRemRangeByScore(r.formatKey("hashrate"),"-inf",max).Result()


iferr!=nil{


returntotal,err


}


varcint64


//創建map


miners:=make(map[string]struct{})


//即(now-largeWindow,即<now-largeWindow


max=fmt.Sprint("(",now-int64(largeWindow/time.Second))


for{


varkeys[]string


varerrerror


//SCAN命令用於迭代當前資料庫中的資料庫鍵


//SCAN0MATCHeth:hashrate:*COUNT100


//SCANcMATCHeth:hashrate:*COUNT100


c,keys,err=r.client.Scan(c,r.formatKey("hashrate","*"),100).Result()


iferr!=nil{


returntotal,err


}


for_,row:=rangekeys{


//eth:hashrate:login中截取login


login:=strings.Split(row,":")[2]


//沒有處理過miners[login]


if_,ok:=miners[login];!ok{


//Zremrangebyscore命令用於移除有序集中,指定分數(score)區間內的所有成員


//ZREMRANGEBYSCOREeth:hashrate:login-inf(now-window


n,err:=r.client.ZRemRangeByScore(r.formatKey("hashrate",login),"-inf",max).Result()


iferr!=nil{


returntotal,err


}


//已處理的計入miners[login]


miners[login]=struct{}{}


//已處理的數量


total+=n


}


}


ifc==0{


break


}


}


returntotal,nil


}


```

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 兄弟連IT教育 的精彩文章:

TAG:兄弟連IT教育 |