open-ethereum-pool以太坊礦池原始碼分析(7)unlocker模組
# open-ethereum-pool以太坊礦池-unlocker模組
## unlocker模組配置
```json
"unlocker": {
"enabled": false,
"poolFee": 1.0,
"poolFeeAddress": "",
"donate": true,
"depth": 120,
"immatureDepth": 20,
"keepTxFees": false,
"interval": "10m",
"daemon": "http://127.0.0.1:8545",
"timeout": "10s"
},
```
## BlockUnlocker定義
```go
type BlockUnlocker struct {
config *UnlockerConfig
backend *storage.RedisClient
rpc *rpc.RPCClient
halt bool
lastFail error
}
```
## unlocker流程圖
## GetCandidates原理
```go
func (r *RedisClient) GetCandidates(maxHeight int64) ([]*BlockData, error) {
//ZRANGEBYSCORE eth:blocks:candidates 0 maxHeight WITHSCORES
option := redis.ZRangeByScore{Min: "0", Max: strconv.FormatInt(maxHeight, 10)}
cmd := r.client.ZRangeByScoreWithScores(r.formatKey("blocks", "candidates"), option)
if cmd.Err() != nil {
return nil, cmd.Err()
}
return convertCandidateResults(cmd), nil
}
func convertCandidateResults(raw *redis.ZSliceCmd) []*BlockData {
var result []*BlockData
for _, v := range raw.Val() {
// "nonce:powHash:mixDigest:timestamp:diff:totalShares"
block := BlockData{}
block.Height = int64(v.Score)
block.RoundHeight = block.Height
fields := strings.Split(v.Member.(string), ":")
block.Nonce = fields[0]
block.PowHash = fields[1]
block.MixDigest = fields[2]
block.Timestamp, _ = strconv.ParseInt(fields[3], 10, 64)
block.Difficulty, _ = strconv.ParseInt(fields[4], 10, 64)
block.TotalShares, _ = strconv.ParseInt(fields[5], 10, 64)
block.candidateKey = v.Member.(string)
result = append(result, &block)
}
return result
}
```
## writeImmatureBlock原理
```go
//Immature即未成年
func (r *RedisClient) writeImmatureBlock(tx *redis.Multi, block *BlockData) {
// Redis 2.8.x returns "ERR source and destination objects are the same"
if block.Height != block.RoundHeight {
//RENAME eth:shares:candidates:round&RoundHeight:nonce eth:shares:candidates:round&blockHeight:nonce
tx.Rename(r.formatRound(block.RoundHeight, block.Nonce), r.formatRound(block.Height, block.Nonce))
}
//Zrem 命令用於移除有序集中的一個或多個成員,不存在的成員將被忽略
//candidates為候選者
//ZREM eth:blocks:candidates nonce:powHash:mixDigest:timestamp:diff:totalShares
tx.ZRem(r.formatKey("blocks", "candidates"), block.candidateKey)
//ZADD eth:blocks:immature block.Height UncleHeight:Orphan:Nonce:serializeHash:Timestamp:Difficulty:TotalShares:Reward
tx.ZAdd(r.formatKey("blocks", "immature"), redis.Z{Score: float64(block.Height), Member: block.key()})
}
func (b *BlockData) key() string {
return join(b.UncleHeight, b.Orphan, b.Nonce, b.serializeHash(), b.Timestamp, b.Difficulty, b.TotalShares, b.Reward)
}
```
## WriteImmatureBlock原理
```go
func (r *RedisClient) WriteImmatureBlock(block *BlockData, roundRewards map[string]int64) error {
tx := r.client.Multi()
defer tx.Close()
_, err := tx.Exec(func() error {
//寫入未成年塊,目的何在?
//補充unlockPendingBlocks()階段,均寫入未成年塊
r.writeImmatureBlock(tx, block)
total := int64(0)
//遍歷roundRewards
for login, amount := range roundRewards {
//求和
total += amount
//Hincrby 命令用於為雜湊表中的欄位值加上指定增量值
//HINCRBY eth:miners:login immature amount
tx.HIncrBy(r.formatKey("miners", login), "immature", amount)
//HSETNX eth:credits:immature:Height:Hash login amount
//Hsetnx 命令用於為雜湊表中不存在的的欄位賦值
tx.HSetNX(r.formatKey("credits", "immature", block.Height, block.Hash), login, strconv.FormatInt(amount, 10))
}
//Hincrby 命令用於為雜湊表中的欄位值加上指定增量值
//HINCRBY eth:finances:immature total
tx.HIncrBy(r.formatKey("finances"), "immature", total)
return nil
})
return err
}
```
## GetImmatureBlocks原理
```go
func (r *RedisClient) GetImmatureBlocks(maxHeight int64) ([]*BlockData, error) {
option := redis.ZRangeByScore{Min: "0", Max: strconv.FormatInt(maxHeight, 10)}
cmd := r.client.ZRangeByScoreWithScores(r.formatKey("blocks", "immature"), option)
if cmd.Err() != nil {
return nil, cmd.Err()
}
return convertBlockResults(cmd), nil
}
func convertBlockResults(rows ...*redis.ZSliceCmd) []*BlockData {
var result []*BlockData
for _, row := range rows {
for _, v := range row.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)
}
}
return result
}
```
## WriteOrphan原理
```
func (r *RedisClient) WriteOrphan(block *BlockData) error {
creditKey := r.formatKey("credits", "immature", block.RoundHeight, block.Hash)
tx, err := r.client.Watch(creditKey)
// Must decrement immatures using existing log entry
immatureCredits := tx.HGetAllMap(creditKey)
if err != nil {
return err
}
defer tx.Close()
_, err = tx.Exec(func() error {
r.writeMaturedBlock(tx, block)
// Decrement immature balances
totalImmature := int64(0)
for login, amountString := range immatureCredits.Val() {
amount, _ := strconv.ParseInt(amountString, 10, 64)
totalImmature += amount
tx.HIncrBy(r.formatKey("miners", login), "immature", (amount * -1))
}
tx.Del(creditKey)
tx.HIncrBy(r.formatKey("finances"), "immature", (totalImmature * -1))
return nil
})
return err
}
func (r *RedisClient) writeMaturedBlock(tx *redis.Multi, block *BlockData) {
tx.Del(r.formatRound(block.RoundHeight, block.Nonce))
tx.ZRem(r.formatKey("blocks", "immature"), block.immatureKey)
tx.ZAdd(r.formatKey("blocks", "matured"), redis.Z{Score: float64(block.Height), Member: block.key()})
}
```
## 參考文件
* [以太坊中的叔塊(uncle block)](http://blog.csdn.net/superswords/article/details/76445278)
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- open-ethereum-pool以太坊礦池原始碼分析(3)payouts模組原始碼
- open-ethereum-pool以太坊礦池原始碼分析(4)-policy模組原始碼
- open-ethereum-pool以太坊礦池原始碼分析(5)proxy模組原始碼
- open-ethereum-pool以太坊礦池原始碼分析(6)-redis模組原始碼Redis
- open-ethereum-pool以太坊礦池原始碼分析(2)API分析原始碼API
- open-ethereum-pool以太坊礦池原始碼分析(1)-main入口分析原始碼AI
- open-ethereum-pool以太坊礦池原始碼分析(1)環境安裝原始碼
- btcpool礦池原始碼分析(7)-sharelogger模組解析TCP原始碼
- 以太坊交易池原始碼分析原始碼
- 以太坊原始碼分析(16)挖礦分析原始碼
- 以太坊原始碼分析(42)miner挖礦部分原始碼分析CPU挖礦原始碼
- 以太坊原始碼分析(26)core-txpool交易池原始碼分析原始碼
- btcpool礦池原始碼分析(3)-BlockMaker模組解析TCP原始碼BloC
- btcpool礦池原始碼分析(4)-GbtMaker模組解析TCP原始碼
- btcpool礦池原始碼分析(5)-JobMaker模組解析TCP原始碼
- btcpool礦池原始碼分析(6)-nmcauxmaker模組解析TCP原始碼UX
- btcpool礦池原始碼分析(6)-PoolWatcher模組解析TCP原始碼
- btcpool礦池原始碼分析(9)-statshttpd模組解析TCP原始碼httpd
- btcpool礦池原始碼分析(10)-StratumServer模組解析TCP原始碼Server
- 死磕以太坊原始碼分析之挖礦流程分析原始碼
- 以太坊交易池原始碼解析原始碼
- 以太坊原始碼分析(7)Ethereum 資源分享原始碼
- 以太坊原始碼分析(37)eth以太坊協議分析原始碼協議
- 以太坊原始碼分析(18)以太坊交易執行分析原始碼
- 以太坊原始碼分析(36)ethdb原始碼分析原始碼
- 以太坊原始碼分析(38)event原始碼分析原始碼
- 以太坊原始碼分析(41)hashimoto原始碼分析原始碼
- 以太坊原始碼分析(43)node原始碼分析原始碼
- 以太坊原始碼分析(51)rpc原始碼分析原始碼RPC
- 以太坊原始碼分析(52)trie原始碼分析原始碼
- 以太坊原始碼分析(13)RPC分析原始碼RPC
- 5.7 以太坊原始碼詳解7原始碼
- 以太坊原始碼分析(52)以太坊fast sync演算法原始碼AST演算法
- 以太坊原始碼分析(1)go-ethereum的設計思路及模組組織形式原始碼Go
- 以太坊原始碼分析(5)accounts程式碼分析原始碼
- 以太坊原始碼分析(8)區塊分析原始碼
- 以太坊原始碼分析(9)cmd包分析原始碼
- 以太坊原始碼分析(35)eth-fetcher原始碼分析原始碼