public string GetAccountByLockScript(string lockScript) { var publicKeyHash = Base16.Decode(Script.GetPublicKeyHashFromLockScript(lockScript)); var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(publicKeyHash); return(address); }
private void getOutputsByAccountId(BlockPoolItem node, string accountId, Dictionary <string, List <OutputMsg> > dict) { foreach (var tx in node.Block.Transactions) { if (!dict.ContainsKey(tx.Hash)) { dict.Add(tx.Hash, new List <OutputMsg>()); } foreach (var output in tx.Outputs) { var publicKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript); var id = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(publicKeyHash)); if (id == accountId) { dict[tx.Hash].Add(output); } } } foreach (var child in node.Children) { getOutputsByAccountId(child, accountId, dict); } }
public Account GenerateNewAccount(bool isAddtoCache = true) { var dac = AccountDac.Default; 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; AccountDac.Default.Insert(account); return(account); }
public Dictionary <string, List <OutputMsg> > GetTransactionOutputsByAccountId(string accountId) { var dict = new Dictionary <string, List <OutputMsg> >(); foreach (var item in this.MainPool) { var tx = item.Transaction; if (!dict.ContainsKey(tx.Hash)) { dict.Add(tx.Hash, new List <OutputMsg>()); } foreach (var output in tx.Outputs) { var publicKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript); var id = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(publicKeyHash)); if (id == accountId) { dict[tx.Hash].Add(output); } } } return(dict); }
public Account GenerateWatchOnlyAddress(string publickeyText) { var dac = AccountDac.Default; byte[] publickey = Base16.Decode(publickeyText); string id = AccountIdHelper.CreateAccountAddress(publickey); Account account = dac.SelectById(id); if (account == null) { account = new Account(); account.Id = id; account.PrivateKey = ""; account.PublicKey = publickeyText; account.Balance = 0; account.IsDefault = false; account.WatchedOnly = true; AccountDac.Default.Insert(account); //UtxoSet.Instance.AddAccountId(account.Id); } return(account); }
public Account ImportAccount(string privateKeyText) { var dac = AccountDac.Default; 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; AccountDac.Default.Insert(account); } return(account); }
/// <summary> /// 存币交易分析处理 /// </summary> /// <param name="successBlock"></param> private static void ProcessDepositTx(BlockMsg successBlock) { if (successBlock == null || successBlock.Transactions == null || !successBlock.Transactions.Any()) { return; } List <DepositList> toInsert = new List <DepositList>(); successBlock.Transactions.ForEach(x => { if (x.DepositTime > 0 && x.Outputs != null && x.Outputs.Any()) { x.Outputs.ForEach(o => { var receiverId = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(o.LockScript) )); var dep = new DepositList() { Address = receiverId, Amount = o.Amount, ExpireTime = x.DepositTime, IsExpired = x.DepositTime < Time.EpochTime ? 1:0, TransactionHash = x.Hash }; toInsert.Add(dep); }); } }); if (toInsert.Any()) { new RewardListComponent().InsertDeposit(toInsert); } }
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 List <TransactionMsg> SearchByAccountId(string accountId) { var publicKeyText = Base16.Encode( AccountIdHelper.GetPublicKeyHash(accountId) ); var result = this.MainPool.Where(t => t.Transaction.Outputs.Where(o => o.LockScript.Contains(publicKeyText)).Count() > 0). Select(t => t.Transaction).ToList(); return(result); }
public IRpcMethodResult ValidateAddress(string address) { try { var result = new ValidateAddressOM(); var accountComponent = new AccountComponent(); result.address = address; if (AccountIdHelper.AddressVerify(address)) { result.isValid = true; var account = accountComponent.GetAccountById(address); if (account != null) { result.isMine = true; result.isWatchOnly = string.IsNullOrWhiteSpace(account.PrivateKey); } else { result.isMine = false; } result.scriptPubKey = Script.BuildLockScipt(address); result.isScript = false; result.script = "P2PKH"; result.hex = null; result.addresses = null; result.pubKey = account.PublicKey; result.isCompressed = false; result.account = account.Tag; result.hdKeyPath = null; result.hdMasterKeyId = null; } else { result.isValid = false; } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public void Initialize() { DtoExtensions.GetAccountByLockScript = lockScript => AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(Script.GetPublicKeyHashFromLockScript(lockScript))); OmniCoin.Update.StartUp.Start(); DbDomains.Init(); RepairBlockData(); RepairUtxoSet(); MiningPoolComponent.LoadMiningPools(); DbDomains.InitData(); LogHelper.Info("Load Data Completed"); }
public CommonResponse GetScoopNumber(string address) { try { try { if (!AccountIdHelper.AddressVerify(address)) { return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {address} is invalid")); } } catch { return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {address} is invalid")); } var miner = MinersJob.Current.Pool_Miners.FirstOrDefault(m => m.Address == address); if (miner == null) { return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_NOT_EXIST, $"Address {address} is not exist")); } var key = "Pool:MinerScoopNumber:" + address; var scoopNumber = RedisManager.Current.GetDataInRedis <string>(key); var ttl = RedisManager.Current.PTtl(key); if (string.IsNullOrWhiteSpace(scoopNumber) || ttl < 10 * 1000) { var random = new Random(); scoopNumber = random.Next(0, 4096).ToString(); RedisManager.Current.SaveDataToRedis(key, scoopNumber.ToString(), ScoopNumberTimeout); } return(OK(scoopNumber)); } catch (ApiCustomException ce) { LogHelper.Error(ce.Message, ce); return(Error(ce.ErrorCode, ce.ErrorMessage)); } catch (Exception ex) { LogHelper.Error(ex.Message, ex); return(Error(ex.HResult, ex.Message)); } }
public static Output ConvertToEntiry(this OutputMsg outputMsg, TransactionMsg transaction, BlockMsg blockMsg) { Output output = new Output(); output.Amount = outputMsg.Amount; output.BlockHash = blockMsg.Header.Hash; output.Index = outputMsg.Index; output.LockScript = outputMsg.LockScript; output.Size = outputMsg.Size; output.Index = transaction.Outputs.IndexOf(outputMsg); output.TransactionHash = transaction.Hash; output.Spent = false; output.IsDiscarded = false; var receiverId = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript) )); output.ReceiverId = receiverId; return(output); }
//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 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 static Transaction ConvertTxMsgToEntity(this TransactionMsg txMsg, bool isSelf = false) { var entity = new Transaction(); entity.Hash = txMsg.Hash; entity.BlockHash = null; entity.Version = txMsg.Version; entity.Timestamp = txMsg.Timestamp; entity.LockTime = txMsg.Locktime; entity.Inputs = new List <Input>(); entity.Outputs = new List <Output>(); long totalInput = 0L; long totalOutput = 0L; foreach (var inputMsg in txMsg.Inputs) { var input = new Input(); input.TransactionHash = txMsg.Hash; input.OutputTransactionHash = inputMsg.OutputTransactionHash; input.OutputIndex = inputMsg.OutputIndex; input.Size = inputMsg.Size; input.UnlockScript = inputMsg.UnlockScript; var utxo = UtxoSetDac.Default.Get(inputMsg.OutputTransactionHash, inputMsg.OutputIndex); if (utxo != null) { input.Amount = utxo.Amount; input.AccountId = utxo.Account; input.BlockHash = utxo.BlockHash; } else { input.Amount = 0; input.AccountId = ""; } entity.Inputs.Add(input); totalInput += input.Amount; } foreach (var outputMsg in txMsg.Outputs) { var output = new Output(); output.Index = outputMsg.Index; output.TransactionHash = entity.Hash; var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript) )); output.ReceiverId = address; output.Amount = outputMsg.Amount; output.Size = outputMsg.Size; output.LockScript = outputMsg.LockScript; entity.Outputs.Add(output); totalOutput += output.Amount; } entity.TotalInput = totalInput; entity.TotalOutput = totalOutput; entity.Fee = totalInput - totalOutput; entity.Size = txMsg.Size; var coinbaseHashIndex = $"{txMsg.Hash}_{0}"; var utxoset = UtxoSetDac.Default.Get(coinbaseHashIndex); entity.BlockHash = utxoset?.BlockHash; if (txMsg.Inputs.Count == 1 && txMsg.Outputs.Count == 1 && txMsg.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { entity.Fee = 0; } return(entity); }
public IRpcMethodResult ListUnspent(int minConfirmations, int maxConfirmations = 9999999, string[] addresses = null) { try { var result = new List <ListUnspentOM>(); var txComponent = new TransactionComponent(); var blockComponent = new BlockComponent(); var outputComponent = new UtxoComponent(); var accountComponent = new AccountComponent(); var addressBookComponent = new AddressBookComponent(); var accounts = accountComponent.GetAllAccounts(); var transactions = txComponent.GetTransactionEntitiesContainUnspentUTXO(); var latestHeight = blockComponent.GetLatestHeight(); foreach (var tx in transactions) { var blockMsg = blockComponent.GetBlockMsgByHash(tx.BlockHash); if (blockMsg != null) { var confirmations = latestHeight - blockMsg.Header.Height; if (confirmations >= minConfirmations && confirmations <= maxConfirmations) { var outputs = txComponent.GetOutputEntitesByTxHash(tx.Hash); foreach (var output in outputs) { var pubKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript); var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(pubKeyHash)); var account = accounts.Where(a => a.Id == address).FirstOrDefault(); if (account != null) { if (addresses == null || addresses.Contains(address)) { result.Add(new ListUnspentOM { txid = output.TransactionHash, vout = output.Index, address = address, account = addressBookComponent.GetTagByAddress(address), scriptPubKey = output.LockScript, redeemScript = null, amount = output.Amount, confirmations = confirmations, spendable = string.IsNullOrWhiteSpace(account.PrivateKey), solvable = false }); } } } } } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
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 Transaction ConvertTxMsgToEntity(TransactionMsg txMsg) { var outputDac = new OutputDac(); var entity = new Transaction(); entity.Hash = txMsg.Hash; entity.BlockHash = null; entity.Version = txMsg.Version; entity.Timestamp = txMsg.Timestamp; entity.LockTime = txMsg.Locktime; entity.Inputs = new List <Input>(); entity.Outputs = new List <Output>(); long totalInput = 0L; long totalOutput = 0L; foreach (var inputMsg in txMsg.Inputs) { var input = new Input(); input.TransactionHash = txMsg.Hash; input.OutputTransactionHash = inputMsg.OutputTransactionHash; input.OutputIndex = inputMsg.OutputIndex; input.Size = inputMsg.Size; input.UnlockScript = inputMsg.UnlockScript; var output = outputDac.SelectByHashAndIndex(inputMsg.OutputTransactionHash, inputMsg.OutputIndex); if (output != null) { input.Amount = output.Amount; input.AccountId = output.ReceiverId; } entity.Inputs.Add(input); totalInput += input.Amount; } foreach (var outputMsg in txMsg.Outputs) { var output = new Output(); output.Index = outputMsg.Index; output.TransactionHash = entity.Hash; var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript) )); output.ReceiverId = address; output.Amount = outputMsg.Amount; output.Size = outputMsg.Size; output.LockScript = outputMsg.LockScript; entity.Outputs.Add(output); totalOutput += output.Amount; } entity.TotalInput = totalInput; entity.TotalOutput = totalOutput; entity.Fee = totalInput - totalOutput; entity.Size = txMsg.Size; if (txMsg.Inputs.Count == 1 && txMsg.Outputs.Count == 1 && txMsg.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { entity.Fee = 0; } return(entity); }
public static bool PoolAccount(string account) { return(AccountIdHelper.AddressVerify(account)); }
public IRpcMethodResult EstimateTxFeeForSendToAddress(string toAddress, long amount, string comment, string commentTo, bool deductFeeFromAmount) { try { EstimateTxFeeOM result = new EstimateTxFeeOM(); var utxoComponent = new UtxoComponent(); var txComponent = new TransactionComponent(); var settingComponent = new SettingComponent(); var addressBookComponent = new AddressBookComponent(); var accountComponent = new AccountComponent(); if (!AccountIdHelper.AddressVerify(toAddress)) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } var setting = settingComponent.GetSetting(); var utxos = utxoComponent.GetAllConfirmedOutputs(); var tx = new TransactionMsg(); var totalSize = tx.Serialize().Length; var output = new OutputMsg(); output.Amount = amount; output.Index = 0; output.LockScript = Script.BuildLockScipt(toAddress); output.Size = output.LockScript.Length; tx.Outputs.Add(output); totalSize += output.Serialize().Length; var blockComponent = new BlockComponent(); var lastBlockHeight = blockComponent.GetLatestHeight(); var totalInput = 0L; var index = 0; double totalAmount = amount; double totalFee = setting.FeePerKB * ((double)totalSize / 1024.0); while (index < utxos.Count) { var account = accountComponent.GetAccountById(utxos[index].AccountId); if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey)) { var utxoTX = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash); Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash); if (utxoTX == null || utxoBlock == null) { index++; continue; } if (!utxoBlock.IsVerified) { index++; continue; } if (Time.EpochTime < utxoTX.Locktime) { index++; continue; } if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { var blockHeight = utxoBlock.Height; if (lastBlockHeight - blockHeight < 100L) { index++; continue; } } var input = new InputMsg(); input.OutputTransactionHash = utxos[index].TransactionHash; input.OutputIndex = utxos[index].OutputIndex; input.UnlockScript = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey)); input.Size = input.UnlockScript.Length; tx.Inputs.Add(input); var size = input.Serialize().Length; totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); totalInput += utxos[index].Amount; } else { index++; continue; } if (!deductFeeFromAmount) { totalAmount = amount + totalFee; } if (totalInput >= (long)Math.Ceiling(totalAmount)) { var size = output.Serialize().Length; if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0)) { totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); } break; } index++; } if (totalInput < totalAmount) { throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH); } if (deductFeeFromAmount) { output.Amount -= (long)Math.Ceiling(totalFee); if (output.Amount <= 0) { throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE); } } result.totalFee = Convert.ToInt64(totalFee); result.totalSize = Convert.ToInt32(totalSize); return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public IRpcMethodResult SendMany(string fromAccount, SendManyOutputIM[] receivers, string[] feeDeductAddresses) { try { string result = null; var utxoComponent = new UtxoComponent(); var txComponent = new TransactionComponent(); var settingComponent = new SettingComponent(); var addressBookComponent = new AddressBookComponent(); var accountComponent = new AccountComponent(); var transactionCommentComponent = new TransactionCommentComponent(); var blockComponent = new BlockComponent(); var lastBlockHeight = blockComponent.GetLatestHeight(); var setting = settingComponent.GetSetting(); var utxos = utxoComponent.GetAllConfirmedOutputs(); var tx = new TransactionMsg(); double totalOutput = 0; var totalSize = tx.Serialize().Length; if (receivers == null || receivers.Length == 0) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } foreach (var receiver in receivers) { if (!AccountIdHelper.AddressVerify(receiver.address)) { throw new CommonException(ErrorCode.Service.Transaction.TO_ADDRESS_INVALID); } var output = new OutputMsg(); output.Amount = receiver.amount; output.Index = tx.Outputs.Count; output.LockScript = Script.BuildLockScipt(receiver.address); output.Size = output.LockScript.Length; tx.Outputs.Add(output); totalSize += output.Serialize().Length; totalOutput += receiver.amount; } foreach (var address in feeDeductAddresses) { if (receivers.Where(r => r.address == address).Count() == 0) { throw new CommonException(ErrorCode.Service.Transaction.FEE_DEDUCT_ADDRESS_INVALID); } } var totalInput = 0L; var index = 0; double totalFee = setting.FeePerKB * ((double)totalSize / 1024.0); double totalAmount = totalOutput; while (index < utxos.Count) { var account = accountComponent.GetAccountById(utxos[index].AccountId); if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey)) { var utxoTX = txComponent.GetTransactionMsgByHash(utxos[index].TransactionHash); Block utxoBlock = blockComponent.GetBlockEntiytByHash(utxos[index].BlockHash); if (utxoTX == null || utxoBlock == null) { index++; continue; } if (!utxoBlock.IsVerified) { index++; continue; } if (Time.EpochTime < utxoTX.Locktime) { index++; continue; } if (utxoTX.InputCount == 1 && utxoTX.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { var blockHeight = utxoBlock.Height; if (lastBlockHeight - blockHeight < 100L) { index++; continue; } } var input = new InputMsg(); input.OutputTransactionHash = utxos[index].TransactionHash; input.OutputIndex = utxos[index].OutputIndex; input.UnlockScript = Script.BuildUnlockScript(input.OutputTransactionHash, input.OutputIndex, Base16.Decode(decryptPrivateKey(account.PrivateKey)), Base16.Decode(account.PublicKey)); input.Size = input.UnlockScript.Length; tx.Inputs.Add(input); var size = input.Serialize().Length; totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); totalInput += utxos[index].Amount; } else { index++; continue; } if (feeDeductAddresses == null || feeDeductAddresses.Length == 0) { totalAmount = totalOutput + totalFee; } if (totalInput >= (long)Math.Ceiling(totalAmount)) { var size = tx.Outputs[0].Serialize().Length; if ((totalInput - (long)Math.Ceiling(totalAmount)) > (setting.FeePerKB * (double)size / 1024.0)) { totalSize += size; totalFee += setting.FeePerKB * ((double)size / 1024.0); if (feeDeductAddresses == null || feeDeductAddresses.Length == 0) { totalAmount = totalOutput + totalFee; } var newAccount = accountComponent.GenerateNewAccount(); if (setting.Encrypt) { if (!string.IsNullOrWhiteSpace(_cache.Get <string>("WalletPassphrase"))) { newAccount.PrivateKey = AES128.Encrypt(newAccount.PrivateKey, _cache.Get <string>("WalletPassphrase")); accountComponent.UpdatePrivateKeyAr(newAccount); } else { throw new CommonException(ErrorCode.Service.Wallet.WALLET_HAS_BEEN_LOCKED); } } var newOutput = new OutputMsg(); newOutput.Amount = totalInput - (long)Math.Ceiling(totalAmount); newOutput.Index = tx.Outputs.Count; newOutput.LockScript = Script.BuildLockScipt(newAccount.Id); newOutput.Size = newOutput.LockScript.Length; tx.Outputs.Add(newOutput); } break; } index++; } if (totalInput < totalAmount) { throw new CommonException(ErrorCode.Service.Transaction.BALANCE_NOT_ENOUGH); } if (feeDeductAddresses != null && feeDeductAddresses.Length > 0) { var averageFee = totalFee / feeDeductAddresses.Length; for (int i = 0; i < receivers.Length; i++) { if (feeDeductAddresses.Contains(receivers[i].address)) { tx.Outputs[i].Amount -= (long)Math.Ceiling(averageFee); if (tx.Outputs[i].Amount <= 0) { throw new CommonException(ErrorCode.Service.Transaction.SEND_AMOUNT_LESS_THAN_FEE); } } } } tx.Timestamp = Time.EpochTime; tx.Hash = tx.GetHash(); txComponent.AddTransactionToPool(tx); Startup.P2PBroadcastTransactionAction(tx.Hash); result = tx.Hash; for (int i = 0; i < receivers.Length; i++) { var receiver = receivers[i]; if (!string.IsNullOrWhiteSpace(receiver.tag)) { addressBookComponent.SetTag(receiver.address, receiver.tag); } if (!string.IsNullOrWhiteSpace(receiver.comment)) { transactionCommentComponent.Add(tx.Hash, i, receiver.comment); } } return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
private Block convertBlockMsgToEntity(BlockMsg blockMsg) { OutputDac outputDac = new OutputDac(); var block = new Block(); block.Hash = blockMsg.Header.Hash; block.Version = blockMsg.Header.Version; block.Height = blockMsg.Header.Height; block.PreviousBlockHash = blockMsg.Header.PreviousBlockHash; block.Bits = blockMsg.Header.Bits; block.Nonce = blockMsg.Header.Nonce; block.GeneratorId = blockMsg.Header.GeneratorId; block.Timestamp = blockMsg.Header.Timestamp; block.TotalAmount = 0; block.TotalFee = 0; block.Transactions = new List <Transaction>(); foreach (var txMsg in blockMsg.Transactions) { var transaction = new Transaction(); transaction.Hash = txMsg.Hash; transaction.BlockHash = block.Hash; transaction.Version = txMsg.Version; transaction.Timestamp = txMsg.Timestamp; transaction.LockTime = txMsg.Locktime; transaction.Inputs = new List <Input>(); transaction.Outputs = new List <Output>(); long totalInput = 0L; long totalOutput = 0L; foreach (var inputMsg in txMsg.Inputs) { var input = new Input(); input.TransactionHash = txMsg.Hash; input.OutputTransactionHash = inputMsg.OutputTransactionHash; input.OutputIndex = inputMsg.OutputIndex; input.Size = inputMsg.Size; input.UnlockScript = inputMsg.UnlockScript; var output = outputDac.SelectByHashAndIndex(inputMsg.OutputTransactionHash, inputMsg.OutputIndex); if (output != null) { input.Amount = output.Amount; input.AccountId = output.ReceiverId; } transaction.Inputs.Add(input); totalInput += input.Amount; } foreach (var outputMsg in txMsg.Outputs) { var output = new Output(); output.Index = outputMsg.Index; output.TransactionHash = transaction.Hash; var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash( Base16.Decode( Script.GetPublicKeyHashFromLockScript(outputMsg.LockScript) )); output.ReceiverId = address; output.Amount = outputMsg.Amount; output.Size = outputMsg.Size; output.LockScript = outputMsg.LockScript; transaction.Outputs.Add(output); totalOutput += output.Amount; } transaction.TotalInput = totalInput; transaction.TotalOutput = totalOutput; transaction.Fee = totalInput - totalOutput; transaction.Size = txMsg.Size; if (txMsg.Inputs.Count == 1 && txMsg.Outputs.Count == 1 && txMsg.Inputs[0].OutputTransactionHash == Base16.Encode(HashHelper.EmptyHash())) { transaction.Fee = 0; } block.Transactions.Add(transaction); block.TotalAmount += transaction.TotalOutput; block.TotalFee += transaction.Fee; } //block.GenerationSignature = blockMsg.Header.GenerationSignature; block.BlockSignature = blockMsg.Header.BlockSignature; //block.CumulativeDifficulty = blockMsg.Header.CumulativeDifficulty; block.PayloadHash = blockMsg.Header.PayloadHash; block.IsVerified = false; return(block); }
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 CommonResponse SubmitMaxNonce([FromBody] MaxNonceIM model) { try { if (model == null) { return(Error(Entities.MiningPoolErrorCode.Miners.COMMON_ERROR, "Posted data error")); } try { LogHelper.Info($"Address is {model.Address}, network is {GlobalParameters.IsTestnet}"); if (!AccountIdHelper.AddressVerify(model.Address)) { return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {model.Address}is invalid")); } } catch { return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_IS_INVALID, $"Address {model.Address} is invalid")); } var miner = MinersJob.Current.Pool_Miners.FirstOrDefault(m => m.Address == model.Address); if (miner == null) { return(Error(Entities.MiningPoolErrorCode.Miners.ADDRESS_NOT_EXIST, $"Address {model.Address} not exist")); } else if (miner.SN != model.SN) { return(Error(Entities.MiningPoolErrorCode.Miners.SN_CODE_ERROR, $"SN code {model.SN} with address {model.Address} is error")); } var scoopNumberKey = "Pool:MinerScoopNumber:" + model.Address; var maxNonceKey = "Pool:MinerMaxNonce:" + model.Address; var scoopNumber = RedisManager.Current.GetDataInRedis <string>(scoopNumberKey); if (scoopNumber == null || scoopNumber != model.ScoopNumber.ToString()) { return(Error(Entities.MiningPoolErrorCode.Miners.SCOOPNUMBER_NOT_MATCH, $"Scoop number from address {model.Address} SN {model.SN} is not matched: {scoopNumber}/{model.ScoopNumber}")); } if (model.MaxNonce > MaxNonceLimit) { return(Error(Entities.MiningPoolErrorCode.Miners.MAXNONCE_IS_INVALID, $"Max nonce {model.MaxNonce} from address {model.Address} is invalid")); } //var data = POC.CalculateScoopData(model.Address, model.MaxNonce, model.ScoopNumber); //try //{ // var scoopData = Convert.FromBase64String(model.ScoopData); // if (Base16.Encode(data) != Base16.Encode(scoopData)) // { // return Error(Entities.MiningPoolErrorCode.Miners.SCOOP_DATA_IS_INVALID, "Scoop data is invalid"); // } //} //catch //{ // return Error(Entities.MiningPoolErrorCode.Miners.SCOOP_DATA_IS_INVALID, "Scoop data is invalid"); //} RedisManager.Current.SaveDataToRedis <string>(maxNonceKey, model.MaxNonce.ToString(), MaxNonceTimeout); return(OK(true)); } catch (ApiCustomException ce) { LogHelper.Error(ce.Message); return(Error(ce.ErrorCode, ce.ErrorMessage)); } catch (Exception ex) { LogHelper.Error(ex.Message, ex); return(Error(ex.HResult, ex.Message)); } }