From b83d16f6095159cf829a731177729f11db75da86 Mon Sep 17 00:00:00 2001 From: Dennis <41244965+DennisAMenace@users.noreply.github.com> Date: Wed, 27 May 2020 19:19:41 -0600 Subject: [PATCH] Added blockmintxfee setting to BlockDefinitionOptions (#133) * Added blockmintxfee setting to BlockDefinitionOptions Added RewardRequired Updated x42 consensus and added MinBlockFeeRate to consensus options. * Updated x42 consensus. * Added additional test node. * Removed RewardRequired and changed the reward check logic. --- src/External/NBitcoin/ConsensusOptions.cs | 4 ++++ .../BlockDefinitionOptions.cs | 5 +++-- .../Blockcore.Features.Miner/MinerSettings.cs | 6 +++++- .../Blockcore.Features.Miner/PowMining.cs | 3 --- .../Staking/PosMinting.cs | 2 +- src/Networks/x42/x42/Networks/x42Main.cs | 3 ++- src/Networks/x42/x42/Networks/x42Test.cs | 15 ++++++++++++++- src/Networks/x42/x42/x42Setup.cs | 8 ++++---- .../Blockcore.IntegrationTests/MinerTests.cs | 6 ++---- 9 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/External/NBitcoin/ConsensusOptions.cs b/src/External/NBitcoin/ConsensusOptions.cs index eb7018a7c..2d87adb9c 100644 --- a/src/External/NBitcoin/ConsensusOptions.cs +++ b/src/External/NBitcoin/ConsensusOptions.cs @@ -19,6 +19,9 @@ public class ConsensusOptions /// The maximum allowed weight for a block, see BIP 141 (network rule) public uint MaxBlockWeight { get; set; } + /// Thee minimum feerate for a transaction in blocks mined. + public long MinBlockFeeRate { get; set; } + /// The maximum allowed size for a serialized block, in bytes (only for buffer size limits). public uint MaxBlockSerializedSize { get; set; } @@ -59,6 +62,7 @@ public ConsensusOptions() // TODO: Remove this constructor. Should always set explicitly. this.MaxBlockSerializedSize = 4000000; this.MaxBlockWeight = 4000000; + this.MinBlockFeeRate = 1000; this.WitnessScaleFactor = 4; this.MaxStandardVersion = 2; this.MaxStandardTxWeight = 400000; diff --git a/src/Features/Blockcore.Features.Miner/BlockDefinitionOptions.cs b/src/Features/Blockcore.Features.Miner/BlockDefinitionOptions.cs index 2385b8bd0..8d0cf43eb 100644 --- a/src/Features/Blockcore.Features.Miner/BlockDefinitionOptions.cs +++ b/src/Features/Blockcore.Features.Miner/BlockDefinitionOptions.cs @@ -20,11 +20,11 @@ public sealed class BlockDefinitionOptions /// Minimum fee rate for transactions to be included in blocks created by miner. public FeeRate BlockMinFeeRate { get; private set; } - public BlockDefinitionOptions(uint blockMaxWeight, uint blockMaxSize) + public BlockDefinitionOptions(uint blockMaxWeight, uint blockMaxSize, int blockMinFeeRate) { this.BlockMaxWeight = blockMaxWeight; this.BlockMaxSize = blockMaxSize; - this.BlockMinFeeRate = new FeeRate(PowMining.DefaultBlockMinTxFee); // TODO: Where should this be set, really? + this.BlockMinFeeRate = new FeeRate(blockMinFeeRate); } /// @@ -36,6 +36,7 @@ public BlockDefinitionOptions RestrictForNetwork(Network network) uint minAllowedBlockWeight = MinBlockSize * (uint) network.Consensus.Options.WitnessScaleFactor; this.BlockMaxWeight = Math.Max(minAllowedBlockWeight, Math.Min(network.Consensus.Options.MaxBlockWeight, this.BlockMaxWeight)); this.BlockMaxSize = Math.Max(MinBlockSize, Math.Min(network.Consensus.Options.MaxBlockSerializedSize, this.BlockMaxSize)); + this.BlockMinFeeRate = new FeeRate(Math.Max(network.Consensus.Options.MinBlockFeeRate, this.BlockMinFeeRate.FeePerK)); return this; } diff --git a/src/Features/Blockcore.Features.Miner/MinerSettings.cs b/src/Features/Blockcore.Features.Miner/MinerSettings.cs index 8fc49a94a..c80631514 100644 --- a/src/Features/Blockcore.Features.Miner/MinerSettings.cs +++ b/src/Features/Blockcore.Features.Miner/MinerSettings.cs @@ -96,8 +96,9 @@ public MinerSettings(NodeSettings nodeSettings) uint blockMaxSize = (uint) config.GetOrDefault("blockmaxsize", (int) nodeSettings.Network.Consensus.Options.MaxBlockSerializedSize, this.logger); uint blockMaxWeight = (uint) config.GetOrDefault("blockmaxweight", (int) nodeSettings.Network.Consensus.Options.MaxBlockWeight, this.logger); + int blockmintxfee = config.GetOrDefault("blockmintxfee", (int)nodeSettings.Network.Consensus.Options.MinBlockFeeRate, this.logger); - this.BlockDefinitionOptions = new BlockDefinitionOptions(blockMaxWeight, blockMaxSize).RestrictForNetwork(nodeSettings.Network); + this.BlockDefinitionOptions = new BlockDefinitionOptions(blockMaxWeight, blockMaxSize, blockmintxfee).RestrictForNetwork(nodeSettings.Network); this.EnableCoinStakeSplitting = config.GetOrDefault("enablecoinstakesplitting", true, this.logger); this.MinimumSplitCoinValue = config.GetOrDefault("minimumsplitcoinvalue", MinimumSplitCoinValueDefaultValue, this.logger); @@ -123,6 +124,7 @@ public static void PrintHelp(Network network) builder.AppendLine("-walletpassword= Password to unlock the wallet."); builder.AppendLine("-blockmaxsize= Maximum block size (in bytes) for the miner to generate."); builder.AppendLine("-blockmaxweight= Maximum block weight (in weight units) for the miner to generate."); + builder.AppendLine("-blockmintxfee= Minimum fee rate for transactions to be included in blocks created by miner."); builder.AppendLine("-enablecoinstakesplitting=<0 or 1> Enable splitting coins when staking. This is true by default."); builder.AppendLine($"-minimumstakingcoinvalue= Minimum size of the coins considered for staking, in satoshis. Default value is {MinimumStakingCoinValueDefaultValue:N0} satoshis (= {MinimumStakingCoinValueDefaultValue / (decimal)Money.COIN:N1} Coin)."); builder.AppendLine($"-minimumsplitcoinvalue= Targeted minimum value of staking coins after splitting, in satoshis. Default value is {MinimumSplitCoinValueDefaultValue:N0} satoshis (= {MinimumSplitCoinValueDefaultValue / Money.COIN} Coin)."); @@ -154,6 +156,8 @@ public static void BuildDefaultConfigurationFile(StringBuilder builder, Network builder.AppendLine($"#blockmaxsize={network.Consensus.Options.MaxBlockSerializedSize}"); builder.AppendLine("#Maximum block weight (in weight units) for the miner to generate."); builder.AppendLine($"#blockmaxweight={network.Consensus.Options.MaxBlockWeight}"); + builder.AppendLine("#Minimum fee rate for transactions to be included in blocks created by miner."); + builder.AppendLine($"#blockmintxfee={network.Consensus.Options.MinBlockFeeRate}"); builder.AppendLine("#Enable splitting coins when staking."); builder.AppendLine("#enablecoinstakesplitting=1"); builder.AppendLine("#Minimum size of the coins considered for staking, in satoshis."); diff --git a/src/Features/Blockcore.Features.Miner/PowMining.cs b/src/Features/Blockcore.Features.Miner/PowMining.cs index 911aea2aa..a0addc333 100644 --- a/src/Features/Blockcore.Features.Miner/PowMining.cs +++ b/src/Features/Blockcore.Features.Miner/PowMining.cs @@ -47,9 +47,6 @@ public class PowMining : IPowMining /// Provider of time functions. private readonly IDateTimeProvider dateTimeProvider; - /// Default for "-blockmintxfee", which sets the minimum feerate for a transaction in blocks created by mining code. - public const int DefaultBlockMinTxFee = 1000; - private uint256 hashPrevBlock; private const int InnerLoopCount = 0x10000; diff --git a/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs b/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs index a0dcf8f28..f057cc43f 100644 --- a/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs +++ b/src/Features/Blockcore.Features.Miner/Staking/PosMinting.cs @@ -719,7 +719,7 @@ await Task.Run(() => Parallel.ForEach(workerContexts, cwc => // Get reward for newly created block. long reward = fees + this.consensusManager.ConsensusRules.GetRule().GetProofOfStakeReward(chainTip.Height + 1); - if (reward <= 0) + 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 diff --git a/src/Networks/x42/x42/Networks/x42Main.cs b/src/Networks/x42/x42/Networks/x42Main.cs index 42d8ec133..b99446ea5 100644 --- a/src/Networks/x42/x42/Networks/x42Main.cs +++ b/src/Networks/x42/x42/Networks/x42Main.cs @@ -31,6 +31,7 @@ public x42Main() maxStandardTxSigopsCost: 20_000 / 5, witnessScaleFactor: 4 ); + consensusOptions.MinBlockFeeRate = Money.Zero; // END MODIFICATIONS CoinSetup setup = x42Setup.Instance.Setup; @@ -109,7 +110,7 @@ public x42Main() minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 500, defaultAssumeValid: null, - maxMoney: long.MaxValue, + maxMoney: Money.Coins(42 * 1000000), coinbaseMaturity: 50, premineHeight: 2, premineReward: Money.Coins(setup.PremineReward), diff --git a/src/Networks/x42/x42/Networks/x42Test.cs b/src/Networks/x42/x42/Networks/x42Test.cs index edd0b5bd1..c5889c49f 100644 --- a/src/Networks/x42/x42/Networks/x42Test.cs +++ b/src/Networks/x42/x42/Networks/x42Test.cs @@ -8,6 +8,7 @@ using NBitcoin.BouncyCastle.Math; using NBitcoin.DataEncoders; using NBitcoin.Protocol; +using x42.Networks.Deployments; namespace x42.Networks { @@ -24,6 +25,7 @@ public x42Test() maxStandardTxSigopsCost: 20_000 / 5, witnessScaleFactor: 4 ); + consensusOptions.MinBlockFeeRate = Money.Zero; // END MODIFICATIONS CoinSetup setup = x42Setup.Instance.Setup; @@ -47,6 +49,10 @@ public x42Test() this.DefaultAPIPort = network.DefaultAPIPort; this.DefaultBanTimeSeconds = 288; // 9 (MaxReorg) * 64 (TargetSpacing) / 2 = 4 hours, 26 minutes and 40 seconds + this.MinTxFee = Money.Zero; + this.FallbackFee = Money.Zero; + this.MinRelayTxFee = Money.Zero; + var consensusFactory = new PosConsensusFactory(); // Create the genesis block. @@ -73,6 +79,13 @@ public x42Test() [BuriedDeployments.BIP66] = 0 }; + var bip9Deployments = new x42BIP9Deployments + { + [x42BIP9Deployments.ColdStaking] = new BIP9DeploymentsParameters("ColdStaking", 27, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultMainnetThreshold), + [x42BIP9Deployments.CSV] = new BIP9DeploymentsParameters("CSV", 0, BIP9DeploymentsParameters.AlwaysActive, 999999999, BIP9DeploymentsParameters.DefaultMainnetThreshold), + [x42BIP9Deployments.Segwit] = new BIP9DeploymentsParameters("Segwit", 1, new DateTime(2020, 3, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2021, 3, 1, 0, 0, 0, DateTimeKind.Utc), BIP9DeploymentsParameters.DefaultMainnetThreshold) + }; + consensusFactory.Protocol = new ConsensusProtocol() { ProtocolVersion = ProtocolVersion.FEEFILTER_VERSION, @@ -89,7 +102,7 @@ public x42Test() majorityRejectBlockOutdated: 950, majorityWindow: 1000, buriedDeployments: buriedDeployments, - bip9Deployments: new NoBIP9Deployments(), + bip9Deployments: bip9Deployments, bip34Hash: null, minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 9, diff --git a/src/Networks/x42/x42/x42Setup.cs b/src/Networks/x42/x42/x42Setup.cs index 7132b2f89..27d1654b7 100644 --- a/src/Networks/x42/x42/x42Setup.cs +++ b/src/Networks/x42/x42/x42Setup.cs @@ -25,7 +25,7 @@ internal class x42Setup ProofOfStakeTimestampMask = 0x0000000F, BlocksWithoutRewards = true, LastProofOfStakeRewardHeight = 12155230, - ProofOfStakeRewardAfterSubsidyLimit = 2, + ProofOfStakeRewardAfterSubsidyLimit = Money.Coins(2), SubsidyLimit = 400000, PoSVersion = 3 }; @@ -50,7 +50,7 @@ internal class x42Setup HashGenesisBlock = "0x04ffe583707a96c1c2eb54af33a4b1dc6d9d8e09fea8c9a7b097ba88f0cb64c4", HashMerkleRoot = "0x6e3439a32382f83dee4f94a6f8bdd38908bcf0c82ec09aba85c5321357f01f67", DNS = new[] { "mainnet1.x42seed.host", "mainnetnode1.x42seed.host", "tech.x42.cloud", "x42.seed.blockcore.net" }, - Nodes = new[] { "34.255.35.42", "52.211.235.48", "63.32.82.169" }, + Nodes = new[] { "34.255.35.42", "52.211.235.48", "63.32.82.169", "18.179.72.204", "15.188.129.215", "18.157.117.214" }, Checkpoints = new Dictionary { { 0, new CheckpointInfo(new uint256("0x04ffe583707a96c1c2eb54af33a4b1dc6d9d8e09fea8c9a7b097ba88f0cb64c4"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, // Genisis @@ -60,7 +60,7 @@ internal class x42Setup { 200000, new CheckpointInfo(new uint256("0xaa276a1c51c025ff1a21fd4b07bfa5d55effc173840e054dd851b20dbb1f2f17"), new uint256("0x63d4bc7b0272703e94ae79103970ea324dc85221e88a51c39a170744848c0cc7")) }, { 300000, new CheckpointInfo(new uint256("0xff72e73ee8f87c0de9bf82c3bb758f4905c3e005493f2ed1faede7c120961750"), new uint256("0x2097fc9edfb8dfe287db45bbce820e168c50be32c9840b1cddf56b297011fc69")) }, { 500000, new CheckpointInfo(new uint256("0x7f9a88ebb32f47090ec37a110c5a05c1162a604dfbfb69c8d492e771cdb63289"), new uint256("0x19db6890c5c934e883bc99eb197509b0a81f19faeefcf49fd7fa6dab83644bfb")) }, - { 634600, new CheckpointInfo(new uint256("0x5c0eb47bc96ba437e6d2550aceaa73ad9a4568110de83380d6a7b5f00aee7308"), new uint256("0x12ef7b665a07cef572c9b8d9ee44f41230d6a65e960d372f9396194ed6f51e53")) } + { 800000, new CheckpointInfo(new uint256("0x981083b047ecf8157a8b2dc24e17ca8cfad01b4e2dabc314df97f3b64fdf37f5"), new uint256("0xf3f0a821801b32c73a7c4f42416ddad3f74b732bd517c968a9b93a33d3684e0b")) } } }; @@ -111,7 +111,7 @@ internal class x42Setup HashGenesisBlock = "0x11bd504102b42b24680d7b4f9b9e9521adc1b690253494d108193cdfcdd2ef0b", HashMerkleRoot = "0x87e7f7df2fbe9fa56c627e59342e0d8142eb5e44c5e5769609059a60f17d0702", DNS = new[] { "testnet1.x42seed.host" }, - Nodes = new[] { "63.32.82.169" }, + Nodes = new[] { "63.32.82.169", "35.155.194.159" }, Checkpoints = new Dictionary { { 0, new CheckpointInfo(new uint256("0x11bd504102b42b24680d7b4f9b9e9521adc1b690253494d108193cdfcdd2ef0b"), new uint256("0x0000000000000000000000000000000000000000000000000000000000000000")) }, // Genisis diff --git a/src/Tests/Blockcore.IntegrationTests/MinerTests.cs b/src/Tests/Blockcore.IntegrationTests/MinerTests.cs index 51db4085b..0e424510e 100644 --- a/src/Tests/Blockcore.IntegrationTests/MinerTests.cs +++ b/src/Tests/Blockcore.IntegrationTests/MinerTests.cs @@ -51,8 +51,6 @@ public class MinerTests private readonly Network network; - private static FeeRate blockMinFeeRate = new FeeRate(PowMining.DefaultBlockMinTxFee); - public static PowBlockDefinition AssemblerForTest(TestContext testContext) { return new PowBlockDefinition(testContext.consensus, testContext.DateTimeProvider, new LoggerFactory(), testContext.mempool, testContext.mempoolLock, new MinerSettings(NodeSettings.Default(testContext.network)), testContext.network, testContext.ConsensusRules, new NodeDeployments(testContext.network, testContext.ChainIndexer)); @@ -312,7 +310,7 @@ public async Task MinerTestPackageSelectionAsync() // Calculate a fee on child transaction that will put the package just // below the block min tx fee (assuming 1 child tx of the same size). - Money feeToUse = blockMinFeeRate.GetFee(2 * freeTxSize) - 1; + Money feeToUse = new FeeRate(this.network.Consensus.Options.MinBlockFeeRate).GetFee(2 * freeTxSize) - 1; tx = context.network.CreateTransaction(tx.ToBytes()); tx.Inputs[0].PrevOut.Hash = hashFreeTx; @@ -354,7 +352,7 @@ public async Task MinerTestPackageSelectionAsync() tx = context.network.CreateTransaction(tx.ToBytes()); tx.Inputs[0].PrevOut.Hash = hashFreeTx2; tx.Outputs.RemoveAt(1); - feeToUse = blockMinFeeRate.GetFee(freeTxSize); + feeToUse = new FeeRate(this.network.Consensus.Options.MinBlockFeeRate).GetFee(freeTxSize); tx.Outputs[0].Value = 5000000000L - 100000000 - feeToUse; uint256 hashLowFeeTx2 = tx.GetHash(); context.mempool.AddUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));