private BlockMsg convertEntityToBlockMsg(Block entity)
        {
            var txDac     = new TransactionDac();
            var inputDac  = new InputDac();
            var outputDac = new OutputDac();

            var blockMsg  = new BlockMsg();
            var headerMsg = new BlockHeaderMsg();

            headerMsg.Version           = entity.Version;
            headerMsg.Hash              = entity.Hash;
            headerMsg.Height            = entity.Height;
            headerMsg.PreviousBlockHash = entity.PreviousBlockHash;
            headerMsg.Bits              = entity.Bits;
            headerMsg.Nonce             = entity.Nonce;
            headerMsg.Timestamp         = entity.Timestamp;

            var transactions = txDac.SelectByBlockHash(entity.Hash);

            headerMsg.TotalTransaction = transactions == null ? 0: transactions.Count;

            foreach (var tx in transactions)
            {
                var txMsg = new TransactionMsg();
                txMsg.Version   = tx.Version;
                txMsg.Hash      = tx.Hash;
                txMsg.Timestamp = tx.Timestamp;
                txMsg.Locktime  = tx.LockTime;

                var inputs  = inputDac.SelectByTransactionHash(tx.Hash);
                var outputs = outputDac.SelectByTransactionHash(tx.Hash);

                foreach (var input in inputs)
                {
                    txMsg.Inputs.Add(new InputMsg
                    {
                        OutputTransactionHash = input.OutputTransactionHash,
                        OutputIndex           = input.OutputIndex,
                        Size         = input.Size,
                        UnlockScript = input.UnlockScript
                    });
                }

                foreach (var output in outputs)
                {
                    txMsg.Outputs.Add(new OutputMsg
                    {
                        Index      = output.Index,
                        Amount     = output.Amount,
                        Size       = output.Size,
                        LockScript = output.LockScript
                    });
                }

                blockMsg.Transactions.Add(txMsg);
            }

            blockMsg.Header = headerMsg;
            return(blockMsg);
        }
        public List <BlockHeaderMsg> GetBlockHeaderMsgByHeights(List <long> heights)
        {
            var blockDac = new BlockDac();
            var txDac    = new TransactionDac();
            var headers  = new List <BlockHeaderMsg>();

            foreach (var height in heights)
            {
                var items = blockDac.SelectByHeight(height);

                foreach (var entity in items)
                {
                    var header = new BlockHeaderMsg();
                    header.Version           = entity.Version;
                    header.Hash              = entity.Hash;
                    header.Height            = entity.Height;
                    header.PreviousBlockHash = entity.PreviousBlockHash;
                    header.Bits              = entity.Bits;
                    header.Nonce             = entity.Nonce;
                    header.Timestamp         = entity.Timestamp;

                    var transactions = txDac.SelectByBlockHash(entity.Hash);
                    header.TotalTransaction = entity.Transactions == null ? 0 : entity.Transactions.Count;

                    headers.Add(header);
                }
            }

            return(headers);
        }
Exemple #3
0
        public void BroadcastNewBlockMessage(BlockHeaderMsg blockHeader)
        {
            var nodes = this.p2pComponent.GetNodes();

            foreach (var node in nodes)
            {
                if (node.IsConnected && !node.IsTrackerServer)
                {
                    var payload = new NewBlockMsg();
                    payload.Header = blockHeader;

                    var cmd = P2PCommand.CreateCommand(this.Identity.ToString(), CommandNames.Block.NewBlock, payload);
                    this.p2pComponent.SendCommand(node.IP, node.Port, cmd);
                }
            }
        }
Exemple #4
0
        public List <BlockHeaderMsg> GetBlockHeaderMsgByHeights(List <long> heights)
        {
            var blockDac = new BlockDac();
            var txDac    = new TransactionDac();
            var headers  = new List <BlockHeaderMsg>();

            foreach (var height in heights)
            {
                var items = blockDac.SelectByHeight(height);

                foreach (var entity in items)
                {
                    var header = new BlockHeaderMsg();
                    header.Version           = entity.Version;
                    header.Hash              = entity.Hash;
                    header.Height            = entity.Height;
                    header.PreviousBlockHash = entity.PreviousBlockHash;
                    header.Bits              = entity.Bits;
                    header.Nonce             = entity.Nonce;
                    header.Timestamp         = entity.Timestamp;
                    header.GeneratorId       = entity.GeneratorId;
                    //header.GenerationSignature = entity.GenerationSignature;
                    //header.BlockSignature = entity.BlockSignature;
                    //header.CumulativeDifficulty = entity.CumulativeDifficulty;
                    header.PayloadHash    = entity.PayloadHash;
                    header.BlockSignature = entity.BlockSignature;
                    header.BlockSigSize   = entity.BlockSignature.Length;

                    var transactions = txDac.SelectByBlockHash(entity.Hash);
                    header.TotalTransaction = entity.Transactions == null ? 0 : entity.Transactions.Count;

                    headers.Add(header);
                }
            }

            return(headers);
        }
