Commit 23daf4d4 authored by Sergei Zubov's avatar Sergei Zubov

Add DeStream fee to transactions

Fee is calculated based on fixed rate and splits up between miner and
DeStream wallet. Fee and split rates are network parameters.
Fee check is disabled, DeStream don't have minimal or maximal fee.
Funds are sent to DeStream wallet via additional output of CoinStake
transaction.
parent afa4ab6b
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Company>NStratis</Company> <Company>NStratis</Company>
<Copyright>Copyright © Stratis Platform SA 2017</Copyright> <Copyright>Copyright © Stratis Platform SA 2017</Copyright>
<Description>The C# Bitcoin Library based on NBitcoin</Description> <Description>The C# Bitcoin Library based on NBitcoin</Description>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Version>4.0.0.54</Version> <Version>4.0.0.54</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>NBitcoin</RootNamespace> <RootNamespace>NBitcoin</RootNamespace>
...@@ -17,30 +14,24 @@ ...@@ -17,30 +14,24 @@
<Authors>NStratis</Authors> <Authors>NStratis</Authors>
<Product>NStratis</Product> <Product>NStratis</Product>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_6;NETCORE;NOSTRNORMALIZE;NOCUSTOMSSLVALIDATION;</DefineConstants> <DefineConstants>TRACE;DEBUG;NETSTANDARD1_6;NETCORE;NOSTRNORMALIZE;NOCUSTOMSSLVALIDATION;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;NETSTANDARD1_6;NETCORE;NOSTRNORMALIZE;NOCUSTOMSSLVALIDATION;</DefineConstants> <DefineConstants>TRACE;NETSTANDARD1_6;NETCORE;NOSTRNORMALIZE;NOCUSTOMSSLVALIDATION;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Protocol\Payloads\**" /> <Compile Remove="Protocol\Payloads\**" />
<EmbeddedResource Remove="Protocol\Payloads\**" /> <EmbeddedResource Remove="Protocol\Payloads\**" />
<None Remove="Protocol\Payloads\**" /> <None Remove="Protocol\Payloads\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Protocol\AddressManager.cs" /> <Compile Remove="Protocol\AddressManager.cs" />
<Compile Remove="Protocol\NodesGroup.cs" /> <Compile Remove="Protocol\NodesGroup.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="BitcoinStream.Partial.tt" /> <None Remove="BitcoinStream.Partial.tt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NStratis.HashLib" Version="1.0.0.1" /> <PackageReference Include="NStratis.HashLib" Version="1.0.0.1" />
...@@ -51,9 +42,7 @@ ...@@ -51,9 +42,7 @@
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" /> <PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.Threading.Thread" Version="4.3.0" /> <PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" /> <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup> </ItemGroup>
</Project> </Project>
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using NBitcoin.BouncyCastle.Math; using NBitcoin.BouncyCastle.Math;
using NBitcoin.DataEncoders; using NBitcoin.DataEncoders;
namespace NBitcoin
{
public abstract partial class Network
{
// TODO: Implement custom circular collection
public readonly IReadOnlyCollection<string> DeStreamWallets = new ReadOnlyCollection<string>(new List<string>()
{
"DQAa8Fg1ytS5wiXbn1qToRpe9wYSQhCAWc",
"DMoFqYQNfsoorMbmTbyErxk43ev9B2EuEe",
});
/// <summary>
///
/// </summary>
public double DeStreamFeePart { get; set; }
/// <summary>
/// Fee applied to all transactions
/// </summary>
public double FeeRate { get; set; }
}
}
namespace NBitcoin.Networks namespace NBitcoin.Networks
{ {
public class DeStreamMain : Network public class DeStreamMain : Network
......
...@@ -12,16 +12,16 @@ namespace NBitcoin.Networks ...@@ -12,16 +12,16 @@ namespace NBitcoin.Networks
public DeStreamTest() //: base() public DeStreamTest() //: base()
{ {
var initialWalletAddresses = new []{ var initialWalletAddresses = new []{
"TWyLf11aUSQvorSvG4oc3asMGXbqkf8MEa", "DC6UcLUzq645UeqCkdk4iJk9tvMVDQ2Ytd",
"TSX8RGmEod8K4a2SvPPWZtmJ5KtrBzzXSw", "D9CKCEtU5cJ5BReBwf4YnWpSqcC7tr1oXv",
"TTp1D1NrV1uwbuL2YvWm46M3xY8nYQLRHr", "DU3cTLWubkzMRGoCSef1G1Jp1tj8z9TGPD",
"TBgvA3dKhGMGeWXpzCG9UUviXLFjZjsQ2S", "D95x2iYdVVUwY5RnPjBmDKiJHToTgHhdor",
"TV37E8whdDUEzVFSsWRHHcj7bWbeDTv9gw", "DPPnSDe416McZ2CKgmUagnJwXZuZ8b31ZM",
"TWyiGrPmuKvcMj9s9SGR4BWzMxhZQXJxZk", "DHdc7gkwZRpKPTZzEf8TBQEthmfxuAJoUM",
"TNL98Epf3ASKFod2QuincwNi2CxHLkkjMD", "DJzLTGxadMGnHqByQtyUW3zsLq5f7mSvJz",
"TG3N5ARtJaajqdNHgC9pxnW5kL9CeWkcDa", "D7UwtqLsCNkKb94tb6TiagUHRgF4UDEXMt",
"TA9GwihBb9KcW3evjxdVkUh1XdQ5wbEcif", "D7a8q2Ldfmh1vBaGrANPFwyKU7oNKBRtQH",
"TBxudKvSsw1hL7aGf9a34dSdxV4e97dx5y" "DDmLwBBEoerPy8nZCAxcoyzwGwBs9zUhFq"
}; };
const decimal initialCoins = 6000000000; const decimal initialCoins = 6000000000;
...@@ -52,13 +52,16 @@ namespace NBitcoin.Networks ...@@ -52,13 +52,16 @@ namespace NBitcoin.Networks
this.Consensus.LastPOWBlock = 12500; this.Consensus.LastPOWBlock = 12500;
this.Consensus.DefaultAssumeValid = this.Consensus.DefaultAssumeValid =
new uint256("0x98fa6ef0bca5b431f15fd79dc6f879dc45b83ed4b1bbe933a383ef438321958e"); // 372652 new uint256("0x98fa6ef0bca5b431f15fd79dc6f879dc45b83ed4b1bbe933a383ef438321958e"); // 372652
this.Consensus.CoinbaseMaturity = 10; this.Consensus.CoinbaseMaturity = 1;
this.Consensus.MaxMoney = long.MaxValue; this.Consensus.MaxMoney = long.MaxValue;
this.Consensus.ProofOfWorkReward = Money.Zero; this.Consensus.ProofOfWorkReward = Money.Zero;
this.Consensus.ProofOfStakeReward = Money.COIN; this.Consensus.ProofOfStakeReward = Money.Zero;
this.Consensus.LastPOWBlock = 12500; this.Consensus.LastPOWBlock = 12500;
this.Consensus.CoinType = 3564; this.Consensus.CoinType = 3564;
this.DeStreamFeePart = 0.9;
this.FeeRate = 0.0077;
this.Base58Prefixes[(int) Base58Type.PUBKEY_ADDRESS] = new byte[] {30}; this.Base58Prefixes[(int) Base58Type.PUBKEY_ADDRESS] = new byte[] {30};
this.Base58Prefixes[(int) Base58Type.SCRIPT_ADDRESS] = new byte[] {90}; this.Base58Prefixes[(int) Base58Type.SCRIPT_ADDRESS] = new byte[] {90};
this.Base58Prefixes[(int) Base58Type.SECRET_KEY] = new byte[] {30 + 90}; this.Base58Prefixes[(int) Base58Type.SECRET_KEY] = new byte[] {30 + 90};
......
...@@ -16,7 +16,7 @@ namespace NBitcoin.Policy ...@@ -16,7 +16,7 @@ namespace NBitcoin.Policy
// TODO: replace fee params with whats in Network. // TODO: replace fee params with whats in Network.
this.MaxTxFee = new FeeRate(Money.Coins(0.1m)); this.MaxTxFee = new FeeRate(Money.Coins(0.1m));
this.MinRelayTxFee = new FeeRate(Money.Satoshis(5000)); // TODO: new FeeRate(Money.Satoshis(network.MinRelayTxFee)); this.MinRelayTxFee = new FeeRate(Money.Satoshis(5000)); // TODO: new FeeRate(Money.Satoshis(network.MinRelayTxFee));
this.CheckFee = true; this.CheckFee = false;
this.CheckScriptPubKey = true; this.CheckScriptPubKey = true;
} }
......
This diff is collapsed.
...@@ -250,7 +250,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -250,7 +250,7 @@ namespace Stratis.Bitcoin.Features.Miner
.FeatureServices(services => .FeatureServices(services =>
{ {
services.AddSingleton<IPowMining, PowMining>(); services.AddSingleton<IPowMining, PowMining>();
services.AddSingleton<IPosMinting, PosMinting>(); services.AddSingleton<IPosMinting, DeStreamPosMinting>();
services.AddSingleton<IBlockProvider, BlockProvider>(); services.AddSingleton<IBlockProvider, BlockProvider>();
services.AddSingleton<BlockDefinition, PowBlockDefinition>(); services.AddSingleton<BlockDefinition, PowBlockDefinition>();
services.AddSingleton<BlockDefinition, PosBlockDefinition>(); services.AddSingleton<BlockDefinition, PosBlockDefinition>();
......
...@@ -198,16 +198,16 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -198,16 +198,16 @@ namespace Stratis.Bitcoin.Features.Miner
/// <summary>Number of UTXO descriptions that a single worker's task will process.</summary> /// <summary>Number of UTXO descriptions that a single worker's task will process.</summary>
/// <remarks>To achieve a good level of parallelism, this should be low enough so that CPU threads are used, /// <remarks>To achieve a good level of parallelism, this should be low enough so that CPU threads are used,
/// but high enough to compensate for tasks' overhead.</remarks> /// but high enough to compensate for tasks' overhead.</remarks>
private const int UtxoStakeDescriptionsPerCoinstakeWorker = 25; protected const int UtxoStakeDescriptionsPerCoinstakeWorker = 25;
/// <summary>Consumes incoming blocks, validates and executes them.</summary> /// <summary>Consumes incoming blocks, validates and executes them.</summary>
private readonly IConsensusLoop consensusLoop; protected readonly IConsensusLoop consensusLoop;
/// <summary>Thread safe access to the best chain of block headers (that the node is aware of) from genesis.</summary> /// <summary>Thread safe access to the best chain of block headers (that the node is aware of) from genesis.</summary>
private readonly ConcurrentChain chain; private readonly ConcurrentChain chain;
/// <summary>Specification of the network the node runs on - regtest/testnet/mainnet.</summary> /// <summary>Specification of the network the node runs on - regtest/testnet/mainnet.</summary>
private readonly Network network; protected readonly Network network;
/// <summary>Provider of information about the node's connection to it's network peers.</summary> /// <summary>Provider of information about the node's connection to it's network peers.</summary>
/// <remarks>Used to verify that node is connected to network before we start staking.</remarks> /// <remarks>Used to verify that node is connected to network before we start staking.</remarks>
...@@ -232,13 +232,13 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -232,13 +232,13 @@ namespace Stratis.Bitcoin.Features.Miner
private readonly IAsyncLoopFactory asyncLoopFactory; private readonly IAsyncLoopFactory asyncLoopFactory;
/// <summary>A manager providing operations on wallets.</summary> /// <summary>A manager providing operations on wallets.</summary>
private readonly IWalletManager walletManager; protected readonly IWalletManager walletManager;
/// <summary>Factory for creating loggers.</summary> /// <summary>Factory for creating loggers.</summary>
private readonly ILoggerFactory loggerFactory; protected readonly ILoggerFactory loggerFactory;
/// <summary>Instance logger.</summary> /// <summary>Instance logger.</summary>
private readonly ILogger logger; protected readonly ILogger logger;
/// <summary>Loop in which the node attempts to generate new POS blocks by staking coins from its wallet.</summary> /// <summary>Loop in which the node attempts to generate new POS blocks by staking coins from its wallet.</summary>
private IAsyncLoop stakingLoop; private IAsyncLoop stakingLoop;
...@@ -256,7 +256,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -256,7 +256,7 @@ namespace Stratis.Bitcoin.Features.Miner
/// Target reserved balance that will not participate in staking. /// Target reserved balance that will not participate in staking.
/// It is possible that less than this amount will be reserved. /// It is possible that less than this amount will be reserved.
/// </summary> /// </summary>
private Money targetReserveBalance; protected Money targetReserveBalance;
/// <summary>Time in milliseconds between attempts to generate PoS blocks.</summary> /// <summary>Time in milliseconds between attempts to generate PoS blocks.</summary>
private readonly int minerSleep; private readonly int minerSleep;
...@@ -273,10 +273,10 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -273,10 +273,10 @@ namespace Stratis.Bitcoin.Features.Miner
/// <summary>Information about node's staking for RPC "getstakinginfo" command.</summary> /// <summary>Information about node's staking for RPC "getstakinginfo" command.</summary>
/// <remarks>This object does not need a synchronized access because there is no execution logic /// <remarks>This object does not need a synchronized access because there is no execution logic
/// that depends on the reported information.</remarks> /// that depends on the reported information.</remarks>
private Models.GetStakingInfoModel rpcGetStakingInfoModel; protected Models.GetStakingInfoModel rpcGetStakingInfoModel;
/// <summary>Estimation of the total staking weight of all nodes on the network.</summary> /// <summary>Estimation of the total staking weight of all nodes on the network.</summary>
private long networkWeight; protected long networkWeight;
/// <summary> /// <summary>
/// Timestamp of the last attempt to search for POS solution. /// Timestamp of the last attempt to search for POS solution.
...@@ -695,7 +695,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -695,7 +695,7 @@ namespace Stratis.Bitcoin.Features.Miner
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task<bool> CreateCoinstakeAsync(List<UtxoStakeDescription> utxoStakeDescriptions, Block block, ChainedHeader chainTip, long searchInterval, long fees, CoinstakeContext coinstakeContext) public virtual async Task<bool> CreateCoinstakeAsync(List<UtxoStakeDescription> utxoStakeDescriptions, Block block, ChainedHeader chainTip, long searchInterval, long fees, CoinstakeContext coinstakeContext)
{ {
this.logger.LogTrace("({0}.{1}:{2},{3}:'{4}',{5}:{6},{7}:{8})", nameof(utxoStakeDescriptions), nameof(utxoStakeDescriptions.Count), utxoStakeDescriptions.Count, nameof(chainTip), chainTip, nameof(searchInterval), searchInterval, nameof(fees), fees); this.logger.LogTrace("({0}.{1}:{2},{3}:'{4}',{5}:{6},{7}:{8})", nameof(utxoStakeDescriptions), nameof(utxoStakeDescriptions.Count), utxoStakeDescriptions.Count, nameof(chainTip), chainTip, nameof(searchInterval), searchInterval, nameof(fees), fees);
...@@ -855,7 +855,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -855,7 +855,7 @@ namespace Stratis.Bitcoin.Features.Miner
/// <param name="block">Template of the block that we are trying to mine.</param> /// <param name="block">Template of the block that we are trying to mine.</param>
/// <param name="minimalAllowedTime">Minimal valid timestamp for new coinstake transaction.</param> /// <param name="minimalAllowedTime">Minimal valid timestamp for new coinstake transaction.</param>
/// <param name="searchInterval">Length of an unexplored block time space in seconds. It only makes sense to look for a solution within this interval.</param> /// <param name="searchInterval">Length of an unexplored block time space in seconds. It only makes sense to look for a solution within this interval.</param>
private void CoinstakeWorker(CoinstakeWorkerContext context, ChainedHeader chainTip, Block block, long minimalAllowedTime, long searchInterval) protected virtual void CoinstakeWorker(CoinstakeWorkerContext context, ChainedHeader chainTip, Block block, long minimalAllowedTime, long searchInterval)
{ {
context.Logger.LogTrace("({0}:'{1}',{2}:{3},{4}:{5})", nameof(chainTip), chainTip, nameof(minimalAllowedTime), minimalAllowedTime, nameof(searchInterval), searchInterval); context.Logger.LogTrace("({0}:'{1}',{2}:{3},{4}:{5})", nameof(chainTip), chainTip, nameof(minimalAllowedTime), minimalAllowedTime, nameof(searchInterval), searchInterval);
...@@ -935,6 +935,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -935,6 +935,7 @@ namespace Stratis.Bitcoin.Features.Miner
utxoStakeInfo.Key = context.CoinstakeContext.Key; utxoStakeInfo.Key = context.CoinstakeContext.Key;
context.CoinstakeContext.CoinstakeTx.Time = txTime; context.CoinstakeContext.CoinstakeTx.Time = txTime;
context.CoinstakeContext.CoinstakeTx.AddInput(new TxIn(prevoutStake)); context.CoinstakeContext.CoinstakeTx.AddInput(new TxIn(prevoutStake));
context.CoinstakeContext.CoinstakeTx.Outputs.Add(new TxOut(0, scriptPubKeyOut)); context.CoinstakeContext.CoinstakeTx.Outputs.Add(new TxOut(0, scriptPubKeyOut));
context.Result.KernelCoin = utxoStakeInfo; context.Result.KernelCoin = utxoStakeInfo;
...@@ -970,7 +971,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -970,7 +971,7 @@ namespace Stratis.Bitcoin.Features.Miner
/// <param name="input">Transaction input.</param> /// <param name="input">Transaction input.</param>
/// <param name="transaction">Transaction being built.</param> /// <param name="transaction">Transaction being built.</param>
/// <returns><c>true</c> if the function succeeds, <c>false</c> otherwise.</returns> /// <returns><c>true</c> if the function succeeds, <c>false</c> otherwise.</returns>
private bool SignTransactionInput(UtxoStakeDescription input, Transaction transaction) protected bool SignTransactionInput(UtxoStakeDescription input, Transaction transaction)
{ {
this.logger.LogTrace("({0}:'{1}')", nameof(input), input.OutPoint); this.logger.LogTrace("({0}:'{1}')", nameof(input), input.OutPoint);
...@@ -1205,7 +1206,7 @@ namespace Stratis.Bitcoin.Features.Miner ...@@ -1205,7 +1206,7 @@ namespace Stratis.Bitcoin.Features.Miner
/// <remarks>The coinstake is split if the number of non-empty UTXOs we have in the wallet /// <remarks>The coinstake is split if the number of non-empty UTXOs we have in the wallet
/// is under the given threshold.</remarks> /// is under the given threshold.</remarks>
/// <seealso cref="CoinstakeSplitLimitMultiplier"/> /// <seealso cref="CoinstakeSplitLimitMultiplier"/>
private bool GetSplitStake(int utxoCount, ChainedHeader chainTip) protected bool GetSplitStake(int utxoCount, ChainedHeader chainTip)
{ {
this.logger.LogTrace("({0}:{1})", nameof(utxoCount), utxoCount); this.logger.LogTrace("({0}:{1})", nameof(utxoCount), utxoCount);
......
...@@ -29,7 +29,7 @@ namespace Stratis.Bitcoin.Features.Wallet ...@@ -29,7 +29,7 @@ namespace Stratis.Bitcoin.Features.Wallet
.FeatureServices(services => .FeatureServices(services =>
{ {
services.AddSingleton<IWalletSyncManager, DeStreamWalletSyncManager>(); services.AddSingleton<IWalletSyncManager, DeStreamWalletSyncManager>();
services.AddSingleton<IWalletTransactionHandler, WalletTransactionHandler>(); services.AddSingleton<IWalletTransactionHandler, DeStreamWalletTransactionHandler>();
services.AddSingleton<IDeStreamWalletManager, DeStreamWalletManager>(); services.AddSingleton<IDeStreamWalletManager, DeStreamWalletManager>();
services.AddSingleton<IWalletManager>(p => p.GetService<IDeStreamWalletManager>()); services.AddSingleton<IWalletManager>(p => p.GetService<IDeStreamWalletManager>());
services.AddSingleton<IWalletFeePolicy, WalletFeePolicy>(); services.AddSingleton<IWalletFeePolicy, WalletFeePolicy>();
......
using System.Linq;
using Microsoft.Extensions.Logging;
using NBitcoin;
using Stratis.Bitcoin.Features.Wallet.Interfaces;
namespace Stratis.Bitcoin.Features.Wallet
{
public class DeStreamWalletTransactionHandler : WalletTransactionHandler
{
public DeStreamWalletTransactionHandler(ILoggerFactory loggerFactory, IWalletManager walletManager,
IWalletFeePolicy walletFeePolicy, Network network) : base(loggerFactory, walletManager, walletFeePolicy,
network)
{
}
/// <inheritdoc />
protected override void AddFee(TransactionBuildContext context)
{
long fee = (long) (context.Recipients.Sum(p => p.Amount) * this.Network.FeeRate);
context.TransactionFee = fee;
context.TransactionBuilder.SendFees(fee);
}
}
}
\ No newline at end of file
...@@ -350,7 +350,7 @@ namespace Stratis.Bitcoin.Features.Wallet ...@@ -350,7 +350,7 @@ namespace Stratis.Bitcoin.Features.Wallet
/// Use the <see cref="FeeRate"/> from the <see cref="walletFeePolicy"/>. /// Use the <see cref="FeeRate"/> from the <see cref="walletFeePolicy"/>.
/// </summary> /// </summary>
/// <param name="context">The context associated with the current transaction being built.</param> /// <param name="context">The context associated with the current transaction being built.</param>
private void AddFee(TransactionBuildContext context) protected virtual void AddFee(TransactionBuildContext context)
{ {
Money fee; Money 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