protected virtual Transaction CreateOutputTransaction() { var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); var tx = new Transaction(); // Distribute funds to configured reward recipients var rewardRecipients = new List <RewardRecipient>(poolConfig.RewardRecipients); foreach (var recipient in rewardRecipients.Where(x => x.Type != RewardRecipientType.Dev && x.Percentage > 0)) { var recipientAddress = BitcoinUtils.AddressToScript(recipient.Address); var recipientReward = new Money((long)Math.Floor(recipient.Percentage / 100.0m * blockReward.Satoshi)); rewardToPool -= recipientReward; tx.AddOutput(recipientReward, recipientAddress); } // Finally distribute remaining funds to pool tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination) { Value = rewardToPool }); // validate it //var checkResult = tx.Check(); //Debug.Assert(checkResult == TransactionCheckResult.Success); return(tx); }
protected virtual Transaction CreateOutputTransaction() { var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); var tx = new Transaction(); // Distribute funds to configured reward recipients var rewardRecipients = new List <RewardRecipient>(poolConfig.RewardRecipients); // Tiny donation to MiningCore developer(s) if (!clusterConfig.DisableDevDonation && networkType == BitcoinNetworkType.Main && KnownAddresses.DevFeeAddresses.ContainsKey(poolConfig.Coin.Type)) { rewardRecipients.Add(new RewardRecipient { Address = KnownAddresses.DevFeeAddresses[poolConfig.Coin.Type], Percentage = 0.2m }); } foreach (var recipient in rewardRecipients.Where(x => x.Percentage > 0)) { var recipientAddress = BitcoinUtils.AddressToScript(recipient.Address); var recipientReward = new Money((long)Math.Floor(recipient.Percentage / 100.0m * blockReward.Satoshi)); rewardToPool -= recipientReward; tx.AddOutput(recipientReward, recipientAddress); } // Finally distribute remaining funds to pool tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination) { Value = rewardToPool }); // validate it //var checkResult = tx.Check(); //Debug.Assert(checkResult == TransactionCheckResult.Success); return(tx); }
protected override async Task PostStartInitAsync() { var commands = new[] { new DaemonCmd(BitcoinCommands.ValidateAddress, new[] { poolConfig.Address }), new DaemonCmd(BitcoinCommands.GetDifficulty), new DaemonCmd(BitcoinCommands.SubmitBlock), new DaemonCmd(BitcoinCommands.GetBlockchainInfo) }; var results = await daemon.ExecuteBatchAnyAsync(commands); if (results.Any(x => x.Error != null)) { var resultList = results.ToList(); var errors = results.Where(x => x.Error != null && commands[resultList.IndexOf(x)].Method != BitcoinCommands.SubmitBlock) .ToArray(); if (errors.Any()) { logger.ThrowLogPoolStartupException($"Init RPC failed: {string.Join(", ", errors.Select(y => y.Error.Message))}", LogCat); } } // extract results var validateAddressResponse = results[0].Response.ToObject <ValidateAddressResponse>(); var difficultyResponse = results[1].Response.ToObject <JToken>(); var submitBlockResponse = results[2]; var blockchainInfoResponse = results[3].Response.ToObject <BlockchainInfo>(); // ensure pool owns wallet if (!validateAddressResponse.IsValid) { logger.ThrowLogPoolStartupException($"Daemon reports pool-address '{poolConfig.Address}' as invalid", LogCat); } if (!validateAddressResponse.IsMine) { logger.ThrowLogPoolStartupException($"Daemon does not own pool-address '{poolConfig.Address}'", LogCat); } isPoS = difficultyResponse.Values().Any(x => x.Path == "proof-of-stake"); // Create pool address script from response if (isPoS) { poolAddressDestination = new PubKey(validateAddressResponse.PubKey); } else { poolAddressDestination = BitcoinUtils.AddressToScript(validateAddressResponse.Address); } // chain detection if (blockchainInfoResponse.Chain.ToLower() == "test") { networkType = BitcoinNetworkType.Test; } else if (blockchainInfoResponse.Chain.ToLower() == "regtest") { networkType = BitcoinNetworkType.RegTest; } else { networkType = BitcoinNetworkType.Main; } ConfigureRewards(); // update stats BlockchainStats.NetworkType = networkType.ToString(); BlockchainStats.RewardType = isPoS ? "POS" : "POW"; // block submission RPC method if (submitBlockResponse.Error?.Message?.ToLower() == "method not found") { hasSubmitBlockMethod = false; } else if (submitBlockResponse.Error?.Code == -1) { hasSubmitBlockMethod = true; } else { logger.ThrowLogPoolStartupException($"Unable detect block submission RPC method", LogCat); } await UpdateNetworkStatsAsync(); SetupCrypto(); SetupJobUpdates(); }