Exemple #5
0
        /// <summary>
        /// 创建新的区块
        /// </summary>
        /// <param name="minerName"></param>
        /// <param name="generatorId"></param>
        /// <param name="accountId"></param>
        /// <returns></returns>
        public BlockMsg CreateNewBlock(string minerName, string generatorId, string remark = null, string accountId = null)
        {
            var accountDac      = new AccountDac();
            var blockDac        = new BlockDac();
            var outputDac       = new OutputDac();
            var txDac           = new TransactionDac();
            var txPool          = TransactionPool.Instance;
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight    = -1;
            string lastBlockHash      = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits      = -1;
            string lastBlockGenerator = null;

            //获取最后一个区块
            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight    = blockEntity.Height;
                lastBlockHash      = blockEntity.Hash;
                lastBlockBits      = blockEntity.Bits;
                lastBlockGenerator = blockEntity.GeneratorId;
            }

            long totalSize    = 0;
            long maxSize      = BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);
            var  poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var  index        = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                var tx = poolItemList[index].Transaction;

                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }
                else
                {
                    break;
                }

                index++;
            }


            var minerAccount = accountDac.SelectDefaultAccount();

            if (accountId != null)
            {
                var account = accountDac.SelectById(accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            var minerAccountId = minerAccount.Id;

            BlockMsg       newBlockMsg = new BlockMsg();
            BlockHeaderMsg headerMsg   = new BlockHeaderMsg();

            headerMsg.Hash              = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.GeneratorId       = generatorId;
            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;

            if (headerMsg.Height == 0)
            {
                minerAccountId = BlockSetting.GenesisBlockReceiver;
                remark         = BlockSetting.GenesisBlockRemark;
            }

            long totalAmount = 0;
            long totalFee    = 0;

            foreach (var tx in transactionMsgs)
            {
                long totalInputsAmount = 0L;
                long totalOutputAmount = 0L;

                foreach (var input in tx.Inputs)
                {
                    var utxo = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                    if (utxo != null)
                    {
                        totalInputsAmount += utxo.Amount;
                    }
                }

                foreach (var output in tx.Outputs)
                {
                    totalOutputAmount += output.Amount;
                }

                totalAmount += totalOutputAmount;
                totalFee    += (totalInputsAmount - totalOutputAmount);
            }

            //var work = new POW(headerMsg.Height);
            BlockMsg prevBlockMsg     = null;
            BlockMsg prevStepBlockMsg = null;

            if (blockEntity != null)
            {
                prevBlockMsg = this.convertEntityToBlockMsg(blockEntity);
            }

            if (headerMsg.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                prevStepBlockMsg = this.GetBlockMsgByHeight(headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1);
            }

            var newBlockReward = POC.GetNewBlockReward(headerMsg.Height);

            headerMsg.Bits             = POC.CalculateBaseTarget(headerMsg.Height, prevBlockMsg, prevStepBlockMsg);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName, remark);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccountId);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);

            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            headerMsg.PayloadHash = newBlockMsg.GetPayloadHash();
            var dsa        = ECDsa.ImportPrivateKey(Base16.Decode(minerAccount.PrivateKey));
            var signResult = dsa.SingnData(Base16.Decode(headerMsg.PayloadHash));

            headerMsg.BlockSignature   = Base16.Encode(signResult);
            headerMsg.BlockSigSize     = headerMsg.BlockSignature.Length;
            headerMsg.TotalTransaction = newBlockMsg.Transactions.Count;
            return(newBlockMsg);
        }
        public BlockMsg CreateNewBlock(string minerName, string accountId = null)
        {
            var accountDac      = new AccountDac();
            var blockDac        = new BlockDac();
            var outputDac       = new OutputDac();
            var txDac           = new TransactionDac();
            var txPool          = TransactionPool.Instance;
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight = -1;
            string lastBlockHash   = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits   = -1;

            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight = blockEntity.Height;
                lastBlockHash   = blockEntity.Hash;
                lastBlockBits   = blockEntity.Bits;
            }

            long totalSize    = 0;
            long maxSize      = BlockSetting.MAX_BLOCK_SIZE - (500 * 1024);
            var  poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var  index        = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                var tx = poolItemList[index].Transaction;

                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }
                else
                {
                    break;
                }

                index++;
            }


            var minerAccount = accountDac.SelectDefaultAccount();

            if (accountId != null)
            {
                var account = accountDac.SelectById(accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            BlockMsg       newBlockMsg = new BlockMsg();
            BlockHeaderMsg headerMsg   = new BlockHeaderMsg();

            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;


            long totalAmount = 0;
            long totalFee    = 0;

            foreach (var tx in transactionMsgs)
            {
                long totalInputsAmount = 0L;
                long totalOutputAmount = 0L;

                foreach (var input in tx.Inputs)
                {
                    var utxo = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                    if (utxo != null)
                    {
                        totalInputsAmount += utxo.Amount;
                    }
                }

                foreach (var output in tx.Outputs)
                {
                    totalOutputAmount += output.Amount;
                }

                totalAmount += totalOutputAmount;
                totalFee    += (totalInputsAmount - totalOutputAmount);
            }

            var      work = new POW(headerMsg.Height);
            BlockMsg previous4032Block = null;

            if (headerMsg.Height > POW.DiffiucltyAdjustStep)
            {
                previous4032Block = this.GetBlockMsgByHeight(headerMsg.Height - POW.DiffiucltyAdjustStep);
            }

            var newBlockReward = work.GetNewBlockReward();

            headerMsg.Bits             = work.CalculateNextWorkTarget(lastBlockHeight, lastBlockBits, previous4032Block);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccount.Id);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);

            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            return(newBlockMsg);
        }
