From 36f93cb687eff7b7e581ea877c5cbd322105b318 Mon Sep 17 00:00:00 2001 From: Dan Gershony Date: Thu, 27 Jan 2022 22:59:01 +0000 Subject: [PATCH] Enable staking on strax (#379) --- .../Staking/PosMinting.cs | 4 +- .../Blockcore.Networks.Strax.csproj | 1 + .../Staking/StraxMinting.cs | 64 +++++++++++++++++++ .../StakeSplittingTests.cs | 6 +- 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/Networks/Blockcore.Networks.Strax/Staking/StraxMinting.cs diff --git a/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs b/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs index 142562692..f1686b713 100644 --- a/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs +++ b/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs @@ -740,7 +740,7 @@ await Task.Run(() => Parallel.ForEach(workerContexts, cwc => long coinstakeOutputValue = coinstakeInput.TxOut.Value + reward; int eventuallyStakableUtxosCount = utxoStakeDescriptions.Count; - Transaction coinstakeTx = this.PrepareCoinStakeTransactions(chainTip.Height, coinstakeContext, coinstakeOutputValue, eventuallyStakableUtxosCount, ourWeight); + Transaction coinstakeTx = this.PrepareCoinStakeTransactions(chainTip.Height, coinstakeContext, coinstakeOutputValue, eventuallyStakableUtxosCount, ourWeight, reward); if (coinstakeTx is IPosTransactionWithTime posTrxn) { @@ -767,7 +767,7 @@ await Task.Run(() => Parallel.ForEach(workerContexts, cwc => return true; } - internal Transaction PrepareCoinStakeTransactions(int currentChainHeight, CoinstakeContext coinstakeContext, long coinstakeOutputValue, int utxosCount, long amountStaked) + public virtual Transaction PrepareCoinStakeTransactions(int currentChainHeight, CoinstakeContext coinstakeContext, long coinstakeOutputValue, int utxosCount, long amountStaked, long reward) { // Split stake into SplitFactor utxos if above threshold. bool shouldSplitStake = this.ShouldSplitStake(utxosCount, amountStaked, coinstakeOutputValue, currentChainHeight); diff --git a/src/Networks/Blockcore.Networks.Strax/Blockcore.Networks.Strax.csproj b/src/Networks/Blockcore.Networks.Strax/Blockcore.Networks.Strax.csproj index e72d9774f..cf35e7a4f 100644 --- a/src/Networks/Blockcore.Networks.Strax/Blockcore.Networks.Strax.csproj +++ b/src/Networks/Blockcore.Networks.Strax/Blockcore.Networks.Strax.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Networks/Blockcore.Networks.Strax/Staking/StraxMinting.cs b/src/Networks/Blockcore.Networks.Strax/Staking/StraxMinting.cs new file mode 100644 index 000000000..002f883df --- /dev/null +++ b/src/Networks/Blockcore.Networks.Strax/Staking/StraxMinting.cs @@ -0,0 +1,64 @@ +using Blockcore.AsyncWork; +using Blockcore.Base; +using Blockcore.Consensus; +using Blockcore.Consensus.Chain; +using Blockcore.Consensus.TransactionInfo; +using Blockcore.Features.Consensus; +using Blockcore.Features.Consensus.CoinViews; +using Blockcore.Features.Consensus.Interfaces; +using Blockcore.Features.MemoryPool; +using Blockcore.Features.MemoryPool.Interfaces; +using Blockcore.Features.Miner; +using Blockcore.Features.Miner.Staking; +using Blockcore.Features.Wallet.Interfaces; +using Blockcore.Interfaces; +using Blockcore.Mining; +using Blockcore.Networks.Strax.Rules; +using Blockcore.Utilities; +using Microsoft.Extensions.Logging; + + +namespace Blockcore.Networks.Strax.Staking +{ + public class StraxMinting : PosMinting + { + public StraxMinting( + IBlockProvider blockProvider, + IConsensusManager consensusManager, + ChainIndexer chainIndexer, + Network network, + IDateTimeProvider dateTimeProvider, + IInitialBlockDownloadState initialBlockDownloadState, + INodeLifetime nodeLifetime, + ICoinView coinView, + IStakeChain stakeChain, + IStakeValidator stakeValidator, + MempoolSchedulerLock mempoolLock, + ITxMempool mempool, + IWalletManager walletManager, + IAsyncProvider asyncProvider, + ITimeSyncBehaviorState timeSyncBehaviorState, + ILoggerFactory loggerFactory, + MinerSettings minerSettings) : base(blockProvider, consensusManager, chainIndexer, network, dateTimeProvider, + initialBlockDownloadState, nodeLifetime, coinView, stakeChain, stakeValidator, mempoolLock, mempool, + walletManager, asyncProvider, timeSyncBehaviorState, loggerFactory, minerSettings) + { + } + + public override Transaction PrepareCoinStakeTransactions(int currentChainHeight, CoinstakeContext coinstakeContext, long coinstakeOutputValue, int utxosCount, long amountStaked, long reward) + { + long cirrusReward = reward * StraxCoinviewRule.CirrusRewardPercentage / 100; + + coinstakeOutputValue -= cirrusReward; + + // Populate the initial coinstake with the modified overall reward amount, the outputs will be split as necessary + base.PrepareCoinStakeTransactions(currentChainHeight, coinstakeContext, coinstakeOutputValue, utxosCount, amountStaked, reward); + + // Now add the remaining reward into an additional output on the coinstake + var cirrusRewardOutput = new TxOut(cirrusReward, StraxCoinstakeRule.CirrusRewardScript); + coinstakeContext.CoinstakeTx.Outputs.Add(cirrusRewardOutput); + + return coinstakeContext.CoinstakeTx; + } + } +} diff --git a/src/Tests/Blockcore.Features.Miner.Tests/StakeSplittingTests.cs b/src/Tests/Blockcore.Features.Miner.Tests/StakeSplittingTests.cs index b8ae966ac..f4c9b180c 100644 --- a/src/Tests/Blockcore.Features.Miner.Tests/StakeSplittingTests.cs +++ b/src/Tests/Blockcore.Features.Miner.Tests/StakeSplittingTests.cs @@ -141,7 +141,8 @@ public void Given_A_Coin_That_Does_Not_Need_Splitting_CoinstakeTx_Should_Have_On coinstakeContext: coinStakeContext, coinstakeOutputValue: coinstakeInputValue, utxosCount: amounts.Count, - amountStaked: amountStaked); + amountStaked: amountStaked, + reward: (long)reward); return (coinstakeInputValue, transaction); } @@ -194,7 +195,8 @@ private Transaction GetCoinstakeTransaction(List amounts) coinstakeContext: coinStakeContext, coinstakeOutputValue: coinstakeInputValue, utxosCount: amounts.Count, - amountStaked: amounts.Sum(u => u.Satoshi)); + amountStaked: amounts.Sum(u => u.Satoshi), + reward: (long)reward); return transaction; }