public bool EncryptWallet(string salt) { bool result = false; AccountDac adac = new AccountDac(); var aclist = adac.SelectAll(); foreach (var item in aclist) { item.PrivateKey = AES128.Encrypt(item.PrivateKey, salt); } try { var rows = adac.UpdatePrivateKeyAr(aclist); if (rows > -1) { SettingComponent sComponent = new SettingComponent(); var setting = sComponent.GetSetting(); setting.Encrypt = true; setting.PassCiphertext = MD5Helper.EncryptTo32(salt); sComponent.SaveSetting(setting); result = true; } } catch (Exception ex) { throw new CommonException(ErrorCode.Engine.Wallet.DB.EXECUTE_SQL_ERROR, ex); } return(result); }
public List <string> GetAllHashesRelevantWithCurrentWalletFromPool() { var accountIds = new AccountDac().SelectAll().Select(a => a.Id).ToList(); var txs = TransactionPool.Instance.GetAllTransactions(); var result = new List <string>(); foreach (var tx in txs) { bool isOK = false; var entity = this.ConvertTxMsgToEntity(tx); foreach (var input in entity.Inputs) { if (accountIds.Contains(input.AccountId)) { result.Add(tx.Hash); isOK = true; } } if (!isOK) { foreach (var output in entity.Outputs) { result.Add(tx.Hash); isOK = true; } } } return(result); }
//IAccountDac _accountDac; //public DAHAuthorize(IAccountDac accountDac) //{ // _accountDac = accountDac; //} public override void OnAuthorization(HttpActionContext actionContext) { AccountDac _accountDac = new AccountDac(); if (actionContext.Request.Headers.Authorization == null) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); } else { string authToken = actionContext.Request.Headers.Authorization.Parameter; string[] credentials = Encoding.UTF8.GetString(Convert.FromBase64String(authToken)).Split(':'); User user = _accountDac.GetUserDetails(new User() { Email = credentials[0], Password = credentials[1] }); if (user == null) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized); } else { Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(credentials[0]), user.Roles.ToArray()); } } }
public void DeleteAccount(string id) { var dac = new AccountDac(); dac.Delete(id); UtxoSet.Instance.RemoveAccountId(id); }
public void ChangePassword(string oldPassword, string newPassword) { SettingComponent sComponent = new SettingComponent(); var setting = sComponent.GetSetting(); if (MD5Helper.EncryptTo32(oldPassword) == setting.PassCiphertext) { AccountDac adac = new AccountDac(); var aclist = adac.SelectAll(); foreach (var item in aclist) { item.PrivateKey = AES128.Decrypt(item.PrivateKey, oldPassword); item.PrivateKey = AES128.Encrypt(item.PrivateKey, newPassword); } try { var rows = adac.UpdatePrivateKeyAr(aclist); if (rows > -1) { setting = sComponent.GetSetting(); setting.Encrypt = true; setting.PassCiphertext = MD5Helper.EncryptTo32(newPassword); sComponent.SaveSetting(setting); } } catch (Exception ex) { throw new CommonException(ErrorCode.Engine.Wallet.DB.EXECUTE_SQL_ERROR, ex); } } else { throw new CommonException(ErrorCode.Engine.Wallet.CHECK_PASSWORD_ERROR); } }
public Account ImportObservedAccount(string publicKeyText) { var dac = new AccountDac(); var publicKey = Base16.Decode(publicKeyText); var id = AccountIdHelper.CreateAccountAddress(publicKey); Account account = dac.SelectById(id); if (account == null) { account = new Account(); account.Id = AccountIdHelper.CreateAccountAddress(publicKey); account.PrivateKey = null; account.PublicKey = Base16.Encode(publicKey); account.Balance = 0; account.IsDefault = false; account.WatchedOnly = true; dac.Insert(account); UtxoSet.Instance.AddAccountId(account.Id); } return(account); }
public Account ImportAccount(string privateKeyText) { var dac = new AccountDac(); byte[] privateKey = Base16.Decode(privateKeyText); byte[] publicKey; using (var dsa = ECDsa.ImportPrivateKey(privateKey)) { publicKey = dsa.PublicKey; } var id = AccountIdHelper.CreateAccountAddress(publicKey); Account account = dac.SelectById(id); if (account == null) { account = new Account(); account.Id = AccountIdHelper.CreateAccountAddress(publicKey); account.PrivateKey = Base16.Encode(privateKey); account.PublicKey = Base16.Encode(publicKey); account.Balance = 0; account.IsDefault = false; account.WatchedOnly = false; dac.Insert(account); UtxoSet.Instance.AddAccountId(account.Id); } return(account); }
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); } } } } }
public void Initialize() { var accountDac = new AccountDac(); var accountIds = accountDac.SelectAll().Select(a => a.Id).ToArray(); UtxoSet.Initialize(accountIds); foreach (var id in accountIds) { this.RefreshUtxoSet(id); } }
public TransactionMsg CreateNewTransactionMsg(List <UtxoMsg> utxos, Dictionary <string, long> receiverIdAndValues) { var outputDac = new OutputDac(); var accountDac = new AccountDac(); var transaction = new TransactionMsg(); transaction.Timestamp = Time.EpochTime; transaction.Locktime = 0; foreach (var utxo in utxos) { var account = accountDac.SelectById(utxo.AccountId); if (account == null || account.WatchedOnly) { //TODO: throw exception; return(null); } var privateKey = account.PrivateKey; var inputMsg = new InputMsg(); inputMsg.OutputTransactionHash = utxo.TransactionHash; inputMsg.OutputIndex = utxo.OutputIndex; inputMsg.UnlockScript = Script.BuildUnlockScript(utxo.TransactionHash, utxo.OutputIndex, Base16.Decode(privateKey), Base16.Decode(account.PublicKey)); inputMsg.Size = inputMsg.UnlockScript.Length; transaction.Inputs.Add(inputMsg); outputDac.UpdateSpentStatus(utxo.TransactionHash, utxo.OutputIndex); } int index = 0; foreach (var key in receiverIdAndValues.Keys) { var value = receiverIdAndValues[key]; var outputMsg = new OutputMsg(); outputMsg.Index = index; outputMsg.Amount = value; outputMsg.LockScript = Script.BuildLockScipt(key); outputMsg.Size = outputMsg.LockScript.Length; transaction.Outputs.Add(outputMsg); index++; } transaction.Hash = transaction.GetHash(); return(transaction); }
//result is List<txid + "," + vout> public long GetAllUnconfirmedBalance() { var accountDac = new AccountDac(); long totalAmount = 0; foreach (var item in TransactionPool.Instance.MainPool) { foreach (var output in item.Transaction.Outputs) { var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(output.LockScript))); if (accountDac.SelectById(address) != null) { totalAmount += output.Amount; } } } return(totalAmount); }
public Account ImportPublicKeyAndAddress(string filePath, string salt) { Account result = null; string extensionName = Path.GetExtension(filePath).ToLower(); if (extensionName != encryptExtensionName && extensionName != noEncryptExtensionName) { throw new CommonException(ErrorCode.Engine.Wallet.IO.EXTENSION_NAME_NOT_SUPPORT); } WatchAccountBackup backup = null; try { if (extensionName == noEncryptExtensionName) { backup = LoadFile <WatchAccountBackup>(filePath, null); } else { backup = LoadFile <WatchAccountBackup>(filePath, salt); } if (backup != null) { AccountDac dac = AccountDac.Default; dac.Insert(new Account { Balance = 0, Id = backup.Address, IsDefault = false, PrivateKey = null, PublicKey = backup.PublicKey, Tag = "", Timestamp = Time.EpochTime, WatchedOnly = true }); result = dac.SelectById(backup.Address); } } catch (Exception ex) { throw new CommonException(ErrorCode.Engine.Wallet.DB.EXECUTE_SQL_ERROR, ex); } return(result); }
public Account GenerateNewAccount() { var dac = new AccountDac(); byte[] privateKey; byte[] publicKey; using (var dsa = ECDsa.GenerateNewKeyPair()) { privateKey = dsa.PrivateKey; publicKey = dsa.PublicKey; } var id = AccountIdHelper.CreateAccountAddress(publicKey); if (dac.IsExisted(id)) { throw new Exception("Account id is existed"); } Account account = new Account(); account.Id = id; account.PrivateKey = Base16.Encode(privateKey); account.PublicKey = Base16.Encode(publicKey); account.Balance = 0; account.IsDefault = false; account.WatchedOnly = false; dac.Insert(account); if (UtxoSet.Instance != null) { UtxoSet.Instance.AddAccountId(account.Id); } return(account); }
//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); }
public void UpdateBalance(string id, long amount) { var dac = new AccountDac(); dac.UpdateBalance(id, amount); }
public void SetDefaultAccount(string id) { var dac = new AccountDac(); dac.SetDefaultAccount(id); }
public Account GetDefaultAccount() { var dac = new AccountDac(); return(dac.SelectDefaultAccount()); }
public Account GetAccountById(string id) { var dac = new AccountDac(); return(dac.SelectById(id)); }
public List <Account> GetAllAccounts() { var dac = new AccountDac(); return(dac.SelectAll()); }
public void AddTransactionToPool(TransactionMsg transaction) { var accountDac = new AccountDac(); var outputDac = new OutputDac(); long feeRate = 0; long totalInput = 0; long totalOutput = 0; foreach (var input in transaction.Inputs) { long amount; string lockCript; long blockHeight; if (this.getOutput(input.OutputTransactionHash, input.OutputIndex, out amount, out lockCript, out blockHeight)) { totalInput += amount; } } foreach (var output in transaction.Outputs) { totalOutput += output.Amount; } feeRate = (totalInput - totalOutput) / transaction.Size; try { long fee = 0; var result = this.VerifyTransaction(transaction, out fee); if (result) { TransactionPool.Instance.AddNewTransaction(feeRate, transaction); //recheck isolate transactions var txList = TransactionPool.Instance.GetIsolateTransactions(); foreach (var tx in txList) { try { if (this.VerifyTransaction(tx, out fee)) { TransactionPool.Instance.MoveIsolateTransactionToMainPool(tx.Hash); } } catch { } } } else { TransactionPool.Instance.AddIsolateTransaction(feeRate, transaction); } foreach (var input in transaction.Inputs) { outputDac.UpdateSpentStatus(input.OutputTransactionHash, input.OutputIndex); UtxoSet.Instance.RemoveUtxoRecord(input.OutputTransactionHash, input.OutputIndex); } foreach (var output in transaction.Outputs) { var accountId = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(output.LockScript) ) ); UtxoSet.Instance.AddUtxoRecord(new UtxoMsg { AccountId = accountId, BlockHash = null, TransactionHash = transaction.Hash, OutputIndex = output.Index, Amount = output.Amount, IsConfirmed = false }); } } catch (CommonException ex) { throw ex; } }
public TransactionMsg CreateNewTransactionMsg(string senderAccountId, Dictionary <string, long> receiverIdAndValues, long fee) { var outputDac = new OutputDac(); var accountDac = new AccountDac(); var account = accountDac.SelectById(senderAccountId); if (account == null || account.WatchedOnly) { //TODO: throw exception; return(null); } var balance = UtxoSet.Instance.GetAccountBlanace(senderAccountId, true); long totalOutput = fee; long totalInput = 0; foreach (var key in receiverIdAndValues.Keys) { totalOutput += receiverIdAndValues[key]; } if (totalOutput > balance) { //TODO: throw exception return(null); } var transaction = new TransactionMsg(); transaction.Timestamp = Time.EpochTime; transaction.Locktime = 0; var outputs = outputDac.SelectUnspentByReceiverId(senderAccountId); foreach (var output in outputs) { var inputMsg = new InputMsg(); inputMsg.OutputTransactionHash = output.TransactionHash; inputMsg.OutputIndex = output.Index; inputMsg.UnlockScript = Script.BuildUnlockScript(output.TransactionHash, output.Index, Base16.Decode(account.PrivateKey), Base16.Decode(account.PublicKey)); inputMsg.Size = inputMsg.UnlockScript.Length; transaction.Inputs.Add(inputMsg); outputDac.UpdateSpentStatus(output.TransactionHash, output.Index); totalInput += output.Amount; if (totalInput >= totalOutput) { break; } } int index = 0; foreach (var key in receiverIdAndValues.Keys) { var value = receiverIdAndValues[key]; var outputMsg = new OutputMsg(); outputMsg.Index = index; outputMsg.Amount = value; outputMsg.LockScript = Script.BuildLockScipt(key); outputMsg.Size = outputMsg.LockScript.Length; transaction.Outputs.Add(outputMsg); index++; } if (totalInput > totalOutput) { var value = totalInput - totalOutput; var outputMsg = new OutputMsg(); outputMsg.Index = index; outputMsg.Amount = value; outputMsg.LockScript = Script.BuildLockScipt(senderAccountId); outputMsg.Size = outputMsg.LockScript.Length; transaction.Outputs.Add(outputMsg); index++; } transaction.Hash = transaction.GetHash(); return(transaction); }
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); }
/// <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); }