private static MsgTx DecodeTransaction(byte[] rawTransaction) { var msgTx = new MsgTx(); msgTx.Decode(rawTransaction); return(msgTx); }
/// <summary> /// Broadcasts a signed transaction to the Decred network /// </summary> /// <param name="operationId"></param> /// <param name="hexTransaction"></param> /// <returns></returns> /// <exception cref="TransactionBroadcastException"></exception> public async Task Broadcast(Guid operationId, string hexTransaction) { if (operationId == Guid.Empty) { throw new BusinessException(ErrorReason.BadRequest, "Operation id is invalid"); } if (string.IsNullOrWhiteSpace(hexTransaction)) { throw new BusinessException(ErrorReason.BadRequest, "SignedTransaction is invalid"); } var txBytes = HexUtil.ToByteArray(hexTransaction); var msgTx = new MsgTx(); msgTx.Decode(txBytes); // If the operation exists in the cache, throw exception var cachedResult = await _broadcastTxRepo.GetAsync(operationId.ToString()); if (cachedResult != null) { throw new BusinessException(ErrorReason.DuplicateRecord, "Operation already broadcast"); } var txHash = HexUtil.FromByteArray(msgTx.GetHash().Reverse().ToArray()); var txWasMined = await _txRepo.GetTxInfoByHash(txHash, long.MaxValue) != null; if (txWasMined) { await SaveBroadcastedTransaction(new BroadcastedTransaction { OperationId = operationId, Hash = txHash, EncodedTransaction = hexTransaction }); throw new BusinessException(ErrorReason.DuplicateRecord, "Operation already broadcast"); } // Submit the transaction to the network via dcrd var result = await _dcrdClient.SendRawTransactionAsync(hexTransaction); if (result.Error != null) { throw new TransactionBroadcastException($"[{result.Error.Code}] {result.Error.Message}"); } await SaveBroadcastedTransaction(new BroadcastedTransaction { OperationId = operationId, Hash = txHash, EncodedTransaction = hexTransaction }); }
public void New_GivenSerializedValueWithMultipleTx_DeserializesInputAndReserializes() { var tests = new MsgTxTestSubject[] { new MultiTxTestSubject(), new NoTxTests() }; foreach (var test in tests) { var subject = new MsgTx(); subject.Decode(test.EncodedMessage); var deserialized = subject.Encode(); Assert.True(test.EncodedMessage.SequenceEqual(deserialized)); } }
/// <summary> /// Determines the state of a broadcasted transaction /// </summary> /// <param name="operationId"></param> /// <returns></returns> /// <exception cref="BusinessException"></exception> public async Task <BroadcastedSingleTransactionResponse> GetBroadcastedTxSingle(Guid operationId) { if (operationId == Guid.Empty) { throw new BusinessException(ErrorReason.BadRequest, "Operation id is invalid"); } // Retrieve the broadcasted transaction and deserialize it. var broadcastedTransaction = await GetBroadcastedTransaction(operationId); var transaction = new MsgTx(); transaction.Decode(HexUtil.ToByteArray(broadcastedTransaction.EncodedTransaction)); // Calculate the fee and total amount spent from the transaction. var fee = transaction.TxIn.Sum(t => t.ValueIn) - transaction.TxOut.Sum(t => t.Value); var amount = transaction.TxOut.Sum(t => t.Value); // Check to see if the transaction has been included in a block. var safeBlockHeight = await _dcrdClient.GetMaxConfirmedBlockHeight(); var knownTx = await _txRepo.GetTxInfoByHash(broadcastedTransaction.Hash, safeBlockHeight); var txState = knownTx == null ? BroadcastedTransactionState.InProgress : BroadcastedTransactionState.Completed; // If the tx has been included in a block, // use the block height + timestamp from the block var txBlockHeight = knownTx?.BlockHeight ?? safeBlockHeight; var timestamp = knownTx?.BlockTime.UtcDateTime ?? DateTime.UtcNow; return(new BroadcastedSingleTransactionResponse { Block = txBlockHeight, State = txState, Hash = broadcastedTransaction.Hash, Amount = amount.ToString(), Fee = fee.ToString(), Error = "", ErrorCode = null, OperationId = operationId, Timestamp = timestamp }); }