コード例 #1
0
        public ContextBlockInformation(ChainedBlock bestBlock, NBitcoin.Consensus consensus)
        {
            Guard.NotNull(bestBlock, nameof(bestBlock));

            this.Header         = bestBlock.Header;
            this.Height         = bestBlock.Height;
            this.MedianTimePast = bestBlock.GetMedianTimePast();
        }
コード例 #2
0
 public ContextBlockInformation(ChainedBlock bestBlock, NBitcoin.Consensus consensus)
 {
     if (bestBlock == null)
     {
         throw new ArgumentNullException("bestBlock");
     }
     Header         = bestBlock.Header;
     Height         = bestBlock.Height;
     MedianTimePast = bestBlock.GetMedianTimePast();
 }
コード例 #3
0
        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);
        }
コード例 #4
0
        /** 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);
        }
コード例 #5
0
        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);
        }