public ThresholdConditionCache(NBitcoin.Consensus consensus) { if (consensus == null) { throw new ArgumentNullException("consensus"); } _Consensus = consensus; }
public ContextInformation(ChainedBlock nextBlock, NBitcoin.Consensus consensus) { Guard.NotNull(nextBlock, nameof(nextBlock)); BestBlock = new ContextBlockInformation(nextBlock.Previous, consensus); Time = DateTimeOffset.UtcNow; NextWorkRequired = nextBlock.GetWorkRequired(consensus); }
public ConsensusValidator(NBitcoin.Consensus consensusParams) { if (consensusParams == null) { throw new ArgumentNullException("consensusParams"); } _ConsensusParams = consensusParams; }
public ContextBlockInformation(ChainedBlock bestBlock, NBitcoin.Consensus consensus) { Guard.NotNull(bestBlock, nameof(bestBlock)); this.Header = bestBlock.Header; this.Height = bestBlock.Height; this.MedianTimePast = bestBlock.GetMedianTimePast(); }
/// <inheritdoc /> public override void Initialize() { this.Logger.LogTrace("()"); this.Consensus = this.Parent.Network.Consensus; this.PowConsensusOptions = this.Parent.Network.Consensus.Option <PowConsensusOptions>(); this.Logger.LogTrace("(-)"); }
public PowConsensusValidator(Network network) { Guard.NotNull(network, nameof(network)); Guard.NotNull(network.Consensus.Option <PowConsensusOptions>(), nameof(network.Consensus.Options)); this.consensusParams = network.Consensus; this.consensusOptions = network.Consensus.Option <PowConsensusOptions>(); this.PerformanceCounter = new ConsensusPerformanceCounter(); }
/// <inheritdoc /> public override void Initialize() { this.Logger.LogTrace("()"); base.Initialize(); this.consensusParams = this.Parent.Network.Consensus; this.Logger.LogTrace("(-)"); }
public ContextInformation(ChainedBlock nextBlock, NBitcoin.Consensus consensus) { if (nextBlock == null) { throw new ArgumentNullException("nextBlock"); } BestBlock = new ContextBlockInformation(nextBlock.Previous, consensus); Time = DateTimeOffset.UtcNow; NextWorkRequired = nextBlock.GetWorkRequired(consensus); }
public ContextBlockInformation(ChainedBlock bestBlock, NBitcoin.Consensus consensus) { if (bestBlock == null) { throw new ArgumentNullException("bestBlock"); } Header = bestBlock.Header; Height = bestBlock.Height; MedianTimePast = bestBlock.GetMedianTimePast(); }
public PowConsensusValidator(Network network, ICheckpoints checkpoints, ILoggerFactory loggerFactory) { Guard.NotNull(network, nameof(network)); Guard.NotNull(network.Consensus.Option <PowConsensusOptions>(), nameof(network.Consensus.Options)); this.logger = loggerFactory.CreateLogger(this.GetType().FullName); this.consensusParams = network.Consensus; this.consensusOptions = network.Consensus.Option <PowConsensusOptions>(); this.PerformanceCounter = new ConsensusPerformanceCounter(); this.checkpoints = checkpoints; }
public RuleContext(ValidationContext validationContext, NBitcoin.Consensus consensus, ChainedHeader consensusTip, DateTimeOffset time) : base() { Guard.NotNull(validationContext, nameof(validationContext)); Guard.NotNull(consensus, nameof(consensus)); this.ValidationContext = validationContext; this.Consensus = consensus; this.ConsensusTip = consensusTip; this.ConsensusTipHeight = consensusTip.Height; this.Time = time; this.MinedBlock = false; }
/// <inheritdoc /> public override void Initialize() { this.Logger.LogTrace("()"); base.Initialize(); this.consensusParams = this.Parent.Network.Consensus; this.generatedTransaction = null; this.refundCounter = 1; this.smartContractParent = (SmartContractConsensusRules)this.Parent; this.Logger.LogTrace("(-)"); }
/// <inheritdoc /> public override void Initialize() { this.Logger.LogTrace("()"); base.Initialize(); this.consensus = this.Parent.Network.Consensus; this.smartContractPosParent = (SmartContractPosConsensusRuleEngine)this.Parent; this.stakeChain = this.smartContractPosParent.StakeChain; this.stakeValidator = this.smartContractPosParent.StakeValidator; this.Logger.LogTrace("(-)"); }
/// <inheritdoc /> public override void Initialize() { this.Logger.LogTrace("()"); base.Initialize(); this.consensus = this.Parent.Network.Consensus; var consensusRules = (PosConsensusRules)this.Parent; this.stakeValidator = consensusRules.StakeValidator; this.stakeChain = consensusRules.StakeChain; this.Logger.LogTrace("(-)"); }
public ContextInformation(BlockValidationContext blockValidationContext, NBitcoin.Consensus consensus) { Guard.NotNull(blockValidationContext, nameof(blockValidationContext)); Guard.NotNull(consensus, nameof(consensus)); this.BlockValidationContext = blockValidationContext; this.Consensus = consensus; // TODO: adding flags to determine the flow of logic is not ideal // a refator is in depbate on moving to a consensus rules engine // this will remove hte need for flags as a validation will // only use the required rules (i.e if the check pow rule will be ommited form the flow) this.CheckPow = true; this.CheckMerkleRoot = true; }
public RuleContext(BlockValidationContext blockValidationContext, NBitcoin.Consensus consensus, ChainedHeader consensusTip) { Guard.NotNull(blockValidationContext, nameof(blockValidationContext)); Guard.NotNull(consensus, nameof(consensus)); this.BlockValidationContext = blockValidationContext; this.Consensus = consensus; this.ConsensusTip = consensusTip; // TODO: adding flags to determine the flow of logic is not ideal // a re-factor is in debate on moving to a consensus rules engine // this will remove the need for flags as validation will only use // the required rules (i.e if the check pow rule will be omitted form the flow) this.CheckPow = true; this.CheckMerkleRoot = true; }
private int ComputeBlockVersion(ChainedHeader prevChainedHeader, NBitcoin.Consensus consensus) { uint version = ThresholdConditionCache.VersionbitsTopBits; var thresholdConditionCache = new ThresholdConditionCache(consensus); IEnumerable <BIP9Deployments> deployments = Enum.GetValues(typeof(BIP9Deployments)).OfType <BIP9Deployments>(); foreach (BIP9Deployments deployment in deployments) { ThresholdState state = thresholdConditionCache.GetState(prevChainedHeader, deployment); if ((state == ThresholdState.LockedIn) || (state == ThresholdState.Started)) { version |= thresholdConditionCache.Mask(deployment); } } return((int)version); }
private int ComputeBlockVersion(ChainedBlock pindexPrev, NBitcoin.Consensus consensus) { var nVersion = ThresholdConditionCache.VERSIONBITS_TOP_BITS; var thresholdConditionCache = new ThresholdConditionCache(consensus); var deploymensts = Enum.GetValues(typeof(BIP9Deployments)) .OfType <BIP9Deployments>(); foreach (var deployment in deploymensts) { var state = thresholdConditionCache.GetState(pindexPrev, deployment); if (state == ThresholdState.LockedIn || state == ThresholdState.Started) { nVersion |= thresholdConditionCache.Mask(deployment); } } return((int)nVersion); }
private int ComputeBlockVersion(ChainedBlock prevChainedBlock, NBitcoin.Consensus consensus) { uint nVersion = ThresholdConditionCache.VERSIONBITS_TOP_BITS; var thresholdConditionCache = new ThresholdConditionCache(consensus); IEnumerable <BIP9Deployments> deploymensts = Enum.GetValues(typeof(BIP9Deployments)) .OfType <BIP9Deployments>(); foreach (BIP9Deployments deployment in deploymensts) { ThresholdState state = thresholdConditionCache.GetState(prevChainedBlock, deployment); if ((state == ThresholdState.LockedIn) || (state == ThresholdState.Started)) { nVersion |= thresholdConditionCache.Mask(deployment); } } return((int)nVersion); }
public CheckPowTransactionRuleTest() { this.consensus = this.network.Consensus; this.options = this.consensus.Option <PowConsensusOptions>(); }
public ConsensusFlags(ChainedBlock nextBlock, ThresholdState[] prevBlockStates, NBitcoin.Consensus chainparams) { // Do not allow blocks that contain transactions which 'overwrite' older transactions, // unless those are already completely spent. // If such overwrites are allowed, coinbases and transactions depending upon those // can be duplicated to remove the ability to spend the first instance -- even after // being sent to another address. // See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information. // This logic is not necessary for memory pool transactions, as AcceptToMemoryPool // already refuses previously-known transaction ids entirely. // This rule was originally applied to all blocks with a timestamp after March 15, 2012, 0:00 UTC. // Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the // two in the chain that violate it. This prevents exploiting the issue against nodes during their // initial block download. this.EnforceBIP30 = (nextBlock.HashBlock == null) || // Enforce on CreateNewBlock invocations which don't have a hash. !((nextBlock.Height == 91842 && nextBlock.HashBlock == new uint256("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || (nextBlock.Height == 91880 && nextBlock.HashBlock == new uint256("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))); // Once BIP34 activated it was not possible to create new duplicate coinbases and thus other than starting // with the 2 existing duplicate coinbase pairs, not possible to create overwriting txs. But by the // time BIP34 activated, in each of the existing pairs the duplicate coinbase had overwritten the first // before the first had been spent. Since those coinbases are sufficiently buried its no longer possible to create further // duplicate transactions descending from the known pairs either. // If we're on the known chain at height greater than where BIP34 activated, we can save the db accesses needed for the BIP30 check. var pindexBIP34height = nextBlock.GetAncestor(chainparams.BuriedDeployments[BuriedDeployments.BIP34]); //Only continue to enforce if we're below BIP34 activation height or the block hash at that height doesn't correspond. this.EnforceBIP30 = this.EnforceBIP30 && (pindexBIP34height == null || !(pindexBIP34height.HashBlock == chainparams.BIP34Hash)); // BIP16 didn't become active until Apr 1 2012 var nBIP16SwitchTime = Utils.UnixTimeToDateTime(1333238400); bool fStrictPayToScriptHash = (nextBlock.Header.BlockTime >= nBIP16SwitchTime); this.ScriptFlags = fStrictPayToScriptHash ? ScriptVerify.P2SH : ScriptVerify.None; // Start enforcing the DERSIG (BIP66) rule if (nextBlock.Height >= chainparams.BuriedDeployments[BuriedDeployments.BIP66]) { this.ScriptFlags |= ScriptVerify.DerSig; } // Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) for block.nVersion=4 // blocks, when 75% of the network has upgraded: if (nextBlock.Height >= chainparams.BuriedDeployments[BuriedDeployments.BIP65]) { this.ScriptFlags |= ScriptVerify.CheckLockTimeVerify; } // Start enforcing BIP68 (sequence locks), BIP112 (CHECKSEQUENCEVERIFY) and BIP113 (Median Time Past) using versionbits logic. if (prevBlockStates[(int)NBitcoin.BIP9Deployments.CSV] == ThresholdState.Active) { this.ScriptFlags |= ScriptVerify.CheckSequenceVerify; this.LockTimeFlags |= Transaction.LockTimeFlags.VerifySequence; this.LockTimeFlags |= Transaction.LockTimeFlags.MedianTimePast; } // Start enforcing WITNESS rules using versionbits logic. if (prevBlockStates[(int)NBitcoin.BIP9Deployments.Segwit] == ThresholdState.Active) { this.ScriptFlags |= ScriptVerify.Witness; } // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height if (nextBlock.Height >= chainparams.BuriedDeployments[BuriedDeployments.BIP34]) { this.EnforceBIP34 = true; } }
private static BigInteger GetProofOfStakeLimit(NBitcoin.Consensus consensus, int height) { return(IsProtocolV2(height) ? consensus.ProofOfStakeLimitV2 : consensus.ProofOfStakeLimit); }
public static Target GetNextTargetRequired(StakeChain stakeChain, ChainedBlock indexLast, NBitcoin.Consensus consensus, bool proofOfStake) { // Genesis block if (indexLast == null) { return(consensus.PowLimit); } // find the last two blocks that correspond to the mining algo // (i.e if this is a POS block we need to find the last two POS blocks) var targetLimit = proofOfStake ? GetProofOfStakeLimit(consensus, indexLast.Height) : consensus.PowLimit.ToBigInteger(); // first block var pindexPrev = GetLastBlockIndex(stakeChain, indexLast, proofOfStake); if (pindexPrev.Previous == null) { return(new Target(targetLimit)); } // second block var pindexPrevPrev = GetLastBlockIndex(stakeChain, pindexPrev.Previous, proofOfStake); if (pindexPrevPrev.Previous == null) { return(new Target(targetLimit)); } int targetSpacing = GetTargetSpacing(indexLast.Height); int actualSpacing = (int)(pindexPrev.Header.Time - pindexPrevPrev.Header.Time); if (IsProtocolV1RetargetingFixed(indexLast.Height)) { if (actualSpacing < 0) { actualSpacing = targetSpacing; } } if (IsProtocolV3((int)indexLast.Header.Time)) { if (actualSpacing > targetSpacing * 10) { actualSpacing = targetSpacing * 10; } } // target change every block // retarget with exponential moving toward target spacing var targetTimespan = 16 * 60; // 16 mins var target = pindexPrev.Header.Bits.ToBigInteger(); int interval = targetTimespan / targetSpacing; target = target.Multiply(BigInteger.ValueOf(((interval - 1) * targetSpacing + actualSpacing + actualSpacing))); target = target.Divide(BigInteger.ValueOf(((interval + 1) * targetSpacing))); if (target.CompareTo(BigInteger.Zero) <= 0 || target.CompareTo(targetLimit) >= 1) { //if (target <= 0 || target > targetLimit) target = targetLimit; } return(new Target(target)); }
public quoxentMain() { CoinSetup setup = quoxentSetup.Instance.Setup; NetworkSetup network = quoxentSetup.Instance.Main; NetworkType = NetworkType.Mainnet; DefaultConfigFilename = setup.ConfigFileName; // The default name used for the quoxent configuration file. Name = network.Name; CoinTicker = network.CoinTicker; Magic = ConversionTools.ConvertToUInt32(setup.Magic); RootFolderName = network.RootFolderName; DefaultPort = network.DefaultPort; DefaultRPCPort = network.DefaultRPCPort; DefaultAPIPort = network.DefaultAPIPort; DefaultMaxOutboundConnections = 16; DefaultMaxInboundConnections = 109; MaxTipAge = 2 * 60 * 60; MinTxFee = 9333; FallbackFee = 9333; MinRelayTxFee = 9333; MaxTimeOffsetSeconds = 25 * 60; DefaultBanTimeSeconds = 16000; // 500 (MaxReorg) * 64 (TargetSpacing) / 2 = 4 hours, 26 minutes and 40 seconds var consensusFactory = new PosConsensusFactory(); // Create the genesis block. GenesisTime = network.GenesisTime; GenesisNonce = network.GenesisNonce; GenesisBits = network.GenesisBits; GenesisVersion = network.GenesisVersion; GenesisReward = network.GenesisReward; Block genesisBlock = CreateGenesisBlock(consensusFactory, GenesisTime, GenesisNonce, GenesisBits, GenesisVersion, GenesisReward, setup.GenesisText); Genesis = genesisBlock; var consensusOptions = new PosConsensusOptions( maxBlockBaseSize: 1_000_000, maxStandardVersion: 2, maxStandardTxWeight: 100_000, maxBlockSigopsCost: 20_000, maxStandardTxSigopsCost: 20_000 / 5, witnessScaleFactor: 4 ); var buriedDeployments = new BuriedDeploymentsArray { [BuriedDeployments.BIP34] = 0, [BuriedDeployments.BIP65] = 0, [BuriedDeployments.BIP66] = 0 }; Consensus = new NBitcoin.Consensus( consensusFactory: consensusFactory, consensusOptions: consensusOptions, coinType: setup.CoinType, hashGenesisBlock: genesisBlock.GetHash(), subsidyHalvingInterval: 29333, majorityEnforceBlockUpgrade: 750, majorityRejectBlockOutdated: 950, majorityWindow: 1000, buriedDeployments: buriedDeployments, bip9Deployments: new NoBIP9Deployments(), bip34Hash: null, minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 500, defaultAssumeValid: null, maxMoney: long.MaxValue, coinbaseMaturity: 50, premineHeight: 2, premineReward: Money.Coins(setup.PremineReward), proofOfWorkReward: Money.Coins(setup.PoWBlockReward), targetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks targetSpacing: setup.TargetSpacing, powAllowMinDifficultyBlocks: false, posNoRetargeting: false, powNoRetargeting: false, powLimit: new Target(new uint256("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), minimumChainWork: null, isProofOfStake: true, lastPowBlock: setup.LastPowBlock, proofOfStakeLimit: new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), proofOfStakeLimitV2: new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), proofOfStakeReward: Money.Coins(setup.PoSBlockReward), proofOfStakeTimestampMask: setup.ProofOfStakeTimestampMask ); Consensus.PosEmptyCoinbase = quoxentSetup.Instance.IsPoSv3(); Consensus.PosUseTimeFieldInKernalHash = quoxentSetup.Instance.IsPoSv3(); // TODO: Set your Base58Prefixes Base58Prefixes = new byte[12][]; Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (byte)network.PubKeyAddress }; Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (byte)network.ScriptAddress }; Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (byte)network.SecretAddress }; Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 }; Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC] = new byte[] { 0x01, 0x43 }; Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x88), (0xB2), (0x1E) }; Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x88), (0xAD), (0xE4) }; Base58Prefixes[(int)Base58Type.PASSPHRASE_CODE] = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 }; Base58Prefixes[(int)Base58Type.CONFIRMATION_CODE] = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A }; Base58Prefixes[(int)Base58Type.STEALTH_ADDRESS] = new byte[] { 0x2a }; Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 23 }; Base58Prefixes[(int)Base58Type.COLORED_ADDRESS] = new byte[] { 0x13 }; Bech32Encoders = new Bech32Encoder[2]; var encoder = new Bech32Encoder(network.CoinTicker.ToLowerInvariant()); Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; Checkpoints = network.Checkpoints; DNSSeeds = network.DNS.Select(dns => new DNSSeedData(dns, dns)).ToList(); SeedNodes = network.Nodes.Select(node => new NBitcoin.Protocol.NetworkAddress(IPAddress.Parse(node), network.DefaultPort)).ToList(); StandardScriptsRegistry = new quoxentStandardScriptsRegistry(); // 64 below should be changed to TargetSpacingSeconds when we move that field. Assert(DefaultBanTimeSeconds <= Consensus.MaxReorgLength * 64 / 2); Assert(Consensus.HashGenesisBlock == uint256.Parse(network.HashGenesisBlock)); Assert(Genesis.Header.HashMerkleRoot == uint256.Parse(network.HashMerkleRoot)); RegisterRules(Consensus); RegisterMempoolRules(Consensus); }
/// <summary> /// Set time to consensus acceptable value /// </summary> /// <param name="consensus">Consensus</param> /// <param name="prev">previous block</param> public void UpdateTime(Consensus consensus, ChainedBlock prev) { UpdateTime(DateTimeOffset.UtcNow, consensus, prev); }
public static T Option <T>(this NBitcoin.Consensus item) where T : NBitcoin.Consensus.ConsensusOptions { return(item.Options as T); }
/// <inheritdoc/> public Target GetNextTargetRequired(IStakeChain stakeChain, ChainedHeader chainedHeader, NBitcoin.Consensus consensus, bool proofOfStake) { this.logger.LogTrace("({0}:'{1}',{2}:{3})", nameof(chainedHeader), chainedHeader, nameof(proofOfStake), proofOfStake); // Genesis block. if (chainedHeader == null) { this.logger.LogTrace("(-)[GENESIS]:'{0}'", consensus.PowLimit); return(consensus.PowLimit); } // Find the last two blocks that correspond to the mining algo // (i.e if this is a POS block we need to find the last two POS blocks). BigInteger targetLimit = proofOfStake ? consensus.ProofOfStakeLimitV2 : consensus.PowLimit.ToBigInteger(); // First block. ChainedHeader lastPowPosBlock = this.GetLastPowPosChainedBlock(stakeChain, chainedHeader, proofOfStake); if (lastPowPosBlock.Previous == null) { var res = new Target(targetLimit); this.logger.LogTrace("(-)[FIRST_BLOCK]:'{0}'", res); return(res); } // Second block. ChainedHeader prevLastPowPosBlock = this.GetLastPowPosChainedBlock(stakeChain, lastPowPosBlock.Previous, proofOfStake); if (prevLastPowPosBlock.Previous == null) { var res = new Target(targetLimit); this.logger.LogTrace("(-)[SECOND_BLOCK]:'{0}'", res); return(res); } // This is used in tests to allow quickly mining blocks. if (consensus.PowNoRetargeting) { this.logger.LogTrace("(-)[NO_POW_RETARGET]:'{0}'", lastPowPosBlock.Header.Bits); return(lastPowPosBlock.Header.Bits); } Target finalTarget = this.CalculateRetarget(lastPowPosBlock.Header.Time, lastPowPosBlock.Header.Bits, prevLastPowPosBlock.Header.Time, targetLimit); this.logger.LogTrace("(-):'{0}'", finalTarget); return(finalTarget); }
public static Target GetWorkRequired(NBitcoin.Consensus consensus, ChainedBlock chainedBlock) { // Genesis block if (chainedBlock.Height == 0) { return(consensus.PowLimit); } var nProofOfWorkLimit = consensus.PowLimit; var pindexLast = chainedBlock.Previous; var height = chainedBlock.Height; if (pindexLast == null) { return(nProofOfWorkLimit); } // Only change once per interval if ((height) % consensus.DifficultyAdjustmentInterval != 0) { if (consensus.PowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if (chainedBlock.Header.BlockTime > pindexLast.Header.BlockTime + TimeSpan.FromTicks(consensus.PowTargetSpacing.Ticks * 2)) { return(nProofOfWorkLimit); } else { // Return the last non-special-min-difficulty-rules-block ChainedBlock pindex = pindexLast; while (pindex.Previous != null && (pindex.Height % consensus.DifficultyAdjustmentInterval) != 0 && pindex.Header.Bits == nProofOfWorkLimit) { pindex = pindex.Previous; } return(pindex.Header.Bits); } } return(pindexLast.Header.Bits); } // Go back by what we want to be 14 days worth of blocks var pastHeight = pindexLast.Height - (consensus.DifficultyAdjustmentInterval - 1); ChainedBlock pindexFirst = chainedBlock.EnumerateToGenesis().FirstOrDefault(o => o.Height == pastHeight); Guard.Assert(pindexFirst != null); if (consensus.PowNoRetargeting) { return(pindexLast.Header.Bits); } // Limit adjustment step var nActualTimespan = pindexLast.Header.BlockTime - pindexFirst.Header.BlockTime; if (nActualTimespan < TimeSpan.FromTicks(consensus.PowTargetTimespan.Ticks / 4)) { nActualTimespan = TimeSpan.FromTicks(consensus.PowTargetTimespan.Ticks / 4); } if (nActualTimespan > TimeSpan.FromTicks(consensus.PowTargetTimespan.Ticks * 4)) { nActualTimespan = TimeSpan.FromTicks(consensus.PowTargetTimespan.Ticks * 4); } // Retarget var bnNew = pindexLast.Header.Bits.ToBigInteger(); bnNew = bnNew.Multiply(BigInteger.ValueOf((long)nActualTimespan.TotalSeconds)); bnNew = bnNew.Divide(BigInteger.ValueOf((long)consensus.PowTargetTimespan.TotalSeconds)); var newTarget = new Target(bnNew); if (newTarget > nProofOfWorkLimit) { newTarget = nProofOfWorkLimit; } return(newTarget); }
public RutanioTest() { // START MODIFICATIONS OF GENERATED CODE var consensusOptions = new RutanioPosConsensusOptions { MaxBlockBaseSize = 1_000_000, MaxStandardVersion = 2, MaxStandardTxWeight = 100_000, MaxBlockSigopsCost = 20_000, MaxStandardTxSigopsCost = 20_000 / 5, WitnessScaleFactor = 4 }; // END MODIFICATIONS CoinSetup setup = RutanioSetup.Instance.Setup; NetworkSetup network = RutanioSetup.Instance.Test; NetworkType = NetworkType.Testnet; Name = network.Name; CoinTicker = network.CoinTicker; Magic = ConversionTools.ConvertToUInt32(setup.Magic, true); RootFolderName = network.RootFolderName; DefaultPort = network.DefaultPort; DefaultRPCPort = network.DefaultRPCPort; DefaultAPIPort = network.DefaultAPIPort; var consensusFactory = new PosConsensusFactory(); // Create the genesis block. GenesisTime = network.GenesisTime; GenesisNonce = network.GenesisNonce; GenesisBits = network.GenesisBits; GenesisVersion = network.GenesisVersion; GenesisReward = network.GenesisReward; Block genesisBlock = CreateGenesisBlock(consensusFactory, GenesisTime, GenesisNonce, GenesisBits, GenesisVersion, GenesisReward, setup.GenesisText); Genesis = genesisBlock; var buriedDeployments = new BuriedDeploymentsArray { [BuriedDeployments.BIP34] = 0, [BuriedDeployments.BIP65] = 0, [BuriedDeployments.BIP66] = 0 }; var bip9Deployments = new RutanioBIP9Deployments() { [RutanioBIP9Deployments.TestDummy] = new BIP9DeploymentsParameters("TestDummy", 28, new DateTime(2020, 6, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2021, 6, 1, 0, 0, 0, DateTimeKind.Utc), BIP9DeploymentsParameters.DefaultTestnetThreshold), [RutanioBIP9Deployments.CSV] = new BIP9DeploymentsParameters("CSV", 0, new DateTime(2020, 6, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2021, 6, 1, 0, 0, 0, DateTimeKind.Utc), BIP9DeploymentsParameters.DefaultTestnetThreshold), [RutanioBIP9Deployments.Segwit] = new BIP9DeploymentsParameters("Segwit", 1, new DateTime(2020, 6, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2021, 6, 1, 0, 0, 0, DateTimeKind.Utc), BIP9DeploymentsParameters.DefaultTestnetThreshold), [RutanioBIP9Deployments.ColdStaking] = new BIP9DeploymentsParameters("ColdStaking", 2, new DateTime(2020, 6, 1, 0, 0, 0, DateTimeKind.Utc), new DateTime(2021, 6, 1, 0, 0, 0, DateTimeKind.Utc), BIP9DeploymentsParameters.DefaultTestnetThreshold) }; Consensus = new NBitcoin.Consensus( consensusFactory: consensusFactory, consensusOptions: consensusOptions, coinType: setup.CoinType, hashGenesisBlock: genesisBlock.GetHash(), subsidyHalvingInterval: 210000, majorityEnforceBlockUpgrade: 750, majorityRejectBlockOutdated: 950, majorityWindow: 1000, buriedDeployments: buriedDeployments, bip9Deployments: new NoBIP9Deployments(), bip34Hash: null, minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 500, defaultAssumeValid: null, maxMoney: long.MaxValue, coinbaseMaturity: 10, premineHeight: 2, premineReward: Money.Coins(setup.PremineReward), proofOfWorkReward: Money.Coins(setup.PoWBlockReward), targetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks targetSpacing: setup.TargetSpacing, powAllowMinDifficultyBlocks: false, posNoRetargeting: false, powNoRetargeting: false, powLimit: new Target(new uint256("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), minimumChainWork: null, isProofOfStake: true, lastPowBlock: setup.LastPowBlock, proofOfStakeLimit: new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), proofOfStakeLimitV2: new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)), proofOfStakeReward: Money.Coins(setup.PoSBlockReward), proofOfStakeTimestampMask: setup.ProofOfStakeTimestampMask ); Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (byte)network.PubKeyAddress }; Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (byte)network.ScriptAddress }; Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (byte)network.SecretAddress }; Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x35), (0x87), (0xCF) }; Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x35), (0x83), (0x94) }; Bech32Encoders = new Bech32Encoder[2]; var encoder = new Bech32Encoder(network.CoinTicker.ToLowerInvariant()); Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; Checkpoints = network.Checkpoints; DNSSeeds = network.DNS.Select(dns => new DNSSeedData(dns, dns)).ToList(); SeedNodes = network.Nodes.Select(node => new NBitcoin.Protocol.NetworkAddress(IPAddress.Parse(Dns.GetHostAddresses(node).GetValue(0).ToString()), network.DefaultPort)).ToList(); StandardScriptsRegistry = new RutanioStandardScriptsRegistry(); // 64 below should be changed to TargetSpacingSeconds when we move that field. Assert(DefaultBanTimeSeconds <= Consensus.MaxReorgLength * 64 / 2); Assert(Consensus.HashGenesisBlock == uint256.Parse(network.HashGenesisBlock)); Assert(Genesis.Header.HashMerkleRoot == uint256.Parse(network.HashMerkleRoot)); RegisterRules(Consensus); RegisterMempoolRules(Consensus); } }
/// <inheritdoc/> public Target GetNextTargetRequired(IStakeChain stakeChain, ChainedBlock chainedBlock, NBitcoin.Consensus consensus, bool proofOfStake) { this.logger.LogTrace("({0}:'{1}',{2}:{3})", nameof(chainedBlock), chainedBlock, nameof(proofOfStake), proofOfStake); // Genesis block. if (chainedBlock == null) { this.logger.LogTrace("(-)[GENESIS]:'{0}'", consensus.PowLimit); return(consensus.PowLimit); } // Find the last two blocks that correspond to the mining algo // (i.e if this is a POS block we need to find the last two POS blocks). BigInteger targetLimit = proofOfStake ? consensus.ProofOfStakeLimitV2 : consensus.PowLimit.ToBigInteger(); // First block. ChainedBlock lastPowPosBlock = GetLastPowPosChainedBlock(stakeChain, chainedBlock, proofOfStake); if (lastPowPosBlock.Previous == null) { var res = new Target(targetLimit); this.logger.LogTrace("(-)[FIRST_BLOCK]:'{0}'", res); return(res); } // Second block. ChainedBlock prevLastPowPosBlock = GetLastPowPosChainedBlock(stakeChain, lastPowPosBlock.Previous, proofOfStake); if (prevLastPowPosBlock.Previous == null) { var res = new Target(targetLimit); this.logger.LogTrace("(-)[SECOND_BLOCK]:'{0}'", res); return(res); } // This is used in tests to allow quickly mining blocks. if (consensus.PowNoRetargeting) { this.logger.LogTrace("(-)[NO_POW_RETARGET]:'{0}'", lastPowPosBlock.Header.Bits); return(lastPowPosBlock.Header.Bits); } int targetSpacing = TargetSpacingSeconds; int actualSpacing = (int)(lastPowPosBlock.Header.Time - prevLastPowPosBlock.Header.Time); if (actualSpacing < 0) { actualSpacing = targetSpacing; } if (actualSpacing > targetSpacing * 10) { actualSpacing = targetSpacing * 10; } int targetTimespan = RetargetIntervalMinutes * 60; int interval = targetTimespan / targetSpacing; BigInteger target = lastPowPosBlock.Header.Bits.ToBigInteger(); long multiplyBy = (interval - 1) * targetSpacing + actualSpacing + actualSpacing; target = target.Multiply(BigInteger.ValueOf(multiplyBy)); long divideBy = (interval + 1) * targetSpacing; target = target.Divide(BigInteger.ValueOf(divideBy)); this.logger.LogTrace("The next target difficulty will be {0} times higher (easier to satisfy) than the previous target.", (double)multiplyBy / (double)divideBy); if ((target.CompareTo(BigInteger.Zero) <= 0) || (target.CompareTo(targetLimit) >= 1)) { target = targetLimit; } var finalTarget = new Target(target); this.logger.LogTrace("(-):'{0}'", finalTarget); return(finalTarget); }