Exemple #7
0
        /// <summary>
        /// 创建新的区块
        /// </summary>
        /// <param name="minerName"></param>
        /// <param name="generatorId"></param>
        /// <param name="accountId"></param>
        /// <returns></returns>
        public BlockMsg CreateNewBlock(string minerName, string generatorId, string remark = null, string accountId = null)
        {
            var accountDac      = AccountDac.Default;
            var blockDac        = BlockDac.Default;
            var txDac           = TransactionDac.Default;
            var txPool          = TransactionPool.Instance;
            var txComponent     = new TransactionComponent();
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight    = -1;
            string lastBlockHash      = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits      = -1;
            string lastBlockGenerator = null;

            //获取最后一个区块
            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight    = blockEntity.Header.Height;
                lastBlockHash      = blockEntity.Header.Hash;
                lastBlockBits      = blockEntity.Header.Bits;
                lastBlockGenerator = blockEntity.Header.GeneratorId;
            }

            long totalSize   = 0;
            long totalInput  = 0;
            long totalOutput = 0;
            long totalAmount = 0;
            long totalFee    = 0;

            long maxSize = Consensus.BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);

            //获取待打包的交易
            var txs = txPool.GetTxsWithoutRepeatCost(10, maxSize);

            var hashIndexs = new List <string>();

            foreach (var tx in txs)
            {
                totalSize   += tx.Size;
                totalInput  += tx.InputCount;
                totalOutput += tx.OutputCount;
                hashIndexs.AddRange(tx.Inputs.Select(x => $"{x.OutputTransactionHash}_{x.OutputIndex}"));
                long totalOutputAmount = tx.Outputs.Sum(x => x.Amount);
                totalAmount += totalOutputAmount;
            }
            var utxos            = UtxoSetDac.Default.Get(hashIndexs);
            var totalInputAmount = utxos.Sum(x => x.Amount);

            totalFee = totalInputAmount - totalAmount;

            transactionMsgs.AddRange(txs);

            var accounts     = AccountDac.Default.SelectAll();
            var minerAccount = accounts.OrderBy(x => x.Timestamp).FirstOrDefault();

            if (accountId != null)
            {
                var account = accounts.FirstOrDefault(x => x.Id == accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            var            minerAccountId = minerAccount.Id;
            BlockMsg       newBlockMsg    = new BlockMsg();
            BlockHeaderMsg headerMsg      = new BlockHeaderMsg();

            headerMsg.Hash              = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.GeneratorId       = generatorId;
            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;

            if (headerMsg.Height == 0)
            {
                minerAccountId = Consensus.BlockSetting.GenesisBlockReceiver;
                remark         = Consensus.BlockSetting.GenesisBlockRemark;
            }

            BlockMsg prevBlockMsg     = null;
            BlockMsg prevStepBlockMsg = null;

            if (blockEntity != null)
            {
                prevBlockMsg = blockEntity;
            }

            if (headerMsg.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                var prevStepHeight = 0L;
                if (!GlobalParameters.IsTestnet && headerMsg.Height <= POC.DIFFICULTY_CALCULATE_LOGIC_ADJUST_HEIGHT)
                {
                    prevStepHeight = headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1;
                }
                else
                {
                    prevStepHeight = headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP;
                }
                prevStepBlockMsg = blockDac.SelectByHeight(prevStepHeight);
            }

            var newBlockReward = POC.GetNewBlockReward(headerMsg.Height);

            headerMsg.Bits             = POC.CalculateBaseTarget(headerMsg.Height, prevBlockMsg, prevStepBlockMsg);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName, remark);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccountId);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            if (newBlockReward < 0 || totalFee < 0 || coinbaseOutputMsg.Amount < 0)
            {
                LogHelper.Warn($"newBlockReward:{newBlockReward}");
                LogHelper.Warn($"totalFee:{totalFee}");
                LogHelper.Warn($"coinbaseOutputMsg.Amount:{coinbaseOutputMsg.Amount}");
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_OUTPUT_AMOUNT_ERROR);
            }

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);


            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            headerMsg.PayloadHash = newBlockMsg.GetPayloadHash();

            LogHelper.Warn($"{headerMsg.Height}::{headerMsg.PayloadHash}");
            LogHelper.Warn($"PayloadHash::{headerMsg.PayloadHash}");
            LogHelper.Warn($"BlockSignature::{headerMsg.BlockSignature}");
            LogHelper.Warn($"miner::{minerName}");

            headerMsg.BlockSignature   = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.BlockSigSize     = headerMsg.BlockSignature.Length;
            headerMsg.TotalTransaction = newBlockMsg.Transactions.Count;
            return(newBlockMsg);
        }