Esempio n. 1
0
        public IActionResult BuildAndSendCallSmartContractTransaction([FromBody] BuildCallContractTransactionRequest request)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            BuildCallContractTransactionResponse response = this.smartContractTransactionService.BuildCallTx(request);

            if (!response.Success)
            {
                return(this.Json(response));
            }

            Transaction transaction = this.network.CreateTransaction(response.Hex);

            if (!this.connectionManager.ConnectedPeers.Any())
            {
                this.logger.LogTrace("(-)[NO_CONNECTED_PEERS]");
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Can't send transaction: sending transaction requires at least one connection!", string.Empty));
            }

            this.broadcasterManager.BroadcastTransactionAsync(transaction).GetAwaiter().GetResult();

            // Check if transaction was actually added to a mempool.
            TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(transaction.GetHash());

            if (transactionBroadCastEntry?.State == Features.Wallet.Broadcasting.State.CantBroadcast)
            {
                this.logger.LogError("Exception occurred: {0}", transactionBroadCastEntry.ErrorMessage);
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, transactionBroadCastEntry.ErrorMessage, "Transaction Exception"));
            }

            return(this.Json(response));
        }
        private async Task OnCrossChainTransactionFullySignedAsync(CrossChainTransferTransactionFullySigned @event)
        {
            if (this.ibdState.IsInitialBlockDownload() || !this.federationWalletManager.IsFederationWalletActive())
            {
                this.logger.LogInformation("Federation wallet isn't active or in IBD. Not attempting to broadcast signed transactions.");
                return;
            }

            TxMempoolInfo txInfo = await this.mempoolManager.InfoAsync(@event.Transfer.PartialTransaction.GetHash()).ConfigureAwait(false);

            if (txInfo != null)
            {
                this.logger.LogDebug("Deposit ID '{0}' already in the mempool.", @event.Transfer.DepositTransactionId);
                return;
            }

            this.logger.LogDebug("Broadcasting deposit-id={0} a signed multisig transaction {1} to the network.", @event.Transfer.DepositTransactionId, @event.Transfer.PartialTransaction.GetHash());

            await this.broadcasterManager.BroadcastTransactionAsync(@event.Transfer.PartialTransaction).ConfigureAwait(false);

            // Check if transaction was actually added to a mempool.
            TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(@event.Transfer.PartialTransaction.GetHash());

            if (transactionBroadCastEntry?.TransactionBroadcastState == TransactionBroadcastState.CantBroadcast && !CrossChainTransferStore.IsMempoolErrorRecoverable(transactionBroadCastEntry.MempoolError))
            {
                this.logger.LogWarning("Deposit ID '{0}' rejected due to '{1}'.", @event.Transfer.DepositTransactionId, transactionBroadCastEntry.ErrorMessage);
                this.store.RejectTransfer(@event.Transfer);
            }
        }
Esempio n. 3
0
        public static void UpdateMemoryPoolEntry(MemoryPoolEntry memoryPoolEntry, TransactionBroadcastEntry broadcastEntry)
        {
            var newState  = broadcastEntry.State.ToBroadcastState();
            var newErrorM = broadcastEntry.MempoolError.GetMemoryPoolError();
            var newErrorC = broadcastEntry.MempoolError.GetMemoryPoolConsensusError();

            var sb = new StringBuilder();

            sb.AppendLine();
            if (newState != memoryPoolEntry.BroadcastState)
            {
                sb.AppendLine($"BroadcastState {memoryPoolEntry.BroadcastState} -> {newState}");
            }
            if (newErrorM != memoryPoolEntry.MemoryPoolError)
            {
                sb.AppendLine($"MemoryPoolError {memoryPoolEntry.MemoryPoolError} -> {newErrorM}");
            }
            if (newErrorC != memoryPoolEntry.ConsensusError)
            {
                sb.AppendLine($"MemoryPoolError {memoryPoolEntry.ConsensusError} -> {newErrorC}");
            }

            Log.Logger.LogInformation($"Updating Tracked tx {memoryPoolEntry.Transaction.HashTx},  changes: {sb}");

            memoryPoolEntry.BroadcastState  = newState;
            memoryPoolEntry.MemoryPoolError = newErrorM;
            memoryPoolEntry.ConsensusError  = newErrorC;
        }
