public ContextBlockInformation(ChainedBlock bestBlock, NBitcoin.Consensus consensus) { Guard.NotNull(bestBlock, nameof(bestBlock)); this.Header = bestBlock.Header; this.Height = bestBlock.Height; this.MedianTimePast = bestBlock.GetMedianTimePast(); }
public ContextBlockInformation(ChainedBlock bestBlock, NBitcoin.Consensus consensus) { if (bestBlock == null) { throw new ArgumentNullException("bestBlock"); } Header = bestBlock.Header; Height = bestBlock.Height; MedianTimePast = bestBlock.GetMedianTimePast(); }
public ThresholdState GetState(ChainedBlock pindexPrev, BIP9Deployments deployment) { int nPeriod = this.consensus.MinerConfirmationWindow; int nThreshold = this.consensus.RuleChangeActivationThreshold; var nTimeStart = this.consensus.BIP9Deployments[deployment]?.StartTime; var nTimeTimeout = this.consensus.BIP9Deployments[deployment]?.Timeout; // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1. if (pindexPrev != null) { pindexPrev = pindexPrev.GetAncestor(pindexPrev.Height - ((pindexPrev.Height + 1) % nPeriod)); } // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known List <ChainedBlock> vToCompute = new List <ChainedBlock>(); while (!this.ContainsKey(pindexPrev?.HashBlock, deployment)) { if (pindexPrev.GetMedianTimePast() < nTimeStart) { // Optimization: don't recompute down further, as we know every earlier block will be before the start time this.Set(pindexPrev?.HashBlock, deployment, ThresholdState.Defined); break; } vToCompute.Add(pindexPrev); pindexPrev = pindexPrev.GetAncestor(pindexPrev.Height - nPeriod); } // At this point, cache[pindexPrev] is known this.Assert(this.ContainsKey(pindexPrev?.HashBlock, deployment)); ThresholdState state = this.Get(pindexPrev?.HashBlock, deployment); // Now walk forward and compute the state of descendants of pindexPrev while (vToCompute.Count != 0) { ThresholdState stateNext = state; pindexPrev = vToCompute[vToCompute.Count - 1]; vToCompute.RemoveAt(vToCompute.Count - 1); switch (state) { case ThresholdState.Defined: { if (pindexPrev.GetMedianTimePast() >= nTimeTimeout) { stateNext = ThresholdState.Failed; } else if (pindexPrev.GetMedianTimePast() >= nTimeStart) { stateNext = ThresholdState.Started; } break; } case ThresholdState.Started: { if (pindexPrev.GetMedianTimePast() >= nTimeTimeout) { stateNext = ThresholdState.Failed; break; } // We need to count ChainedBlock pindexCount = pindexPrev; int count = 0; for (int i = 0; i < nPeriod; i++) { if (this.Condition(pindexCount, deployment)) { count++; } pindexCount = pindexCount.Previous; } if (count >= nThreshold) { stateNext = ThresholdState.LockedIn; } break; } case ThresholdState.LockedIn: { // Always progresses into ACTIVE. stateNext = ThresholdState.Active; break; } case ThresholdState.Failed: case ThresholdState.Active: { // Nothing happens, these are terminal states. break; } } this.Set(pindexPrev?.HashBlock, deployment, state = stateNext); } return(state); }
/** Construct a new block template with coinbase to scriptPubKeyIn */ public override BlockTemplate CreateNewBlock(Script scriptPubKeyIn, bool fMineWitnessTx = true) { long nTimeStart = DateTime.UtcNow.Ticks / TicksPerMicrosecond; pblock = pblocktemplate.Block; // pointer for convenience this.scriptPubKeyIn = scriptPubKeyIn; this.CreateCoinbase(); this.ComputeBlockVersion(); // TODO: MineBlocksOnDemand // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios //if (this.network. chainparams.MineBlocksOnDemand()) // pblock->nVersion = GetArg("-blockversion", pblock->nVersion); medianTimePast = Utils.DateTimeToUnixTime(pindexPrev.GetMedianTimePast()); lockTimeCutoff = PowConsensusValidator.StandardLocktimeVerifyFlags.HasFlag(Transaction.LockTimeFlags.MedianTimePast) ? medianTimePast : pblock.Header.Time; // TODO: Implement Witness Code // Decide whether to include witness transactions // This is only needed in case the witness softfork activation is reverted // (which would require a very deep reorganization) or when // -promiscuousmempoolflags is used. // TODO: replace this with a call to main to assess validity of a mempool // transaction (which in most cases can be a no-op). fIncludeWitness = false; //IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx; // add transactions from the mempool int nPackagesSelected = 0; int nDescendantsUpdated = 0; AddTransactions(nPackagesSelected, nDescendantsUpdated); long nTime1 = DateTime.UtcNow.Ticks / TicksPerMicrosecond; LastBlockTx = blockTx; LastBlockSize = blockSize; LastBlockWeight = blockWeight; // TODO: Implement Witness Code // pblocktemplate->CoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus()); pblocktemplate.VTxFees[0] = -fees; coinbase.Outputs[0].Value = this.fees + this.consensusLoop.Validator.GetProofOfWorkReward(this.height); pblocktemplate.TotalFee = this.fees; var nSerializeSize = pblock.GetSerializedSize(); Logs.Mining.LogInformation( $"CreateNewBlock: total size: {nSerializeSize} block weight: {consensusLoop.Validator.GetBlockWeight(pblock)} txs: {blockTx} fees: {fees} sigops {blockSigOpsCost}"); this.UpdateHeaders(); //pblocktemplate->TxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); this.TestBlockValidity(); //int64_t nTime2 = GetTimeMicros(); //LogPrint(BCLog::BENCH, "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart)); return(pblocktemplate); }
private Block CreateNewBlock(ChainedBlock pindexPrev, bool proofOfStake, out long fee) { fee = 0; // create the block var block = new Block(); var height = pindexPrev.Height + 1; // Create coinbase tx var txNew = new Transaction(); txNew.AddInput(new TxIn()); txNew.AddOutput(new TxOut(Money.Zero, Script.Empty)); if (!proofOfStake) { throw new MinedBlockException("Only POS transactions supported"); } else { // Height first in coinbase required for block.version=2 txNew.Inputs[0].ScriptSig = new Script(BitConverter.GetBytes(height)); //(CScript() << nHeight) + COINBASE_FLAGS; if (!(txNew.Inputs[0].ScriptSig.Length <= 100)) { throw new MinedBlockException(); } } // Add our coinbase tx as first transaction block.AddTransaction(txNew); // Largest block you're willing to create: uint nBlockMaxSize = 1000000 / 2 / 2; //GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN / 2); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = Math.Max((uint)1000, Math.Min((uint)(1000000 - 1000), nBlockMaxSize)); // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay uint nBlockPrioritySize = 27000; //GetArg("-blockprioritysize", 27000); nBlockPrioritySize = Math.Min(nBlockMaxSize, nBlockPrioritySize); // Minimum block size you want to create; block will be filled with free transactions // until there are no more or the block reaches this size: uint nBlockMinSize = 0; //GetArg("-blockminsize", 0); nBlockMinSize = Math.Min(nBlockMaxSize, nBlockMinSize); // Fee-per-kilobyte amount considered the same as "free" // Be careful setting this: if you set it to zero then // a transaction spammer can cheaply fill blocks using // 1-satoshi-fee transactions. It should be set above the real // cost to you of processing a transaction. long nMinTxFee = 10000; //MIN_TX_FEE; //if (mapArgs.count("-mintxfee")) // ParseMoney(mapArgs["-mintxfee"], nMinTxFee); block.Header.Bits = BlockValidator.GetNextTargetRequired(pindexPrev, this.Context.Network.Consensus, proofOfStake); // Collect memory pool transactions into the block // ============================ // todo: add transactions from the mem pool when its implemented // ============================ //if (fDebug && GetBoolArg("-printpriority", false)) // LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize); if (!proofOfStake) { block.Transactions[0].Outputs[0].Value = BlockValidator.GetProofOfWorkReward(this.chainIndex, fee); } //if (pFees) // *pFees = nFees; // Fill in header block.Header.HashPrevBlock = pindexPrev.HashBlock; block.Header.BlockTime = pindexPrev.GetMedianTimePast() + TimeSpan.FromSeconds(1.0); //pblock->nTime = max(pindexPrev->GetPastTimeLimit() + 1, pblock->GetMaxTransactionTime()); if (!proofOfStake) { block.Header.UpdateTime(this.Context.Network, pindexPrev); } block.Header.Nonce = 0; return(block); }