public TransactionHashInfo Post([FromBody] TransactionModel request) { if (!ShouldSendCoins(request.RecipientAddress)) { return(new TransactionHashInfo() { IsValid = false, ErrorMessage = "User has received coins in the last hour." }); } if (request.Value > _appSettings.MaxAddressDonationPerHour) { return(new TransactionHashInfo() { IsValid = false, ErrorMessage = String.Format("User cannot receive more than {0} coins per hour.", _appSettings.MaxAddressDonationPerHour) }); } var privateKey = CryptoUtils.HexToByteArray(_appSettings.PrivateKey); var publicKey = CryptoUtils.GetPublicFor(privateKey); var date = DateTime.UtcNow; TransactionData dataToSign = GetDataToSign(request, publicKey, date); var json = Newtonsoft.Json.JsonConvert.SerializeObject(dataToSign); var msgHash = CryptoUtils.GetSha256Bytes(json); var signedMessage = CryptoUtils.BouncyCastleSign(msgHash, privateKey); // send http request to node var signedTransactionData = new TransactionDataSigned { From = _appSettings.FaucetAddress, To = request.RecipientAddress, Value = request.Value, Fee = 0, SenderPubKey = CryptoUtils.ByteArrayToHex(publicKey), DateCreated = date, SenderSignature = CryptoUtils.ByteArrayToHex(signedMessage) }; var res = HttpUtils.DoApiPost <TransactionDataSigned, TransactionHashInfo>(request.NodeUrl, "api/transactions", signedTransactionData); if (res.IsValid) { // add transaction record with limits var recordHistory = new TransactionHistory { Address = request.RecipientAddress, DateReceived = res.DateReceived, Amount = request.Value }; _dbService.Add(request.RecipientAddress, recordHistory); } return(res); }
private void PropagateTransactionToPeers(TransactionDataSigned transaction) { var tasks = new List <Task>(); dbService.GetPeers().ForEach(p => { tasks.Add(Task.Run(() => HttpUtils.DoApiPost <TransactionDataSigned, TransactionHashInfo>(p.Url, TRANSACTION_API_PATH, transaction))); }); Task.WaitAll(tasks.ToArray()); }
public TransactionHashInfo CreateTransaction(TransactionDataSigned signedData) { var dateReceived = DateTime.UtcNow; var newTransaction = new Transaction(signedData); if (dbService.GetTransactions().Any(t => t.TransactionHashHex == newTransaction.TransactionHashHex)) { return(new TransactionHashInfo { IsValid = true, ErrorMessage = $"Duplicate transaction", DateReceived = dateReceived, TransactionHash = newTransaction.TransactionHashHex }); } bool isValidTransaction = ValidateTransaction(signedData); if (!isValidTransaction) { return(new TransactionHashInfo { IsValid = isValidTransaction, ErrorMessage = "Transaction data is corrupted.", DateReceived = dateReceived, TransactionHash = "" }); } //validate balance var bal = GetBalance(signedData.From, 1).ConfirmedBalance.Balance; var hasFunds = (bal >= signedData.Value + signedData.Fee); if (!hasFunds) { return(new TransactionHashInfo { IsValid = false, ErrorMessage = $"Not enough funds. Available funds: {bal}, required funds: {signedData.Value} + {signedData.Fee} for the fee", DateReceived = dateReceived, TransactionHash = "" }); } dbService.AddTransaction(newTransaction); PropagateTransactionToPeers(newTransaction); return(new TransactionHashInfo() { IsValid = isValidTransaction, DateReceived = dateReceived, TransactionHash = newTransaction.TransactionHashHex }); }
private bool ValidateTransaction(TransactionDataSigned signedData) { TransactionData toValidate = new TransactionData(signedData); var messageData = JsonConvert.SerializeObject(toValidate); // Validate signature var senderPublicKey = CryptoUtils.HexToByteArray(signedData.SenderPubKey); var senderSignature = CryptoUtils.HexToByteArray(signedData.SenderSignature); var messageDataHash = CryptoUtils.GetSha256Bytes(messageData); var isTestValid = CryptoUtils.BouncyCastleVerify(messageDataHash, senderSignature, senderPublicKey); return(isTestValid); }
public TransactionHashInfo Post([FromBody] TransactionDataSigned data) { return(_blockchainService.CreateTransaction(data)); }