Esempio n. 4
0
        public IActionResult Call([FromBody] BuildCallContractTransactionRequest request)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            BuildCallContractTransactionResponse response = this.smartContractTransactionService.BuildCallTx(request);

            if (!response.Success)
            {
                return(this.BadRequest(this.Json(response)));
            }

            Transaction transaction = this.network.CreateTransaction(response.Hex);

            this.broadcasterManager.BroadcastTransactionAsync(transaction).GetAwaiter().GetResult();

            // Check if transaction was actually added to a mempool.
            TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(transaction.GetHash());

            if (transactionBroadCastEntry?.State == State.CantBroadcast)
            {
                this.logger.LogError("Exception occurred: {0}", transactionBroadCastEntry.ErrorMessage);
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, transactionBroadCastEntry.ErrorMessage, "Transaction Exception"));
            }

            return(this.Json(response));
        }
Esempio n. 5
0
        public bool TryGetFromBroadcastStore(uint256 transactionHash, out TransactionBroadcastEntry entry)
        {
            lock (BroadcastStoreLock)
            {
                var found = BroadcastStore.FirstOrDefault(x => x.TransactionId == transactionHash);
                entry = found;

                return(found is { });
        public IActionResult SendTransaction([FromBody] SendTransactionRequest request)
        {
            Guard.NotNull(request, nameof(request));

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(BuildErrorResponse(this.ModelState));
            }

            if (!this.connectionManager.ConnectedPeers.Any())
            {
                throw new WalletException("Can't send transaction: sending transaction requires at least one connection!");
            }

            try
            {
                Transaction transaction = this.network.CreateTransaction(request.Hex);

                var model = new WalletSendTransactionModel
                {
                    TransactionId = transaction.GetHash(),
                    Outputs       = new List <TransactionOutputModel>()
                };

                foreach (TxOut output in transaction.Outputs)
                {
                    bool isUnspendable = output.ScriptPubKey.IsUnspendable;

                    string address = GetAddressFromScriptPubKey(output);
                    model.Outputs.Add(new TransactionOutputModel
                    {
                        Address      = address,
                        Amount       = output.Value,
                        OpReturnData = isUnspendable ? Encoding.UTF8.GetString(output.ScriptPubKey.ToOps().Last().PushData) : null
                    });
                }

                this.broadcasterManager.BroadcastTransactionAsync(transaction).GetAwaiter().GetResult();

                TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(transaction.GetHash());

                if (!string.IsNullOrEmpty(transactionBroadCastEntry?.ErrorMessage))
                {
                    this.logger.LogError("Exception occurred: {0}", transactionBroadCastEntry.ErrorMessage);
                    return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, transactionBroadCastEntry.ErrorMessage, "Transaction Exception"));
                }

                return(this.Json(model));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
Esempio n. 7
0
        public TransactionBroadcastEntry GetTransaction(uint256 transactionHash)
        {
            TransactionBroadcastEntry txEntry = this.Broadcasts.FirstOrDefault(x => x.Transaction.GetHash() == transactionHash);

            if (txEntry == default(TransactionBroadcastEntry))
            {
                return(null);
            }

            return(txEntry);
        }
Esempio n. 8
0
        public void AddOrUpdate(Transaction transaction, State state)
        {
            TransactionBroadcastEntry broadcastEntry = this.Broadcasts.FirstOrDefault(x => x.Transaction.GetHash() == transaction.GetHash());

            if (broadcastEntry == null)
            {
                broadcastEntry = new TransactionBroadcastEntry(transaction, state);
                this.Broadcasts.Add(broadcastEntry);
                this.OnTransactionStateChanged(broadcastEntry);
            }
            else if (broadcastEntry.State != state)
            {
                broadcastEntry.State = state;
                this.OnTransactionStateChanged(broadcastEntry);
            }
        }
Esempio n. 9
0
 public bool TryAddToBroadcastStore(Transaction transaction, string nodeRemoteSocketEndpoint)
 {
     lock (BroadcastStoreLock)
     {
         if (BroadcastStore.Any(x => x.TransactionId == transaction.GetHash()))
         {
             return(false);
         }
         else
         {
             var entry = new TransactionBroadcastEntry(transaction, nodeRemoteSocketEndpoint);
             BroadcastStore.Add(entry);
             return(true);
         }
     }
 }
        public bool TryGetFromBroadcastStore(uint256 transactionHash, out TransactionBroadcastEntry entry)
        {
            lock (BroadcastStoreLock)
            {
                var found = BroadcastStore.FirstOrDefault(x => x.TransactionId == transactionHash);
                entry = found;

                if (found is null)
                {
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
        }
Esempio n. 11
0
        BroadcastState BroadCast(Transaction transaction)
        {
            if (!this.connectionManager.ConnectedPeers.Any())
            {
                throw new X1WalletException(HttpStatusCode.BadRequest, "Can't send the transactions without connections.");
            }
            this.broadcasterManager.BroadcastTransactionAsync(transaction).GetAwaiter().GetResult();
            TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(transaction.GetHash());

            if (transactionBroadCastEntry.State == State.CantBroadcast)
            {
                throw new X1WalletException(HttpStatusCode.InternalServerError,
                                            $"Can't send the transaction: {transactionBroadCastEntry.ErrorMessage}.");
            }

            return(transactionBroadCastEntry.State.ToBroadcastState());
        }
        private async Task <SignedMultisigTransactionBroadcastResultItem> BroadcastFullySignedTransfersAsync(ICrossChainTransfer crossChainTransfer)
        {
            var transferItem = new SignedMultisigTransactionBroadcastResultItem()
            {
                DepositId     = crossChainTransfer.DepositTransactionId?.ToString(),
                TransactionId = crossChainTransfer.PartialTransaction.GetHash().ToString(),
            };

            TxMempoolInfo txMempoolInfo = await this.mempoolManager.InfoAsync(crossChainTransfer.PartialTransaction.GetHash()).ConfigureAwait(false);

            if (txMempoolInfo != null)
            {
                this.logger.LogInformation("Deposit '{0}' already in the mempool.", crossChainTransfer.DepositTransactionId);
                transferItem.ItemMessage = $"Deposit '{crossChainTransfer.DepositTransactionId}' already in the mempool.";
                return(transferItem);
            }

            this.logger.LogInformation("Broadcasting deposit '{0}', a signed multisig transaction '{1'} to the network.", crossChainTransfer.DepositTransactionId, crossChainTransfer.PartialTransaction.GetHash());

            await this.broadcasterManager.BroadcastTransactionAsync(crossChainTransfer.PartialTransaction).ConfigureAwait(false);

            // Check if transaction was added to a mempool.
            TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(crossChainTransfer.PartialTransaction.GetHash());

            if (transactionBroadCastEntry == null)
            {
                return(transferItem);
            }

            // If there was no mempool error, then it safe to assume the transaction was broadcasted ok or already known.
            if (transactionBroadCastEntry.MempoolError == null)
            {
                return(transferItem);
            }

            if (transactionBroadCastEntry.TransactionBroadcastState == TransactionBroadcastState.CantBroadcast && !CrossChainTransferStore.IsMempoolErrorRecoverable(transactionBroadCastEntry.MempoolError))
            {
                this.logger.LogWarning("Deposit '{0}' rejected: '{1}'.", crossChainTransfer.DepositTransactionId, transactionBroadCastEntry.ErrorMessage);
                this.crossChainTransferStore.RejectTransfer(crossChainTransfer);
                transferItem.ItemMessage = $"Deposit '{crossChainTransfer.DepositTransactionId}' rejected: '{transactionBroadCastEntry.ErrorMessage}'.";
                return(transferItem);
            }

            return(transferItem);
        }
Esempio n. 13
0
        void OnTransactionStateChanged(object sender, TransactionBroadcastEntry broadcastEntry)
        {
            if (broadcastEntry.State == State.CantBroadcast)
            {
                return;
            }

            try
            {
                this.WalletSemaphore.Wait();

                base.TransactionBroadcastEntryChanged(broadcastEntry);
            }
            finally
            {
                this.WalletSemaphore.Release();
            }
        }
Esempio n. 14
0
        protected void TransactionBroadcastEntryChanged(TransactionBroadcastEntry broadcastEntry)
        {
            var memoryPoolEntry = MemoryPoolService.GetMemoryPoolEntry(broadcastEntry.Transaction.GetHash(), this.metadata.MemoryPool.Entries);

            if (memoryPoolEntry == null)
            {
                TransactionMetadata walletTransaction = BlockService.AnalyzeTransaction(broadcastEntry.Transaction, int.MaxValue, this.metadata.Blocks.Values, GetOrAddAddress);
                if (walletTransaction != null)
                {
                    var entry = MemoryPoolService.CreateMemoryPoolEntry(walletTransaction, broadcastEntry);
                    this.metadata.MemoryPool.Entries.Add(entry);
                }
            }
            else
            {
                MemoryPoolService.UpdateMemoryPoolEntry(memoryPoolEntry, broadcastEntry);
            }
            SaveMetadata();
        }
Esempio n. 15
0
        public async Task <IActionResult> BuildAndSendCallSmartContractTransactionAsync([FromBody] BuildCallContractTransactionRequest request)
        {
            if (!this.ModelState.IsValid)
            {
                return(ModelStateErrors.BuildErrorResponse(this.ModelState));
            }

            // Ignore this check if the node is running dev mode.
            if (this.nodeSettings.DevMode == null && !this.connectionManager.ConnectedPeers.Any())
            {
                this.logger.LogTrace("(-)[NO_CONNECTED_PEERS]");
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.Forbidden, "Can't send transaction as the node requires at least one connection.", string.Empty));
            }

            BuildCallContractTransactionResponse response = this.smartContractTransactionService.BuildCallTx(request);

            if (!response.Success)
            {
                return(this.Json(response));
            }

            Transaction transaction = this.network.CreateTransaction(response.Hex);

            await this.broadcasterManager.BroadcastTransactionAsync(transaction);

            // Check if transaction was actually added to a mempool.
            TransactionBroadcastEntry transactionBroadCastEntry = this.broadcasterManager.GetTransaction(transaction.GetHash());

            if (transactionBroadCastEntry?.TransactionBroadcastState == Features.Wallet.Broadcasting.TransactionBroadcastState.CantBroadcast)
            {
                this.logger.LogError("Exception occurred: {0}", transactionBroadCastEntry.ErrorMessage);
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, transactionBroadCastEntry.ErrorMessage, "Transaction Exception"));
            }

            response.Message = $"Your CALL method {request.MethodName} transaction was successfully built and sent. Check the receipt using the transaction ID once it has been included in a new block.";

            return(this.Json(response));
        }
 private void BroadcasterManager_TransactionStateChanged(object sender, TransactionBroadcastEntry transactionEntry)
 {
     this.ProcessTransaction(transactionEntry.Transaction, null, null, transactionEntry.State == State.Propagated);
 }
