Пример #1
0
        private static MsgTx DecodeTransaction(byte[] rawTransaction)
        {
            var msgTx = new MsgTx();

            msgTx.Decode(rawTransaction);
            return(msgTx);
        }
Пример #2
0
        /// <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
            });
        }
Пример #3
0
        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));
            }
        }
Пример #4
0
        /// <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
            });
        }