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); }
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); }
//Check whether output has been spent or contained in another transaction, true = spent, false = unspent private bool checkOutputSpent(string currentTxHash, string outputTxHash, int outputIndex) { var outputDac = new OutputDac(); var inputDac = new InputDac(); var txDac = new TransactionDac(); var blockDac = new BlockDac(); var outputEntity = outputDac.SelectByHashAndIndex(outputTxHash, outputIndex); var inputEntity = inputDac.SelectByOutputHash(outputTxHash, outputIndex); if (inputEntity != null && inputEntity.TransactionHash != currentTxHash) { var tx = txDac.SelectByHash(inputEntity.TransactionHash); if (tx != null) { var blockEntity = blockDac.SelectByHash(tx.BlockHash); if (blockEntity != null && blockEntity.IsVerified) { return(true); } } } return(false); }
public void RefreshUtxoSet(string accountId) { var outputDac = new OutputDac(); var accountDac = new AccountDac(); var txDac = new TransactionDac(); var account = accountDac.SelectById(accountId); if (account != null && UtxoSet.Instance != null) { var set = UtxoSet.Instance.GetUtxoSetByAccountId(accountId); if (set != null) { set.Clear(); //load from database var outputsInDB = outputDac.SelectUnspentByReceiverId(accountId); foreach (var output in outputsInDB) { var msg = new UtxoMsg(); msg.AccountId = output.ReceiverId; msg.TransactionHash = output.TransactionHash; msg.OutputIndex = output.Index; msg.Amount = output.Amount; msg.IsConfirmed = true; msg.IsWatchedOnly = account.WatchedOnly; var txEntity = txDac.SelectByHash(output.TransactionHash); msg.BlockHash = txEntity != null ? txEntity.BlockHash : null; set.Add(msg); } //load from transaction pool var outputsInTxPool = TransactionPool.Instance.GetTransactionOutputsByAccountId(accountId); foreach (var txHash in outputsInTxPool.Keys) { foreach (var output in outputsInTxPool[txHash]) { var msg = new UtxoMsg(); msg.AccountId = accountId; msg.TransactionHash = txHash; msg.OutputIndex = output.Index; msg.Amount = output.Amount; msg.IsConfirmed = false; msg.IsWatchedOnly = account.WatchedOnly; set.Add(msg); } } } } }
private bool existsInDB(string transactionHash) { var transactionDac = new TransactionDac(); if (transactionDac.HasTransactionByHash(transactionHash)) { return(true); } return(false); }
/// <summary> /// 估算交易费率 /// </summary> /// <returns></returns> public long EstimateSmartFee() { //对象初始化 var txDac = new TransactionDac(); var transactionMsgs = new List <TransactionMsg>(); var txPool = TransactionPool.Instance; long totalSize = 0; long totalFee = 0; //设置最大上限 long maxSize = BlockSetting.MAX_BLOCK_SIZE - (1 * 1024); //交易池中的项目按照费率从高到低排列 List <TransactionPoolItem> poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList(); var index = 0; while (totalSize < maxSize && index < poolItemList.Count) { //获取totalFee和totalSize TransactionMsg tx = poolItemList[index].Transaction; //判断交易Hash是否在交易Msg中 if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0) { totalFee += Convert.ToInt64(poolItemList[index].FeeRate * tx.Serialize().LongLength / 1024.0); if (txDac.SelectByHash(tx.Hash) == null) { transactionMsgs.Add(tx); totalSize += tx.Size; } else { txPool.RemoveTransaction(tx.Hash); } } /* * else * { * break; * } */ index++; } //获取费率 if (poolItemList.Count == 0) { return(1024); } long feeRate = Convert.ToInt64(Math.Ceiling((totalFee / (totalSize / 1024.0)) / poolItemList.Count)); if (feeRate < 1024) { feeRate = 1024; } return(feeRate); }
public List <Transaction> GetTransactionEntitiesContainUnspentUTXO() { var items = new TransactionDac().SelectTransactionsContainUnspentUTXO(); return(items); //var result = new List<TransactionMsg>(); //foreach(var item in items) //{ // result.Add(this.convertTxEntityToMsg(item)); //} //return result; }
public TransactionMsg GetTransactionMsgByHash(string txHash) { var txDac = new TransactionDac(); var entity = txDac.SelectByHash(txHash); if (entity != null) { return(this.ConvertTxEntityToMsg(entity)); } else { return(TransactionPool.Instance.GetTransactionByHash(txHash)); } }
public BlockMsg GetBlockMsgByHeight(long height) { var blockDac = new BlockDac(); var txDac = new TransactionDac(); BlockMsg block = null; var items = blockDac.SelectByHeight(height); if (items.Count > 0) { block = this.convertEntityToBlockMsg(items[0]); } return(block); }
public BlockMsg GetBlockMsgByHash(string hash) { var blockDac = new BlockDac(); var txDac = new TransactionDac(); BlockMsg block = null; var entity = blockDac.SelectByHash(hash); if (entity != null) { block = this.convertEntityToBlockMsg(entity); } return(block); }
public TransactionMsg GetTransactionMsgFromDB(string txHash, out string blockHash) { var txDac = new TransactionDac(); var entity = txDac.SelectByHash(txHash); blockHash = null; if (entity != null) { blockHash = entity.BlockHash; return(this.ConvertTxEntityToMsg(entity)); } else { return(null); } }
public List <BlockMsg> GetBlockMsgByHeights(List <long> heights) { var blockDac = new BlockDac(); var txDac = new TransactionDac(); var inputDac = new InputDac(); var outputDac = new OutputDac(); var blocks = new List <BlockMsg>(); foreach (var height in heights) { var items = blockDac.SelectByHeight(height); foreach (var entity in items) { blocks.Add(this.convertEntityToBlockMsg(entity)); } } return(blocks); }
public bool CheckTxExisted(string txHash) { var dac = new TransactionDac(); if (dac.SelectByHash(txHash) != null) { return(true); } else { var hashes = this.GetAllHashesFromPool(); if (hashes.Contains(txHash)) { return(true); } else { return(false); } } }
public Transaction GetTransactionEntityByHash(string hash) { var inputDac = new InputDac(); var outputDac = new OutputDac(); var item = new TransactionDac().SelectByHash(hash); if (item != null) { item.Inputs = inputDac.SelectByTransactionHash(item.Hash); item.Outputs = outputDac.SelectByTransactionHash(item.Hash); } else { var msg = TransactionPool.Instance.GetTransactionByHash(hash); if (msg != null) { item = this.ConvertTxMsgToEntity(msg); } } return(item); }
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); }
//check whether output is existed. get amount and lockscript from output. private bool getOutput(string transactionHash, int outputIndex, out long outputAmount, out string lockScript, out long blockHeight) { var outputDac = new OutputDac(); var outputEntity = outputDac.SelectByHashAndIndex(transactionHash, outputIndex); if (outputEntity == null) { long height = -1; var outputMsg = TransactionPool.Instance.GetOutputMsg(transactionHash, outputIndex); if (outputMsg != null) { outputAmount = outputMsg.Amount; lockScript = outputMsg.LockScript; blockHeight = height; return(true); } } else { outputAmount = outputEntity.Amount; lockScript = outputEntity.LockScript; var tx = new TransactionDac().SelectByHash(outputEntity.TransactionHash); if (tx != null) { var blockEntity = new BlockDac().SelectByHash(tx.BlockHash); blockHeight = blockEntity.Height; return(true); } } outputAmount = 0; lockScript = null; blockHeight = -1; return(false); }
//public List<UtxoMsg> GetAllConfirmedOutputs() //{ // return UtxoSet.Instance.GetAllUnspentOutputs(); //} public List <UtxoMsg> GetAllConfirmedOutputs() { List <UtxoMsg> utxoMsgs = new List <UtxoMsg>(); var outputDac = new OutputDac(); var txDac = new TransactionDac(); var blockDac = new BlockDac(); var accountDac = new AccountDac(); var lastHeight = -1L; var lastBlock = blockDac.SelectLast(); if (lastBlock != null) { lastHeight = lastBlock.Height; } var outputs = outputDac.SelectAllUnspentOutputs(); foreach (var output in outputs) { var msg = new UtxoMsg(); msg.AccountId = output.ReceiverId; msg.TransactionHash = output.TransactionHash; msg.OutputIndex = output.Index; msg.Amount = output.Amount; msg.IsConfirmed = true; var account = accountDac.SelectById(msg.AccountId); msg.IsWatchedOnly = account.WatchedOnly; var txEntity = txDac.SelectByHash(output.TransactionHash); msg.BlockHash = txEntity != null ? txEntity.BlockHash : null; utxoMsgs.Add(msg); } return(utxoMsgs); }
/// <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 void SaveBlockIntoDB(BlockMsg msg) { try { VerifyBlock(msg); Block block = this.convertBlockMsgToEntity(msg); block.IsDiscarded = false; block.IsVerified = false; var blockDac = new BlockDac(); var transactionDac = new TransactionDac(); var inputDac = new InputDac(); var outputDac = new OutputDac(); //foreach (var tx in block.Transactions) //{ // foreach (var input in tx.Inputs) // { // if (input.OutputTransactionHash != Base16.Encode(HashHelper.EmptyHash())) // { // var output = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex); // if (output != null) // { // input.AccountId = output.ReceiverId; // outputDac.UpdateSpentStatus(input.OutputTransactionHash, input.OutputIndex); // } // } // } //} blockDac.Save(block); //update nextblock hash //blockDac.UpdateNextBlockHash(block.PreviousBlockHash, block.Hash); //remove transactions in tx pool foreach (var tx in block.Transactions) { TransactionPool.Instance.RemoveTransaction(tx.Hash); //save into utxo set foreach (var output in tx.Outputs) { var accountId = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(output.LockScript) ) ); UtxoSet.Instance.AddUtxoRecord(new UtxoMsg { AccountId = accountId, BlockHash = block.Hash, TransactionHash = tx.Hash, OutputIndex = output.Index, Amount = output.Amount, IsConfirmed = true }); } } } catch (Exception ex) { LogHelper.Error(ex.Message, ex); throw ex; } }
public void GetBalanceInDB(out long confirmedBalance, out long unconfirmedBalance) { //return new OutputDac().SumSelfUnspentOutputs(); confirmedBalance = 0; unconfirmedBalance = 0; var outputDac = new OutputDac(); var txDac = new TransactionDac(); var blockDac = new BlockDac(); var lastHeight = -1L; var lastBlock = blockDac.SelectLast(); if (lastBlock != null) { lastHeight = lastBlock.Height; } var outputs = outputDac.SelectAllUnspentOutputs(); foreach (var output in outputs) { var tx = txDac.SelectByHash(output.TransactionHash); if (tx != null) { var block = blockDac.SelectByHash(tx.BlockHash); if (block != null) { if (tx.TotalInput == 0) { //coinbase if (lastHeight - block.Height >= 100) { confirmedBalance += output.Amount; } else { unconfirmedBalance += output.Amount; } } else { if (block.IsVerified) { if (Time.EpochTime >= tx.LockTime) { confirmedBalance += output.Amount; } else { unconfirmedBalance += output.Amount; } } else { unconfirmedBalance += output.Amount; } } } } } }
public List <Transaction> SearchTransactionEntities(string account, int count, int skip = 0, bool includeWatchOnly = true) { var inputDac = new InputDac(); var outputDac = new OutputDac(); var items = new TransactionDac().SelectTransactions(account, count, skip, includeWatchOnly); var accounts = new AccountDac().SelectAll(); foreach (var item in items) { item.Inputs = inputDac.SelectByTransactionHash(item.Hash); item.Outputs = outputDac.SelectByTransactionHash(item.Hash); } if (skip == 0) { var txList = TransactionPool.Instance.GetAllTransactions(); bool containsUnconfirmedTx = false; foreach (var tx in txList) { var entity = this.ConvertTxMsgToEntity(tx); bool isSendTransaction = false; if (entity != null) { foreach (var input in entity.Inputs) { if (accounts.Where(a => a.Id == input.AccountId).Count() > 0) { items.Add(entity); isSendTransaction = true; containsUnconfirmedTx = true; break; } } if (!isSendTransaction) { foreach (var output in entity.Outputs) { if (accounts.Where(a => a.Id == output.ReceiverId).Count() > 0) { items.Add(entity); containsUnconfirmedTx = true; break; } } } } } if (containsUnconfirmedTx) { items = items.OrderByDescending(t => t.Timestamp).ToList(); } } //var result = new List<TransactionMsg>(); //foreach(var item in items) //{ // result.Add(convertTxEntityToMsg(item)); //} //return result; return(items); }
public void ProcessUncsonfirmedBlocks() { var blockDac = new BlockDac(); var txDac = new TransactionDac(); var txComponent = new TransactionComponent(); var utxoComponent = new UtxoComponent(); long lastHeight = this.GetLatestHeight(); long confirmedHeight = -1; var confirmedBlock = blockDac.SelectLastConfirmed(); var confirmedHash = Base16.Encode(HashHelper.EmptyHash()); if (confirmedBlock != null) { confirmedHeight = confirmedBlock.Height; confirmedHash = confirmedBlock.Hash; } if (lastHeight - confirmedHeight >= 6) { var blocks = blockDac.SelectByPreviousHash(confirmedHash); if (blocks.Count == 1) { blockDac.UpdateBlockStatusToConfirmed(blocks[0].Hash); this.ProcessUncsonfirmedBlocks(); } else if (blocks.Count > 1) { var countOfDescendants = new Dictionary <string, long>(); foreach (var block in blocks) { var count = blockDac.CountOfDescendants(block.Hash); if (!countOfDescendants.ContainsKey(block.Hash)) { countOfDescendants.Add(block.Hash, count); } } var dicSort = countOfDescendants.OrderBy(d => d.Value).ToList(); var lastItem = blocks.Where(b => b.Hash == dicSort[dicSort.Count - 1].Key).First(); var index = 0; while (index < dicSort.Count - 1) { var currentItem = blocks.Where(b => b.Hash == dicSort[index].Key).First(); if (lastHeight - currentItem.Height >= 6) { var txList = txDac.SelectByBlockHash(currentItem.Hash); //Skip coinbase tx for (int i = 1; i < txList.Count; i++) { var tx = txList[i]; var txMsg = txComponent.ConvertTxEntityToMsg(tx); txComponent.AddTransactionToPool(txMsg); } //remove coinbase from utxo UtxoSet.Instance.RemoveUtxoRecord(txList[0].Hash, 0); blockDac.UpdateBlockStatusToDiscarded(currentItem.Hash); index++; } else { break; } } if (dicSort.Count - index <= 1) { blockDac.UpdateBlockStatusToConfirmed(lastItem.Hash); this.ProcessUncsonfirmedBlocks(); } } } }
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); }