Esempio n. 17
0
        public static MemoryPoolEntry CreateMemoryPoolEntry(TransactionMetadata walletTransaction, TransactionBroadcastEntry broadcastEntry)
        {
            var entry = new MemoryPoolEntry
            {
                Transaction     = walletTransaction,
                TransactionTime = DateTime.UtcNow.ToUnixTime()
            };

            if (broadcastEntry != null)
            {
                entry.BroadcastState  = broadcastEntry.State.ToBroadcastState();
                entry.MemoryPoolError = broadcastEntry.MempoolError.GetMemoryPoolError();
                entry.ConsensusError  = broadcastEntry.MempoolError.GetMemoryPoolError();
            }

            return(entry);
        }
Esempio n. 18
0
        private void SetupTransactionWasBroadcast()
        {
            var cantBroadcastTransactionEntry = new TransactionBroadcastEntry(_transactionHelpers.CreateEmpty(), BroadcastState.Broadcasted, new MempoolError());

            _broadcasterManager.Setup(callTo => callTo.GetTransaction(It.IsAny <uint256>())).Returns(cantBroadcastTransactionEntry);
        }
Esempio n. 19
0
        protected bool IsPropagated(Transaction transaction)
        {
            TransactionBroadcastEntry broadcastEntry = this.GetTransaction(transaction.GetHash());

            return((broadcastEntry != null) && (broadcastEntry.State == State.Propagated));
        }
Esempio n. 20
0
 public void OnTransactionStateChanged(TransactionBroadcastEntry entry)
 {
     this.TransactionStateChanged?.Invoke(this, entry);
 }