public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig) { extraPoolConfig = poolConfig.Extra.SafeExtensionDataAs <BitcoinPoolConfigExtra>(); base.Configure(poolConfig, clusterConfig); }
public override async Task <decimal> UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, Block block, PoolConfig pool) { var result = await base.UpdateBlockRewardBalancesAsync(con, tx, block, pool); // Transfer entire block reward to z-addr await TransferTransparentPoolBalance(); return(result); }
private Task NotifyPayoutFailureAsync(Balance[] balances, PoolConfig pool, Exception ex) { messageBus.SendMessage(new PaymentNotification(pool.Id, ex.Message, balances.Sum(x => x.Amount), pool.Template.Symbol)); return(Task.FromResult(true)); }
private Task NotifyPayoutFailureAsync(Balance[] balances, PoolConfig pool, Exception ex) { notificationService.NotifyPaymentFailure(pool.Id, balances.Sum(x => x.Amount), ex.Message); return(Task.FromResult(true)); }
public virtual Task <decimal> UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, Block block, PoolConfig pool) { var blockRewardRemaining = block.Reward; // Distribute funds to configured reward recipients foreach (var recipient in poolConfig.RewardRecipients.Where(x => x.Percentage > 0)) { var amount = block.Reward * (recipient.Percentage / 100.0m); var address = recipient.Address; blockRewardRemaining -= amount; // skip transfers from pool wallet to pool wallet if (address != poolConfig.Address) { logger.Info(() => $"Adding {FormatAmount(amount)} to balance of {address}"); balanceRepo.AddAmount(con, tx, poolConfig.Id, poolConfig.Coin.Type, address, amount, $"Reward for block {block.BlockHeight}"); } } return(Task.FromResult(blockRewardRemaining)); }
public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig) { coin = poolConfig.Template.As <BitcoinTemplate>(); base.Configure(poolConfig, clusterConfig); }
private DateTime?CalculateRewards(PoolConfig poolConfig, decimal window, Block block, decimal blockReward, Dictionary <string, double> shares, Dictionary <string, decimal> rewards) { var done = false; var before = block.Created; var inclusive = true; var pageSize = 50000; var currentPage = 0; var accumulatedScore = 0.0m; var blockRewardRemaining = blockReward; DateTime?shareCutOffDate = null; while (!done) { logger.Info(() => $"Fetching page {currentPage} of shares for pool {poolConfig.Id}, block {block.BlockHeight}"); var page = shareReadFaultPolicy.Execute(() => cf.Run(con => shareRepo.ReadSharesBeforeCreated(con, poolConfig.Id, before, inclusive, pageSize))); //, sw, logger)); inclusive = false; currentPage++; for (var i = 0; !done && i < page.Length; i++) { var share = page[i]; if (share.Difficulty == 0 || share.NetworkDifficulty == 0) { logger.Warn(() => $"Found share with 0 difficulty submited by miner {share.Miner} for block {share.BlockHeight}"); continue; } // build address var address = share.Miner; if (!string.IsNullOrEmpty(share.PayoutInfo)) { address += PayoutConstants.PayoutInfoSeperator + share.PayoutInfo; } // record attributed shares for diagnostic purposes if (!shares.ContainsKey(address)) { shares[address] = share.Difficulty; } else { shares[address] += share.Difficulty; } var score = (decimal)(share.Difficulty / share.NetworkDifficulty); // if accumulated score would cross threshold, cap it to the remaining value if (accumulatedScore + score >= window) { score = window - accumulatedScore; shareCutOffDate = share.Created; done = true; } // calulate reward var reward = score * blockReward / window; accumulatedScore += score; blockRewardRemaining -= reward; // this should never happen if (blockRewardRemaining <= 0 && !done) { throw new OverflowException("blockRewardRemaining < 0"); } if (reward > 0) { // accumulate miner reward if (!rewards.ContainsKey(address)) { rewards[address] = reward; } else { rewards[address] += reward; } } } if (page.Length < pageSize) { break; } before = page[page.Length - 1].Created; } logger.Info(() => $"Balance-calculation for pool {poolConfig.Id}, block {block.BlockHeight} completed with accumulated score {accumulatedScore:0.####} ({(accumulatedScore / window) * 100:0.#}%)"); return(shareCutOffDate); }
public static ILogger GetPoolScopedLogger(Type type, PoolConfig poolConfig) { return(LogManager.GetLogger(poolConfig.Id)); }
public override void Init(EquihashBlockTemplate blockTemplate, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, Network network, EquihashSolver solver) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.clock = clock; this.poolAddressDestination = poolAddressDestination; coin = poolConfig.Template.As <EquihashCoinTemplate>(); this.network = network; var equihashTemplate = poolConfig.Template.As <EquihashCoinTemplate>(); networkParams = coin.GetNetwork(network.ChainName); BlockTemplate = blockTemplate; JobId = jobId; Difficulty = (double)new BigRational(networkParams.Diff1BValue, BlockTemplate.Target.HexToReverseByteArray().AsSpan().ToBigInteger()); this.solver = solver; if (!string.IsNullOrEmpty(BlockTemplate.Target)) { blockTargetValue = new uint256(BlockTemplate.Target); } else { var tmp = new Target(BlockTemplate.Bits.HexToByteArray()); blockTargetValue = tmp.ToUInt256(); } previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash .HexToByteArray() .ReverseInPlace() .ToHexString(); BuildCoinbase(); // build tx hashes var txHashes = new List <uint256> { new(coinbaseInitialHash) }; txHashes.AddRange(BlockTemplate.Transactions.Select(tx => new uint256(tx.TxId.HexToReverseByteArray()))); // build merkle root merkleRoot = MerkleNode.GetRoot(txHashes).Hash.ToBytes().ReverseInPlace(); merkleRootReversed = merkleRoot.ReverseInPlace(); merkleRootReversedHex = merkleRootReversed.ToHexString(); jobParams = new object[] { JobId, BlockTemplate.Version.ReverseByteOrder().ToStringHex8(), previousBlockHashReversedHex, merkleRootReversedHex, BlockTemplate.Height.ReverseByteOrder().ToStringHex8() + sha256Empty.Take(28).ToHexString(), // height + hashReserved BlockTemplate.CurTime.ReverseByteOrder().ToStringHex8(), BlockTemplate.Bits.HexToReverseByteArray().ToHexString(), false }; } }
public override async Task ConfigureAsync(ClusterConfig clusterConfig, PoolConfig poolConfig) { await base.ConfigureAsync(clusterConfig, poolConfig); poolExtraConfig = poolConfig.Extra.SafeExtensionDataAs <ZCashPoolConfigExtra>(); }
public async Task <decimal> UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, Block block, PoolConfig pool) { var blockRewardRemaining = block.Reward; // Distribute funds to configured reward recipients foreach (var recipient in poolConfig.RewardRecipients.Where(x => x.Percentage > 0)) { var amount = block.Reward * (recipient.Percentage / 100.0m); var address = recipient.Address; blockRewardRemaining -= amount; // skip transfers from pool wallet to pool wallet if (address != poolConfig.Address) { logger.Info(() => $"Adding {FormatAmount(amount)} to balance of {address}"); await balanceRepo.AddAmountAsync(con, tx, poolConfig.Id, poolConfig.Template.Symbol, address, amount, $"Reward for block {block.BlockHeight}"); } } // Deduct static reserve for tx fees blockRewardRemaining -= EthereumConstants.StaticTransactionFeeReserve; return(blockRewardRemaining); }
public override void Init(ZCashBlockTemplate blockTemplate, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, BitcoinNetworkType networkType, bool isPoS, double shareMultiplier, decimal?blockrewardMultiplier, IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher)); Contract.RequiresNonNull(headerHasher, nameof(headerHasher)); Contract.RequiresNonNull(blockHasher, nameof(blockHasher)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.poolConfig = poolConfig; this.clusterConfig = clusterConfig; this.clock = clock; this.poolAddressDestination = poolAddressDestination; this.networkType = networkType; if (ZCashConstants.Chains.TryGetValue(poolConfig.Coin.Type, out var chain)) { chain.TryGetValue(networkType, out chainConfig); } BlockTemplate = blockTemplate; JobId = jobId; Difficulty = (double)new BigRational(chainConfig.Diff1b, BlockTemplate.Target.HexToByteArray().ReverseArray().ToBigInteger()); txExpiryHeight = blockTemplate.Height + 100; // ZCash Sapling & Overwinter support isSaplingActive = chainConfig.SaplingActivationHeight.HasValue && chainConfig.SaplingTxVersion.HasValue && chainConfig.SaplingTxVersionGroupId.HasValue && chainConfig.SaplingActivationHeight.Value > 0 && blockTemplate.Height >= chainConfig.SaplingActivationHeight.Value; isOverwinterActive = isSaplingActive || chainConfig.OverwinterTxVersion.HasValue && chainConfig.OverwinterTxVersionGroupId.HasValue && chainConfig.OverwinterActivationHeight.HasValue && chainConfig.OverwinterActivationHeight.Value > 0 && blockTemplate.Height >= chainConfig.OverwinterActivationHeight.Value; if (isSaplingActive) { txVersion = chainConfig.SaplingTxVersion.Value; txVersionGroupId = chainConfig.SaplingTxVersionGroupId.Value; } else if (isOverwinterActive) { txVersion = chainConfig.OverwinterTxVersion.Value; txVersionGroupId = chainConfig.OverwinterTxVersionGroupId.Value; } // Misc this.isPoS = isPoS; this.shareMultiplier = shareMultiplier; this.headerHasher = headerHasher; this.blockHasher = blockHasher; this.equihash = chainConfig.Solver(); if (!string.IsNullOrEmpty(BlockTemplate.Target)) { blockTargetValue = new uint256(BlockTemplate.Target); } else { var tmp = new Target(BlockTemplate.Bits.HexToByteArray()); blockTargetValue = tmp.ToUInt256(); } previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash .HexToByteArray() .ReverseArray() .ToHexString(); blockReward = blockTemplate.Subsidy.Miner * BitcoinConstants.SatoshisPerBitcoin; if (chainConfig?.PayFoundersReward == true) { var founders = blockTemplate.Subsidy.Founders ?? blockTemplate.Subsidy.Community; if (!founders.HasValue) { throw new Exception("Error, founders reward missing for block template"); } blockReward = (blockTemplate.Subsidy.Miner + founders.Value) * BitcoinConstants.SatoshisPerBitcoin; } rewardFees = blockTemplate.Transactions.Sum(x => x.Fee); BuildCoinbase(); // build tx hashes var txHashes = new List <uint256> { new uint256(coinbaseInitialHash) }; txHashes.AddRange(BlockTemplate.Transactions.Select(tx => new uint256(tx.Hash.HexToByteArray().ReverseArray()))); // build merkle root merkleRoot = MerkleNode.GetRoot(txHashes).Hash.ToBytes().ReverseArray(); merkleRootReversed = merkleRoot.ReverseArray(); merkleRootReversedHex = merkleRootReversed.ToHexString(); // misc var hashReserved = isSaplingActive && !string.IsNullOrEmpty(blockTemplate.FinalSaplingRootHash) ? blockTemplate.FinalSaplingRootHash.HexToByteArray().ReverseArray().ToHexString() : sha256Empty.ToHexString(); jobParams = new object[] { JobId, BlockTemplate.Version.ReverseByteOrder().ToStringHex8(), previousBlockHashReversedHex, merkleRootReversedHex, hashReserved, BlockTemplate.CurTime.ReverseByteOrder().ToStringHex8(), BlockTemplate.Bits.HexToByteArray().ReverseArray().ToHexString(), false }; }
public override void Configure(PoolConfig pc, ClusterConfig cc) { coin = pc.Template.As <EthereumCoinTemplate>(); base.Configure(pc, cc); }
public static int UpdatePoolConfig(PoolConfig config) { return(SugarBase.DBAutoClose.Updateable(config).ExecuteCommand()); }
/// <inheritdoc /> public override void Configure(PoolConfig poolConfig, ClusterConfig clusterConfig) { poolExtraConfig = poolConfig.Extra.SafeExtensionDataAs <ZCashPoolConfigExtra>(); base.Configure(poolConfig, clusterConfig); }
public virtual void Init(TBlockTemplate blockTemplate, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, SonoNetworkType networkType, bool isPoS, double shareMultiplier, decimal blockrewardMultiplier, IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher)); Contract.RequiresNonNull(headerHasher, nameof(headerHasher)); Contract.RequiresNonNull(blockHasher, nameof(blockHasher)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.poolConfig = poolConfig; this.clusterConfig = clusterConfig; this.clock = clock; this.poolAddressDestination = poolAddressDestination; this.networkType = networkType; BlockTemplate = blockTemplate; JobId = jobId; Difficulty = new Target(new NSono.BouncyCastle.Math.BigInteger(BlockTemplate.Target, 16)).Difficulty; extraNoncePlaceHolderLength = SonoConstants.ExtranoncePlaceHolderLength; this.isPoS = isPoS; this.shareMultiplier = shareMultiplier; this.blockRewardMultiplier = blockrewardMultiplier; this.coinbaseHasher = coinbaseHasher; this.headerHasher = headerHasher; this.blockHasher = blockHasher; if (!string.IsNullOrEmpty(BlockTemplate.Target)) { blockTargetValue = new uint256(BlockTemplate.Target); } else { var tmp = new Target(BlockTemplate.Bits.HexToByteArray()); blockTargetValue = tmp.ToUInt256(); } previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash .HexToByteArray() .ReverseByteOrder() .ToHexString(); BuildMerkleBranches(); BuildCoinbase(); jobParams = new object[] { JobId, previousBlockHashReversedHex, coinbaseInitialHex, coinbaseFinalHex, merkleBranchesHex, BlockTemplate.Version.ToStringHex8(), BlockTemplate.Bits, BlockTemplate.CurTime.ToStringHex8(), false }; }
public override async Task <decimal> UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, Block block, PoolConfig pool) { var blockRewardRemaining = await base.UpdateBlockRewardBalancesAsync(con, tx, block, pool); // Deduct static reserve for tx fees blockRewardRemaining -= EthereumConstants.StaticTransactionFeeReserve; return(blockRewardRemaining); }
public override async Task <decimal> UpdateBlockRewardBalancesAsync(IDbConnection con, IDbTransaction tx, Block block, PoolConfig pool) { await ShieldCoinbaseAsync(); return(await base.UpdateBlockRewardBalancesAsync(con, tx, block, pool)); }
public void Init(PoolConfig poolConfig, double difficulty, VarDiffConfig varDiffConfig, IMasterClock clock) { Difficulty = difficulty; LastActivity = clock.Now; Stats = new ShareStats(); }
private async Task <DateTime?> CalculateRewardsAsync(PoolConfig poolConfig, Block block, decimal blockReward, Dictionary <string, double> shares, Dictionary <string, decimal> rewards) { var done = false; var before = block.Created; var inclusive = true; var pageSize = 50000; var currentPage = 0; var accumulatedScore = 0.0m; var blockRewardRemaining = blockReward; DateTime?shareCutOffDate = null; Dictionary <string, decimal> scores = new Dictionary <string, decimal>(); while (!done) { logger.Info(() => $"Fetching page {currentPage} of shares for pool {poolConfig.Id}, block {block.BlockHeight}"); var page = await shareReadFaultPolicy.ExecuteAsync(() => cf.Run(con => shareRepo.ReadSharesBeforeCreatedAsync(con, poolConfig.Id, before, inclusive, pageSize))); inclusive = false; currentPage++; for (var i = 0; !done && i < page.Length; i++) { var share = page[i]; var address = share.Miner; // record attributed shares for diagnostic purposes if (!shares.ContainsKey(address)) { shares[address] = share.Difficulty; } else { shares[address] += share.Difficulty; } var score = (decimal)(share.Difficulty / share.NetworkDifficulty); if (!scores.ContainsKey(address)) { scores[address] = score; } else { scores[address] += score; } accumulatedScore += score; // set the cutoff date to clean up old shares after a successful payout if (shareCutOffDate == null || share.Created > shareCutOffDate) { shareCutOffDate = share.Created; } } if (page.Length < pageSize) { done = true; break; } before = page[page.Length - 1].Created; done = page.Length <= 0; } if (accumulatedScore > 0) { var rewardPerScorePoint = blockReward / accumulatedScore; // build rewards for all addresses that contributed to the round foreach (var address in scores.Select(x => x.Key).Distinct()) { // loop all scores for the current address foreach (var score in scores.Where(x => x.Key == address)) { var reward = score.Value * rewardPerScorePoint; if (reward > 0) { // accumulate miner reward if (!rewards.ContainsKey(address)) { rewards[address] = reward; } else { rewards[address] += reward; } } blockRewardRemaining -= reward; } } } // this should never happen if (blockRewardRemaining <= 0 && !done) { throw new OverflowException("blockRewardRemaining < 0"); } logger.Info(() => $"Balance-calculation for pool {poolConfig.Id}, block {block.BlockHeight} completed with accumulated score {accumulatedScore:0.####} ({accumulatedScore * 100:0.#}%)"); return(shareCutOffDate); }
public override void Init(ZCashBlockTemplate blockTemplate, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, BitcoinNetworkType networkType, bool isPoS, double shareMultiplier, decimal blockrewardMultiplier, IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher)); Contract.RequiresNonNull(headerHasher, nameof(headerHasher)); Contract.RequiresNonNull(blockHasher, nameof(blockHasher)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.poolConfig = poolConfig; this.clusterConfig = clusterConfig; this.clock = clock; this.poolAddressDestination = poolAddressDestination; this.networkType = networkType; BlockTemplate = blockTemplate; JobId = jobId; Difficulty = (double)new BigRational(ZCashConstants.Diff1b, BlockTemplate.Target.HexToByteArray().ToBigInteger()); this.isPoS = isPoS; this.shareMultiplier = shareMultiplier; this.headerHasher = headerHasher; this.blockHasher = blockHasher; if (!string.IsNullOrEmpty(BlockTemplate.Target)) { blockTargetValue = new uint256(BlockTemplate.Target); } else { var tmp = new Target(BlockTemplate.Bits.HexToByteArray()); blockTargetValue = tmp.ToUInt256(); } previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash .HexToByteArray() .ReverseArray() .ToHexString(); BuildCoinbase(); // build tx hashes var txHashes = new List <uint256> { new uint256(coinbaseInitialHash) }; txHashes.AddRange(BlockTemplate.Transactions.Select(tx => new uint256(tx.TxId.HexToByteArray().ReverseArray()))); // build merkle root merkleRoot = MerkleNode.GetRoot(txHashes).Hash.ToBytes().ReverseArray(); merkleRootReversed = merkleRoot.ReverseArray(); merkleRootReversedHex = merkleRootReversed.ToHexString(); jobParams = new object[] { JobId, BlockTemplate.Version.ReverseByteOrder().ToStringHex8(), previousBlockHashReversedHex, merkleRootReversedHex, BlockTemplate.Height.ReverseByteOrder().ToStringHex8() + sha256Empty.Take(28).ToHexString(), // height + hashReserved BlockTemplate.CurTime.ReverseByteOrder().ToStringHex8(), BlockTemplate.Bits.HexToByteArray().ReverseArray().ToHexString(), false }; }
private WorkerPerformanceStatsContainer[] GetMinerPerformanceInternal(string mode, PoolConfig pool, string address) { Persistence.Model.Projections.WorkerPerformanceStatsContainer[] stats; var end = clock.Now; if (mode == "day" || mode != "month") { // set range if (end.Minute < 30) { end = end.AddHours(-1); } end = end.AddMinutes(-end.Minute); end = end.AddSeconds(-end.Second); var start = end.AddDays(-1); stats = cf.Run(con => statsRepo.GetMinerPerformanceBetweenHourly( con, pool.Id, address, start, end)); } else { if (end.Hour < 12) { end = end.AddDays(-1); } end = end.Date; // set range var start = end.AddMonths(-1); stats = cf.Run(con => statsRepo.GetMinerPerformanceBetweenDaily( con, pool.Id, address, start, end)); } // map var result = mapper.Map <WorkerPerformanceStatsContainer[]>(stats); return(result); }
private WorkerPerformanceStatsContainer[] GetMinerPerformanceInternal(string mode, PoolConfig pool, string address) { Persistence.Model.Projections.WorkerPerformanceStatsContainer[] stats; if (mode == "day" || mode != "month") { // set range #if DEBUG var end = new DateTime(2018, 1, 7, 16, 0, 0); #else var end = clock.Now; // new DateTime(2018, 1, 7, 16, 0, 0); #endif var start = end.AddDays(-1); stats = cf.Run(con => statsRepo.GetMinerPerformanceBetweenHourly( con, pool.Id, address, start, end)); } else { // set range var end = clock.Now; var start = end.AddMonths(-1); stats = cf.Run(con => statsRepo.GetMinerPerformanceBetweenDaily( con, pool.Id, address, start, end)); } // map var result = mapper.Map <WorkerPerformanceStatsContainer[]>(stats); return(result); }
public override void Init(ZCashBlockTemplate blockTemplate, string jobId, PoolConfig poolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, BitcoinNetworkType networkType, bool isPoS, double shareMultiplier, IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher)); Contract.RequiresNonNull(headerHasher, nameof(headerHasher)); Contract.RequiresNonNull(blockHasher, nameof(blockHasher)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.poolConfig = poolConfig; this.clusterConfig = clusterConfig; this.clock = clock; this.poolAddressDestination = poolAddressDestination; this.networkType = networkType; if (ZCashConstants.CoinbaseTxConfig.TryGetValue(poolConfig.Coin.Type, out var coinbaseTx)) { coinbaseTx.TryGetValue(networkType, out coinbaseTxConfig); } BlockTemplate = blockTemplate; JobId = jobId; Difficulty = (double)new BigRational(ZCashConstants.Diff1b, BigInteger.Parse(BlockTemplate.Target, NumberStyles.HexNumber)); this.isPoS = isPoS; this.shareMultiplier = shareMultiplier; this.headerHasher = headerHasher; this.blockHasher = blockHasher; blockTargetValue = BigInteger.Parse("0" + BlockTemplate.Target, NumberStyles.HexNumber); previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash .HexToByteArray() .ReverseArray() .ToHexString(); blockReward = blockTemplate.Subsidy.Miner * BitcoinConstants.SatoshisPerBitcoin; if (coinbaseTxConfig?.PayFoundersReward == true) { var founders = blockTemplate.Subsidy.Founders ?? blockTemplate.Subsidy.Community; if (!founders.HasValue) { throw new Exception("Error, founders reward missing for block template"); } blockReward = (blockTemplate.Subsidy.Miner + founders.Value) * BitcoinConstants.SatoshisPerBitcoin; } rewardFees = blockTemplate.Transactions.Sum(x => x.Fee); BuildCoinbase(); // build tx hashes var txHashes = new List <uint256> { new uint256(coinbaseInitialHash) }; txHashes.AddRange(BlockTemplate.Transactions.Select(tx => new uint256(tx.Hash.HexToByteArray().ReverseArray()))); // build merkle root merkleRoot = MerkleNode.GetRoot(txHashes).Hash.ToBytes().ReverseArray(); merkleRootReversed = merkleRoot.ReverseArray(); merkleRootReversedHex = merkleRootReversed.ToHexString(); jobParams = new object[] { JobId, BlockTemplate.Version.ReverseByteOrder().ToStringHex8(), previousBlockHashReversedHex, merkleRootReversedHex, sha256Empty.ToHexString(), // hashReserved BlockTemplate.CurTime.ReverseByteOrder().ToStringHex8(), BlockTemplate.Bits.HexToByteArray().ReverseArray().ToHexString(), false }; }
public void Init(BlockTemplate blockTemplate, string jobId, PoolConfig poolConfig, BitcoinPoolConfigExtra extraPoolConfig, ClusterConfig clusterConfig, IMasterClock clock, IDestination poolAddressDestination, Network network, bool isPoS, double shareMultiplier, IHashAlgorithm coinbaseHasher, IHashAlgorithm headerHasher, IHashAlgorithm blockHasher) { Contract.RequiresNonNull(blockTemplate, nameof(blockTemplate)); Contract.RequiresNonNull(poolConfig, nameof(poolConfig)); Contract.RequiresNonNull(clusterConfig, nameof(clusterConfig)); Contract.RequiresNonNull(clock, nameof(clock)); Contract.RequiresNonNull(poolAddressDestination, nameof(poolAddressDestination)); Contract.RequiresNonNull(coinbaseHasher, nameof(coinbaseHasher)); Contract.RequiresNonNull(headerHasher, nameof(headerHasher)); Contract.RequiresNonNull(blockHasher, nameof(blockHasher)); Contract.Requires <ArgumentException>(!string.IsNullOrEmpty(jobId), $"{nameof(jobId)} must not be empty"); this.poolConfig = poolConfig; coin = poolConfig.Template.As <BitcoinTemplate>(); networkParams = coin.GetNetwork(network.NetworkType); txVersion = coin.CoinbaseTxVersion; this.network = network; this.clock = clock; this.poolAddressDestination = poolAddressDestination; BlockTemplate = blockTemplate; JobId = jobId; Difficulty = new Target(new NBitcoin.BouncyCastle.Math.BigInteger(BlockTemplate.Target, 16)).Difficulty; extraNoncePlaceHolderLength = BitcoinConstants.ExtranoncePlaceHolderLength; this.isPoS = isPoS; this.shareMultiplier = shareMultiplier; txComment = !string.IsNullOrEmpty(extraPoolConfig?.CoinbaseTxComment) ? extraPoolConfig.CoinbaseTxComment : coin.CoinbaseTxComment; if (coin.HasMasterNodes) { masterNodeParameters = BlockTemplate.Extra.SafeExtensionDataAs <MasterNodeBlockTemplateExtra>(); if (!string.IsNullOrEmpty(masterNodeParameters.CoinbasePayload)) { txVersion = 3; var txType = 5; txVersion = txVersion + ((uint)(txType << 16)); } } if (coin.HasCoinbasePayload) { coinbasepayloadParameters = BlockTemplate.Extra.SafeExtensionDataAs <CoinbasePayloadBlockTemplateExtra>(); } if (coin.HasFounderFee) { FounderParameters = BlockTemplate.Extra.SafeExtensionDataAs <FounderBlockTemplateExtra>(); } if (coin.HasCoinbaseDevReward) { CoinbaseDevRewardParams = BlockTemplate.Extra.SafeExtensionDataAs <CoinbaseDevRewardTemplateExtra>(); } if (coin.HasTreasury) { TreasuryParams = BlockTemplate.Extra.SafeExtensionDataAs <TreasuryTemplateExtra>(); } if (coin.HasPayee) { payeeParameters = BlockTemplate.Extra.SafeExtensionDataAs <PayeeBlockTemplateExtra>(); } this.coinbaseHasher = coinbaseHasher; this.headerHasher = headerHasher; this.blockHasher = blockHasher; if (!string.IsNullOrEmpty(BlockTemplate.Target)) { blockTargetValue = new uint256(BlockTemplate.Target); } else { var tmp = new Target(BlockTemplate.Bits.HexToByteArray()); blockTargetValue = tmp.ToUInt256(); } previousBlockHashReversedHex = BlockTemplate.PreviousBlockhash .HexToByteArray() .ReverseByteOrder() .ToHexString(); BuildMerkleBranches(); BuildCoinbase(); jobParams = new object[] { JobId, previousBlockHashReversedHex, coinbaseInitialHex, coinbaseFinalHex, merkleBranchesHex, BlockTemplate.Version.ToStringHex8(), BlockTemplate.Bits, BlockTemplate.CurTime.ToStringHex8(), false }; }
/* * void LoadPoolGameObjects() * { * PoolConfig poolConfig = new PoolConfig(); * * if (IsStack) * { * PoolGamesObjectsStack = new Dictionary<string, Stack<PoolGameObject>>(); * } * else * { * PoolGamesObjects = new List<PoolGameObject>(); * } * //return; * //foreach (var i in Enumerable.Range(0, 1000)) * foreach (var i in Enumerable.Range(0, poolConfig.LimitField)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabField.ToString(), false); * } * * //------------- * foreach (var i in Enumerable.Range(0, poolConfig.LimitBoss)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabBoss.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabUfo.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitVood)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabVood.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabWallWood.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabWallRock.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabRock.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabElka.ToString(), false); * } * * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabPerson.ToString(), false); * } * foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) * { * indexPool = i; * AddPoolNewTypeObject(SaveLoadData.TypePrefabs.PrefabFlore.ToString(), false); * } * } */ void LoadPoolGamePrefabs() { PoolConfig poolConfig = new PoolConfig(); m_collectionPoolPrefabsStr = new Dictionary <string, GameObject>() { { TypePoolPrefabs.PoolFloor.ToString(), Storage.GridData.PrefabFloor }, { TypePoolPrefabs.PoolFlore.ToString(), Storage.GridData.PrefabFlore }, { TypePoolPrefabs.PoolWood.ToString(), Storage.GridData.PrefabWood }, { TypePoolPrefabs.PoolWall.ToString(), Storage.GridData.PrefabWall }, { TypePoolPrefabs.PoolPerson.ToString(), Storage.GridData.PrefabPerson }, { TypePoolPrefabs.PoolPortal.ToString(), Storage.GridData.PrefabPortal },//#PO# { TypePoolPrefabs.PoolPersonUFO.ToString(), Storage.GridData.PrefabUfo }, { TypePoolPrefabs.PoolPersonBoss.ToString(), Storage.GridData.PrefabBoss }, }; //if (IsStack) //{ PoolGamesObjectsStack = new Dictionary <string, Stack <PoolGameObject> >(); //} //else //{ // PoolGamesObjects = new List<PoolGameObject>(); //} // public GameObject PrefabField; //public GameObject PrefabFlore; //public GameObject PrefabPerson; //public GameObject PrefabWall; //public GameObject PrefabFloor; foreach (var i in Enumerable.Range(0, poolConfig.LimitFloor)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolFloor.ToString()); } foreach (var i in Enumerable.Range(0, poolConfig.LimitFlore)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolFlore.ToString()); } foreach (var i in Enumerable.Range(0, poolConfig.LimitWood)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolWood.ToString()); } foreach (var i in Enumerable.Range(0, poolConfig.LimitWall)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolWall.ToString()); } //------------- foreach (var i in Enumerable.Range(0, poolConfig.LimitNPC)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolPerson.ToString()); } //+++++++ foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolPersonUFO.ToString(), false); } foreach (var i in Enumerable.Range(0, poolConfig.LimitOthers)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolPersonBoss.ToString(), false); } //#PO# foreach (var i in Enumerable.Range(0, poolConfig.LimitPortal)) { indexPool = i; AddPoolNewTypeObject(TypePoolPrefabs.PoolPortal.ToString()); } }