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">
<PropertyGroup>
<Company>NStratis</Company>
<Copyright>Copyright © Stratis Platform SA 2017</Copyright>
<Description>The C# Bitcoin Library based on NBitcoin</Description>
</PropertyGroup>
<PropertyGroup>
<Version>4.0.0.54</Version>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>NBitcoin</RootNamespace>
......@@ -17,30 +14,24 @@
<Authors>NStratis</Authors>
<Product>NStratis</Product>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_6;NETCORE;NOSTRNORMALIZE;NOCUSTOMSSLVALIDATION;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;NETSTANDARD1_6;NETCORE;NOSTRNORMALIZE;NOCUSTOMSSLVALIDATION;</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Protocol\Payloads\**" />
<EmbeddedResource Remove="Protocol\Payloads\**" />
<None Remove="Protocol\Payloads\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Protocol\AddressManager.cs" />
<Compile Remove="Protocol\NodesGroup.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="BitcoinStream.Partial.tt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NStratis.HashLib" Version="1.0.0.1" />
......@@ -51,9 +42,7 @@
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
</Project>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using NBitcoin.BouncyCastle.Math;
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
{
public class DeStreamMain : Network
......
......@@ -12,16 +12,16 @@ namespace NBitcoin.Networks
public DeStreamTest() //: base()
{
var initialWalletAddresses = new []{
"TWyLf11aUSQvorSvG4oc3asMGXbqkf8MEa",
"TSX8RGmEod8K4a2SvPPWZtmJ5KtrBzzXSw",
"TTp1D1NrV1uwbuL2YvWm46M3xY8nYQLRHr",
"TBgvA3dKhGMGeWXpzCG9UUviXLFjZjsQ2S",
"TV37E8whdDUEzVFSsWRHHcj7bWbeDTv9gw",
"TWyiGrPmuKvcMj9s9SGR4BWzMxhZQXJxZk",
"TNL98Epf3ASKFod2QuincwNi2CxHLkkjMD",
"TG3N5ARtJaajqdNHgC9pxnW5kL9CeWkcDa",
"TA9GwihBb9KcW3evjxdVkUh1XdQ5wbEcif",
"TBxudKvSsw1hL7aGf9a34dSdxV4e97dx5y"
"DC6UcLUzq645UeqCkdk4iJk9tvMVDQ2Ytd",
"D9CKCEtU5cJ5BReBwf4YnWpSqcC7tr1oXv",
"DU3cTLWubkzMRGoCSef1G1Jp1tj8z9TGPD",
"D95x2iYdVVUwY5RnPjBmDKiJHToTgHhdor",
"DPPnSDe416McZ2CKgmUagnJwXZuZ8b31ZM",
"DHdc7gkwZRpKPTZzEf8TBQEthmfxuAJoUM",
"DJzLTGxadMGnHqByQtyUW3zsLq5f7mSvJz",
"D7UwtqLsCNkKb94tb6TiagUHRgF4UDEXMt",
"D7a8q2Ldfmh1vBaGrANPFwyKU7oNKBRtQH",
"DDmLwBBEoerPy8nZCAxcoyzwGwBs9zUhFq"
};
const decimal initialCoins = 6000000000;
......@@ -52,13 +52,16 @@ namespace NBitcoin.Networks
this.Consensus.LastPOWBlock = 12500;
this.Consensus.DefaultAssumeValid =
new uint256("0x98fa6ef0bca5b431f15fd79dc6f879dc45b83ed4b1bbe933a383ef438321958e"); // 372652
this.Consensus.CoinbaseMaturity = 10;
this.Consensus.CoinbaseMaturity = 1;
this.Consensus.MaxMoney = long.MaxValue;
this.Consensus.ProofOfWorkReward = Money.Zero;
this.Consensus.ProofOfStakeReward = Money.COIN;
this.Consensus.ProofOfStakeReward = Money.Zero;
this.Consensus.LastPOWBlock = 12500;
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.SCRIPT_ADDRESS] = new byte[] {90};
this.Base58Prefixes[(int) Base58Type.SECRET_KEY] = new byte[] {30 + 90};
......
......@@ -16,7 +16,7 @@ namespace NBitcoin.Policy
// TODO: replace fee params with whats in Network.
this.MaxTxFee = new FeeRate(Money.Coins(0.1m));
this.MinRelayTxFee = new FeeRate(Money.Satoshis(5000)); // TODO: new FeeRate(Money.Satoshis(network.MinRelayTxFee));
this.CheckFee = true;
this.CheckFee = false;
this.CheckScriptPubKey = true;
}
......
This diff is collapsed.
......@@ -250,7 +250,7 @@ namespace Stratis.Bitcoin.Features.Miner
.FeatureServices(services =>
{
services.AddSingleton<IPowMining, PowMining>();
services.AddSingleton<IPosMinting, PosMinting>();
services.AddSingleton<IPosMinting, DeStreamPosMinting>();
services.AddSingleton<IBlockProvider, BlockProvider>();
services.AddSingleton<BlockDefinition, PowBlockDefinition>();
services.AddSingleton<BlockDefinition, PosBlockDefinition>();
......
......@@ -198,16 +198,16 @@ namespace Stratis.Bitcoin.Features.Miner
/// <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,
/// 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>
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>
private readonly ConcurrentChain chain;
/// <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>
/// <remarks>Used to verify that node is connected to network before we start staking.</remarks>
......@@ -232,13 +232,13 @@ namespace Stratis.Bitcoin.Features.Miner
private readonly IAsyncLoopFactory asyncLoopFactory;
/// <summary>A manager providing operations on wallets.</summary>
private readonly IWalletManager walletManager;
protected readonly IWalletManager walletManager;
/// <summary>Factory for creating loggers.</summary>
private readonly ILoggerFactory loggerFactory;
protected readonly ILoggerFactory loggerFactory;
/// <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>
private IAsyncLoop stakingLoop;
......@@ -256,7 +256,7 @@ namespace Stratis.Bitcoin.Features.Miner
/// Target reserved balance that will not participate in staking.
/// It is possible that less than this amount will be reserved.
/// </summary>
private Money targetReserveBalance;
protected Money targetReserveBalance;
/// <summary>Time in milliseconds between attempts to generate PoS blocks.</summary>
private readonly int minerSleep;
......@@ -273,10 +273,10 @@ namespace Stratis.Bitcoin.Features.Miner
/// <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
/// 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>
private long networkWeight;
protected long networkWeight;
/// <summary>
/// Timestamp of the last attempt to search for POS solution.
......@@ -695,7 +695,7 @@ namespace Stratis.Bitcoin.Features.Miner
}
/// <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);
......@@ -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="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>
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);
......@@ -935,6 +935,7 @@ namespace Stratis.Bitcoin.Features.Miner
utxoStakeInfo.Key = context.CoinstakeContext.Key;
context.CoinstakeContext.CoinstakeTx.Time = txTime;
context.CoinstakeContext.CoinstakeTx.AddInput(new TxIn(prevoutStake));
context.CoinstakeContext.CoinstakeTx.Outputs.Add(new TxOut(0, scriptPubKeyOut));
context.Result.KernelCoin = utxoStakeInfo;
......@@ -970,7 +971,7 @@ namespace Stratis.Bitcoin.Features.Miner
/// <param name="input">Transaction input.</param>
/// <param name="transaction">Transaction being built.</param>
/// <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);
......@@ -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
/// is under the given threshold.</remarks>
/// <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);
......
......@@ -29,7 +29,7 @@ namespace Stratis.Bitcoin.Features.Wallet
.FeatureServices(services =>
{
services.AddSingleton<IWalletSyncManager, DeStreamWalletSyncManager>();
services.AddSingleton<IWalletTransactionHandler, WalletTransactionHandler>();
services.AddSingleton<IWalletTransactionHandler, DeStreamWalletTransactionHandler>();
services.AddSingleton<IDeStreamWalletManager, DeStreamWalletManager>();
services.AddSingleton<IWalletManager>(p => p.GetService<IDeStreamWalletManager>());
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
/// Use the <see cref="FeeRate"/> from the <see cref="walletFeePolicy"/>.
/// </summary>
/// <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;
......
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