兄弟连区块链教程open-ethereum-pool矿池源码分析unlocker模块

兄弟连区块链教程open-ethereum-pool以太坊矿池源码分析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原理


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()})
}

原文地址:http://blog.51cto.com/12918475/2287945

时间: 2024-10-05 04:14:52

兄弟连区块链教程open-ethereum-pool矿池源码分析unlocker模块的相关文章

区块链教程btcpool矿池源码分析StratumServer模块解析

兄弟连区块链教程btcpool矿池源码分析StratumServer模块解析 核心机制总结 接收的job延迟超过60秒将丢弃 如果job中prevHash与本地job中prevHash不同,即为已产生新块,job中isClean状态将置为true????* true即要求矿机立即切换job 三种情况下将向矿机下发新job:???? 收到新高度的job???? 过去一个job为新高度且为空块job,且最新job为非空块job????* 达到预定的时间间隔30秒 最近一次下发job的时间将写入文件(

兄弟连区块链教程btcpool矿池源码分析BlockMaker模块解析

btcpool矿池-BlockMaker模块解析 核心机制总结 blkmaker可以连多个bitcoind节点 blkmaker监听和接收4类消息:RAWGBT.STRATUM_JOB.SOLVED_SHARE和NMC_SOLVED_SHARE 监听RAWGBT目的为获取gbtHash/交易列表,用于构建Block,gbtHash和vtxs写入rawGbtMap_??* rawGbtMap_保存最近100条gbtHash/vtxs对 监听STRATUMJOB目的为获取jobId/gbtHash,

兄弟连区块链教程open-ethereum-pool矿池源码分析policy模块

open-ethereum-pooleth矿池-policy模块 PolicyServer定义 type PolicyServer struct { sync.RWMutex statsMu sync.Mutex config *Config stats map[string]*Stats banChannel chan string startedAt int64 grace int64 timeout int64 blacklist []string whitelist []string s

兄弟连区块链教程open-ethereum-pool矿池源码分析payouts模块

open-ethereum-pooleth矿池-payouts模块 PayoutsProcessor定义 type PayoutsProcessor struct { config *PayoutsConfig backend *storage.RedisClient rpc *rpc.RPCClient halt bool lastFail error } GetPendingPayments原理 func (r *RedisClient) GetPendingPayments() []*Pe

兄弟连区块链教程btcpool矿池源码分析JobMaker模块解析

核心机制总结 同时监听kafka KAFKA_TOPIC_RAWGBT和KAFKA_TOPIC_NMC_AUXBLOCK,以支持混合挖矿 接收的Gbt消息,如果与本地时间延迟超过60秒将丢弃,如果延迟超过3秒将打印log 可用的Gbt消息,将以gbtTime+isEmptyBlock+height来构造key写入本地Map,另gbtHash也会写入本地队列 本地gbtHash队列仅保存最近20条,本地gbtMap中Gbt消息有效期:非空Gbt有效期90秒,空Gbt有效期15秒,过期将清除??*

区块链教程open-ethereum-pool矿池源码分析main入口

兄弟连区块链教程open-ethereum-pool矿池源码分析main入口,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁.回归理性,表面上看相关人才需求与身价似乎正在回落.但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上. open-ethereum-pool以太坊矿池-main入口 命令行启动 ./build/bin/open-ethereum-pool config.json config.json配置文件 { ????"threads": 2,

兄弟连区块链教程open-ethereum-pool矿池源码分析环境安装

安装Geth //安装parity cd /tmp/ wget d1h4xl4cr1h0mo.cloudfront.net/v1.8.11/x86_64-unknown-linux-gnu/parity_1.8.11_ubuntu_amd64.deb dpkg -i parity_1.8.11_ubuntu_amd64.deb //安装screen apt-get update apt-get -y install screen //启动parity screen parity --base-p

兄弟连区块链教程btcpool矿池源码分析核心机制总结及优化思考

btcpool矿池-核心机制总结及优化思考 核心机制总结 ①gbtmaker 监听Bitcoind ZMQ中BITCOIND_ZMQ_HASHBLOCK消息,一有新块产生,将立即向kafka发送新Gbt 另默认每5秒间隔(可从配置文件中指定)主动RPC请求Bitcoind,获取Gbt发送给kafka Gbt消息大小约2M,含交易列表 ②jobmaker 同时监听kafka KAFKA_TOPIC_RAWGBT和KAFKA_TOPIC_NMC_AUXBLOCK,以支持混合挖矿 接收的Gbt消息,如

兄弟连区块链教程open-ethereum-pool矿池源码分析API分析

ApiServer相关定义 type ApiConfig struct { Enabled bool `json:"enabled"` Listen string `json:"listen"` StatsCollectInterval string `json:"statsCollectInterval"` HashrateWindow string `json:"hashrateWindow"` HashrateLarge