Commit 781d0b29 authored by Sergei Zubov's avatar Sergei Zubov

Modify fee calculations

Splitting fee between miner and DeStream extracted to function.
In consensus, sum of fees of all transactions is split, not each fee.
parent b2b99c47
......@@ -30,6 +30,18 @@ namespace NBitcoin
/// </summary>
public double FeeRate { get; set; }
/// <summary>
/// Splits fee between miner and DeStream
/// </summary>
/// <param name="fee">Total amount of fees to be split</param>
/// <param name="deStreamFee">DeStream fee part</param>
/// <param name="minerReward">Miner fee part</param>
public void SplitFee(long fee, out long deStreamFee, out long minerReward)
{
deStreamFee = Convert.ToInt64(fee * this.DeStreamFeePart);
minerReward = fee - deStreamFee;
}
public bool IsDeStreamAddress(string address)
{
return this.DeStreamWallets.Contains(address);
......
......@@ -35,7 +35,9 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
$"Rule context must be {nameof(DeStreamPowRuleContext)} or {nameof(DeStreamRuleContext)}");
}
if (Math.Abs(actualFee - expectedFee) > 1)
this.Parent.Network.SplitFee(expectedFee, out long expectedDeStreamFee, out long _);
if (actualFee < expectedDeStreamFee)
ConsensusErrors.BadTransactionFeeOutOfRange.Throw();
return Task.CompletedTask;
......@@ -67,13 +69,13 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
private long GetFeeInTransaction(Transaction transaction, Money totalIn,
IEnumerable<Script> changeScriptPubKeys)
{
double feeInTransaction = transaction.Outputs
long feeInTransaction = Convert.ToInt64(transaction.Outputs
.Where(p => !changeScriptPubKeys.Contains(p.ScriptPubKey))
.Sum(p => p.Value) * this.Parent.Network.FeeRate;
.Sum(p => p.Value) * this.Parent.Network.FeeRate);
if (Math.Abs(totalIn.Satoshi - transaction.TotalOut.Satoshi - feeInTransaction) > 1)
ConsensusErrors.BadTransactionFeeOutOfRange.Throw();
return (long) (feeInTransaction * this.Parent.Network.DeStreamFeePart);
return feeInTransaction;
}
}
}
\ No newline at end of file
......@@ -157,16 +157,6 @@ namespace Stratis.Bitcoin.Features.Miner
this.logger.LogTrace("Worker #{0} found the kernel.", workersResult.KernelFoundIndex);
// Get reward for newly created block.
long reward = this.GetReward(fees, chainTip.Height);
if (reward < 0)
{
// TODO: This can't happen unless we remove reward for mined block.
// If this can happen over time then this check could be done much sooner
// to avoid a lot of computation.
this.logger.LogTrace("(-)[NO_REWARD]:false");
return false;
}
// Split stake if above threshold.
this.SplitStake(nonEmptyUtxos, chainTip, coinstakeContext.CoinstakeTx.Outputs);
......@@ -174,11 +164,8 @@ namespace Stratis.Bitcoin.Features.Miner
// Input to coinstake transaction.
UtxoStakeDescription coinstakeInput = workersResult.KernelCoin;
// Total amount of input values in coinstake transaction.
long coinstakeInputValue = coinstakeInput.TxOut.Value + reward;
// Set output amount.
this.SetOutputAmount(coinstakeContext.CoinstakeTx.Outputs, coinstakeInput.TxOut.Value, fees, reward);
this.SetOutputAmount(coinstakeContext.CoinstakeTx.Outputs, coinstakeInput.TxOut.Value, fees);
// Sign.
if (!this.SignTransactionInput(coinstakeInput, coinstakeContext.CoinstakeTx))
......@@ -204,32 +191,27 @@ namespace Stratis.Bitcoin.Features.Miner
return true;
}
private void SetOutputAmount(TxOutList outputs, long totalOut, long fees, long reward)
private void SetOutputAmount(TxOutList outputs, long totalOut, long fees)
{
this.network.SplitFee(fees, out long deStreamFee, out long minerReward);
if (outputs.Count == 4)
{
outputs[1].Value = (totalOut + reward) / 2 / Money.CENT * Money.CENT;
outputs[2].Value = totalOut + reward - outputs[1].Value;
outputs[3].Value = fees - reward;
outputs[1].Value = (totalOut + minerReward) / 2 / Money.CENT * Money.CENT;
outputs[2].Value = totalOut + minerReward - outputs[1].Value;
outputs[3].Value = deStreamFee;
this.logger.LogTrace("Coinstake first output value is {0}, second is {1}, third is {3}.",
outputs[1].Value, outputs[2].Value, outputs[3].Value);
}
else
{
outputs[1].Value = totalOut + reward;
outputs[2].Value = fees - reward;
outputs[1].Value = totalOut + minerReward;
outputs[2].Value = deStreamFee;
this.logger.LogTrace("Coinstake first output value is {0}, second is {1} .", outputs[1].Value,
outputs[2].Value);
}
}
private long GetReward(long fees, int chainTipHeight)
{
return (long) (fees * (1 - this.network.DeStreamFeePart)) +
this.consensusLoop.ConsensusRules.GetRule<PosCoinviewRule>()
.GetProofOfStakeReward(chainTipHeight + 1);
}
private void SplitStake(int nonEmptyUtxos, ChainedHeader chainTip, TxOutList outputs)
{
if (!this.GetSplitStake(nonEmptyUtxos, chainTip)) return;
......
using System.Linq;
using System;
using System.Linq;
using Microsoft.Extensions.Logging;
using NBitcoin;
using NBitcoin.DataEncoders;
......@@ -63,9 +64,9 @@ namespace Stratis.Bitcoin.Features.Miner
// pblocktemplate->CoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
var coinviewRule = this.ConsensusLoop.ConsensusRules.GetRule<CoinViewRule>();
this.coinbase.Outputs[0].Value = (long) (this.fees.Satoshi * (1 - this.Network.DeStreamFeePart)) +
coinviewRule.GetProofOfWorkReward(this.height);
this.coinbase.Outputs[1].Value = (long) (this.fees.Satoshi * this.Network.DeStreamFeePart);
this.Network.SplitFee(this.fees.Satoshi, out long deStreamFee, out long minerReward);
this.coinbase.Outputs[0].Value = minerReward;
this.coinbase.Outputs[1].Value = deStreamFee;
this.BlockTemplate.TotalFee = this.fees;
int nSerializeSize = this.block.GetSerializedSize();
......
using System.Linq;
using System;
using System.Linq;
using Microsoft.Extensions.Logging;
using NBitcoin;
using NBitcoin.DataEncoders;
......@@ -63,9 +64,9 @@ namespace Stratis.Bitcoin.Features.Miner
// pblocktemplate->CoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
var coinviewRule = this.ConsensusLoop.ConsensusRules.GetRule<CoinViewRule>();
this.coinbase.Outputs[0].Value = (long) (this.fees.Satoshi * (1 - this.Network.DeStreamFeePart)) +
coinviewRule.GetProofOfWorkReward(this.height);
this.coinbase.Outputs[1].Value = (long) (this.fees.Satoshi * this.Network.DeStreamFeePart);
this.Network.SplitFee(this.fees.Satoshi, out long deStreamFee, out long minerReward);
this.coinbase.Outputs[0].Value = minerReward;
this.coinbase.Outputs[1].Value = deStreamFee;
this.BlockTemplate.TotalFee = this.fees;
int nSerializeSize = this.block.GetSerializedSize();
......
......@@ -22,7 +22,7 @@ namespace Stratis.Bitcoin.Features.Wallet
/// <inheritdoc />
protected override void AddFee(TransactionBuildContext context)
{
long fee = (long) (context.Recipients.Sum(p => p.Amount) * this.Network.FeeRate);
long fee = Convert.ToInt64(context.Recipients.Sum(p => p.Amount) * this.Network.FeeRate);
context.TransactionFee = fee;
context.TransactionBuilder.SendFees(fee);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment