Esempio n. 1
0
        public PowBlockAssembler(ConsensusLoop consensusLoop, Network network, ConcurrentChain chain,
                                 MempoolScheduler mempoolScheduler, TxMempool mempool,
                                 IDateTimeProvider dateTimeProvider, AssemblerOptions options = null)
        {
            options = options ?? new AssemblerOptions();
            this.blockMinFeeRate = options.BlockMinFeeRate;
            // Limit weight to between 4K and MAX_BLOCK_WEIGHT-4K for sanity:
            this.blockMaxWeight = (uint)Math.Max(4000, Math.Min(PowMining.DefaultBlockMaxWeight - 4000, options.BlockMaxWeight));
            // Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
            this.blockMaxSize = (uint)Math.Max(1000, Math.Min(network.Consensus.Option <PowConsensusOptions>().MAX_BLOCK_SERIALIZED_SIZE - 1000, options.BlockMaxSize));
            // Whether we need to account for byte usage (in addition to weight usage)
            this.needSizeAccounting = (blockMaxSize < network.Consensus.Option <PowConsensusOptions>().MAX_BLOCK_SERIALIZED_SIZE - 1000);

            this.consensusLoop    = consensusLoop;
            this.chain            = chain;
            this.mempoolScheduler = mempoolScheduler;
            this.mempool          = mempool;
            this.dateTimeProvider = dateTimeProvider;
            this.options          = options;
            this.network          = network;

            this.inBlock = new TxMempool.SetEntries();

            // Reserve space for coinbase tx
            this.blockSize       = 1000;
            this.blockWeight     = 4000;
            this.blockSigOpsCost = 400;
            this.fIncludeWitness = false;

            // These counters do not include coinbase tx
            this.blockTx = 0;
            this.fees    = 0;

            this.pblocktemplate = new BlockTemplate {
                Block = new Block(), VTxFees = new List <Money>()
            };
        }
Esempio n. 2
0
        public void GenerateBlocks(List <TrxStakingInfo> trxPairs)
        {
            this.LastCoinStakeSearchInterval = 0;

            if (this.chain.Tip != this.consensusLoop.Tip)
            {
                return;
            }

            BlockTemplate pblocktemplate = null;
            bool          tryToSync      = true;

            while (true)
            {
                while (!this.connection.ConnectedNodes.Any() || chainState.IsInitialBlockDownload)
                {
                    this.LastCoinStakeSearchInterval = 0;
                    tryToSync = true;
                    this.cancellationProvider.Cancellation.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(this.minerSleep));
                }

                if (tryToSync)
                {
                    tryToSync = false;
                    if (this.connection.ConnectedNodes.Count() < 3 ||
                        this.chain.Tip.Header.Time < dateTimeProvider.GetTime() - 10 * 60)
                    {
                        this.cancellationProvider.Cancellation.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(60000));
                        continue;
                    }
                }

                if (pblocktemplate == null)
                {
                    pblocktemplate = this.blockAssemblerFactory.Create(new AssemblerOptions()
                    {
                        IsProofOfStake = true
                    }).CreateNewBlock(new Script());
                }


                var pblock     = pblocktemplate.Block;
                var pindexPrev = this.chain.Tip;

                var stakeTxes = new List <StakeTx>();

                var coinset =
                    this.coinView.FetchCoinsAsync(trxPairs.Select(s => s.TransactionHash).ToArray()).GetAwaiter().GetResult();
                foreach (var sets in coinset.UnspentOutputs)
                {
                    int index = 0;
                    foreach (var outputx in sets._Outputs)
                    {
                        if (outputx != null && outputx.Value > Money.Zero)
                        {
                            var stakeTx = new StakeTx();

                            stakeTx.TxOut       = outputx;
                            stakeTx.OutPoint    = new OutPoint(sets.TransactionId, index);
                            stakeTx.PrvKey      = trxPairs.First(t => t.TransactionHash == sets.TransactionId).PrvKey;
                            stakeTx.OutputIndex = index;
                            stakeTx.HashBlock   = this.chain.GetBlock((int)sets.Height).HashBlock;
                            stakeTx.UtxoSet     = sets;

                            stakeTxes.Add(stakeTx);
                        }

                        index++;
                    }
                }

                // Trying to sign a block
                if (this.SignBlock(stakeTxes, pblock, pindexPrev, pblocktemplate.TotalFee))
                {
                    var blockResult = new BlockResult {
                        Block = pblock
                    };
                    this.CheckState(new ContextInformation(blockResult, network.Consensus), pindexPrev);

                    trxPairs.Add(new TrxStakingInfo
                    {
                        TransactionHash = pblock.Transactions[1].GetHash(),
                        PrvKey          = trxPairs.First().PrvKey
                    });

                    pblocktemplate = null;
                }
                else
                {
                    this.cancellationProvider.Cancellation.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(this.minerSleep));
                }
            }
        }
        public void GenerateBlocks(WalletSecret walletSecret)
        {
            this.LastCoinStakeSearchInterval = 0;

            BlockTemplate pblocktemplate = null;
            bool          tryToSync      = true;

            while (true)
            {
                if (this.chain.Tip != this.consensusLoop.Tip)
                {
                    return;
                }

                while (!this.connection.ConnectedNodes.Any() || chainState.IsInitialBlockDownload)
                {
                    this.LastCoinStakeSearchInterval = 0;
                    tryToSync = true;
                    this.cancellationProvider.Cancellation.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(this.minerSleep));
                }

                if (tryToSync)
                {
                    tryToSync = false;
                    if (this.connection.ConnectedNodes.Count() < 3 ||
                        this.chain.Tip.Header.Time < dateTimeProvider.GetTime() - 10 * 60)
                    {
                        //this.cancellationProvider.Cancellation.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(60000));
                        continue;
                    }
                }

                if (pblocktemplate == null)
                {
                    pblocktemplate = this.blockAssemblerFactory.Create(new AssemblerOptions()
                    {
                        IsProofOfStake = true
                    }).CreateNewBlock(new Script());
                }


                var pblock     = pblocktemplate.Block;
                var pindexPrev = this.consensusLoop.Tip;

                var stakeTxes = new List <StakeTx>();
                var spendable = this.wallet.GetSpendableTransactions(1);

                var coinset = this.coinView.FetchCoinsAsync(spendable.SelectMany(s => s.Transactions.Select(t => t.Id)).ToArray()).GetAwaiter().GetResult();

                foreach (var unspentInfo in spendable)
                {
                    foreach (var infoTransaction in unspentInfo.Transactions)
                    {
                        var set  = coinset.UnspentOutputs.FirstOrDefault(f => f?.TransactionId == infoTransaction.Id);
                        var utxo = set?._Outputs[infoTransaction.Index.Value];

                        if (utxo != null && utxo.Value > Money.Zero)
                        {
                            var stakeTx = new StakeTx();

                            stakeTx.TxOut       = utxo;
                            stakeTx.OutPoint    = new OutPoint(set.TransactionId, infoTransaction.Index.Value);
                            stakeTx.Address     = unspentInfo.Address;
                            stakeTx.OutputIndex = infoTransaction.Index.Value;
                            stakeTx.HashBlock   = this.chain.GetBlock((int)set.Height).HashBlock;
                            stakeTx.UtxoSet     = set;
                            stakeTx.Secret      = walletSecret;                        //temporary
                            stakeTxes.Add(stakeTx);
                        }
                    }
                }

                // Trying to sign a block
                if (this.SignBlock(stakeTxes, pblock, pindexPrev, pblocktemplate.TotalFee))
                {
                    var blockResult = new BlockResult {
                        Block = pblock
                    };
                    this.CheckState(new ContextInformation(blockResult, this.network.Consensus), pindexPrev);

                    pblocktemplate = null;
                }
                else
                {
                    this.cancellationProvider.Cancellation.Token.WaitHandle.WaitOne(TimeSpan.FromMilliseconds(this.minerSleep));
                }
            }
        }