public void UndeleteRoutes(GrupoRuta grupo) { using (SmartTransaction transaction = SmartTransaction.BeginTransaction()) { try { UndeleteRoutesWithoutTransaction(grupo); try { transaction.Commit(); } catch (Exception ex) { STrace.Exception(typeof(RutaDAO).FullName, ex, "Exception in UndeleteRoutes(GrupoRuta) -> transaction.Commit();"); throw ex; } } catch (Exception ex) { STrace.Exception(typeof(RutaDAO).FullName, ex, "Exception in UndeleteRoutes(GrupoRuta)"); try { transaction.Rollback(); } catch (Exception ex2) { STrace.Exception(typeof(RutaDAO).FullName, ex2, "Exception in UndeleteRoutes(GrupoRuta) -> transaction.Rollback();"); } throw ex; } } }
public async Task ConfirmTransactionTestAsync() { var transactionProcessor = await CreateTransactionProcessorAsync(); var keys = transactionProcessor.KeyManager.GetKeys().ToArray(); int coinsReceived = 0; int confirmed = 0; transactionProcessor.CoinReceived += (s, e) => coinsReceived++; transactionProcessor.CoinSpent += (s, e) => throw new InvalidOperationException("We are not spending the coin."); transactionProcessor.SpenderConfirmed += (s, e) => confirmed++; // A confirmed segwit transaction for us var tx = CreateCreditingTransaction(keys[0].PubKey.WitHash.ScriptPubKey, Money.Coins(1.0m)); transactionProcessor.Process(tx); Assert.Equal(1, coinsReceived); var coin = Assert.Single(transactionProcessor.Coins); Assert.False(coin.Confirmed); var tx2 = new SmartTransaction(tx.Transaction.Clone(), new Height(54321)); Assert.Equal(tx.GetHash(), tx2.GetHash()); transactionProcessor.Process(tx2); Assert.Equal(1, coinsReceived); Assert.True(coin.Confirmed); Assert.Equal(0, confirmed); }
private async Task BroadcastTransactionWithRpcAsync(SmartTransaction transaction) { await RpcClient.SendRawTransactionAsync(transaction.Transaction).ConfigureAwait(false); BelieveTransaction(transaction); Logger.LogInfo($"Transaction is successfully broadcasted with RPC: {transaction.GetHash()}."); }
private void AnalyzeCoinjoin(SmartTransaction tx, int newInputAnonset, ISet <HdPubKey> distinctWalletInputPubKeys) { var indistinguishableWalletOutputs = tx .WalletOutputs.GroupBy(x => x.Amount) .ToDictionary(x => x.Key, y => y.Count()); var anonsets = tx.Transaction.GetAnonymitySets(tx.WalletOutputs.Select(x => x.Index)); foreach (var newCoin in tx.WalletOutputs.ToArray()) { // Begin estimating the anonymity set size based on the number of // equivalent outputs that the i-th output has in in the transaction. int anonset = anonsets[newCoin.Index]; // Picking randomly an output would make our anonset: total/ours. anonset /= indistinguishableWalletOutputs[newCoin.Amount]; // Account for the inherited anonymity set size from the inputs in the // anonymity set size estimate. // The anonymity set size estimated for the input cluster is corrected // by -1 to avoid double counting ourselves in the anonset. // Stated differently, the right value to use for the calculation is not the // anonymity set size, but the subset of only the other participants, since // every output must belong to a member of the set. anonset += newInputAnonset - 1; HdPubKey hdPubKey = newCoin.HdPubKey; uint256 txid = tx.GetHash(); if (hdPubKey.AnonymitySet == HdPubKey.DefaultHighAnonymitySet) { // If the new coin's HD pubkey haven't been used yet // then its anonset haven't been set yet. // In that case the acquired anonset does not have to be intersected with the default anonset, // so this coin gets the aquired anonset. hdPubKey.SetAnonymitySet(anonset, txid); } else if (distinctWalletInputPubKeys.Contains(hdPubKey)) { // If it's a reuse of an input's pubkey, then intersection punishment is senseless. hdPubKey.SetAnonymitySet(newInputAnonset, txid); } else if (tx.WalletOutputs.Where(x => x != newCoin).Select(x => x.HdPubKey).Contains(hdPubKey)) { // If it's a reuse of another output' pubkey, then intersection punishment can only go as low as the inherited anonset. hdPubKey.SetAnonymitySet(Math.Max(newInputAnonset, Intersect(new[] { anonset, hdPubKey.AnonymitySet }, 1)), txid); } else if (hdPubKey.AnonymitySetReasons.Contains(txid)) { // If we already processed this transaction for this script // then we'll go with normal processing, it's not an address reuse, // it's just we're processing the transaction twice. hdPubKey.SetAnonymitySet(anonset, txid); } else { // It's address reuse. hdPubKey.SetAnonymitySet(Intersect(new[] { anonset, hdPubKey.AnonymitySet }, 1), txid); } } }
/// <summary> /// Sets clusters and anonymity sets for related HD public keys. /// </summary> public void Analyze(SmartTransaction tx) { var inputCount = tx.Transaction.Inputs.Count; var outputCount = tx.Transaction.Outputs.Count; var ownInputCount = tx.WalletInputs.Count; var ownOutputCount = tx.WalletOutputs.Count; if (ownInputCount == 0) { AnalyzeReceive(tx); } else if (inputCount == ownInputCount && outputCount != ownOutputCount) { AnalyzeNormalSpend(tx); } else { AnalyzeWalletInputs(tx, out HashSet <HdPubKey> distinctWalletInputPubKeys, out int newInputAnonset); if (inputCount == ownInputCount) { AnalyzeSelfSpend(tx, newInputAnonset); } else { AnalyzeCoinjoin(tx, newInputAnonset, distinctWalletInputPubKeys); } AdjustWalletInputs(tx, distinctWalletInputPubKeys, newInputAnonset); } AnalyzeClusters(tx); }
public BroadcastTransactionViewModel( BitcoinStore store, Network network, TransactionBroadcaster broadcaster, SmartTransaction transaction) { Title = "Broadcast Transaction"; var nullMoney = new Money(-1L); var nullOutput = new TxOut(nullMoney, Script.Empty); var psbt = PSBT.FromTransaction(transaction.Transaction, network); TxOut GetOutput(OutPoint outpoint) => store.TransactionStore.TryGetTransaction(outpoint.Hash, out var prevTxn) ? prevTxn.Transaction.Outputs[outpoint.N] : nullOutput; var inputAddressAmount = psbt.Inputs .Select(x => x.PrevOut) .Select(GetOutput) .ToArray(); var outputAddressAmount = psbt.Outputs .Select(x => x.GetCoin().TxOut) .ToArray(); var psbtTxn = psbt.GetOriginalTransaction(); _transactionId = psbtTxn.GetHash().ToString(); _inputCount = inputAddressAmount.Length; _inputCountString = $" input{TextHelpers.AddSIfPlural(_inputCount)} and "; _outputCount = outputAddressAmount.Length; _outputCountString = $" output{TextHelpers.AddSIfPlural(_outputCount)}."; _totalInputValue = inputAddressAmount.Any(x => x.Value == nullMoney) ? null : inputAddressAmount.Select(x => x.Value).Sum(); _totalOutputValue = outputAddressAmount.Any(x => x.Value == nullMoney) ? null : outputAddressAmount.Select(x => x.Value).Sum(); _networkFee = TotalInputValue is null || TotalOutputValue is null ? null : TotalInputValue - TotalOutputValue; EnableCancel = true; EnableBack = false; this.WhenAnyValue(x => x.IsBusy) .Subscribe(x => EnableCancel = !x); var nextCommandCanExecute = this.WhenAnyValue(x => x.IsBusy) .Select(x => !x); NextCommand = ReactiveCommand.CreateFromTask( async() => await OnNext(broadcaster, transaction), nextCommandCanExecute); EnableAutoBusyOn(NextCommand); }
/// <returns>transactions it processed, empty if not processed any</returns> private HashSet <SmartTransaction> ProcessTransactions(IEnumerable <Transaction> transactions, Height height) { var processedTransactions = new HashSet <SmartTransaction>(); try { // Process all transactions foreach (var tx in transactions) { var smartTx = new SmartTransaction(tx, height); if (ProcessTransaction(smartTx)) { processedTransactions.Add(smartTx); } } // If processed any then do it again recursively until zero new is processed if (processedTransactions.Count > 0) { var newlyProcessedTransactions = ProcessTransactions(transactions, height); foreach (var ptx in newlyProcessedTransactions) { processedTransactions.Add(ptx); } } } catch (Exception ex) { Debug.WriteLine($"Ignoring {nameof(ProcessBlock)} exception at height {height}:"); Debug.WriteLine(ex); } return(processedTransactions); }
private async Task BroadcastTransactionToBackendAsync(SmartTransaction transaction) { Logger.LogInfo("Broadcasting with backend..."); using (var client = new WasabiClient(Synchronizer.WasabiClient.TorClient.DestinationUriAction, Synchronizer.WasabiClient.TorClient.TorSocks5EndPoint)) { try { await client.BroadcastAsync(transaction).ConfigureAwait(false); } catch (HttpRequestException ex2) when(ex2.Message.Contains("bad-txns-inputs-missingorspent", StringComparison.InvariantCultureIgnoreCase) || ex2.Message.Contains("missing-inputs", StringComparison.InvariantCultureIgnoreCase) || ex2.Message.Contains("txn-mempool-conflict", StringComparison.InvariantCultureIgnoreCase)) { if (transaction.Transaction.Inputs.Count == 1) // If we tried to only spend one coin, then we can mark it as spent. If there were more coins, then we do not know. { OutPoint input = transaction.Transaction.Inputs.First().PrevOut; lock (WalletServicesLock) { foreach (var walletService in AliveWalletServices) { SmartCoin coin = walletService.Coins.GetByOutPoint(input); if (coin != default) { coin.SpentAccordingToBackend = true; } } } } } } BelieveTransaction(transaction); Logger.LogInfo($"Transaction is successfully broadcasted to backend: {transaction.GetHash()}."); }
public void SmartCoinEquality() { var tx = Transaction.Parse("0100000000010176f521a178a4b394b647169a89b29bb0d95b6bce192fd686d533eb4ea98464a20000000000ffffffff02ed212d020000000016001442da650f25abde0fef57badd745df7346e3e7d46fbda6400000000001976a914bd2e4029ce7d6eca7d2c3779e8eac36c952afee488ac02483045022100ea43ccf95e1ac4e8b305c53761da7139dbf6ff164e137a6ce9c09e15f316c22902203957818bc505bbafc181052943d7ab1f3ae82c094bf749813e8f59108c6c268a012102e59e61f20c7789aa73faf5a92dc8c0424e538c635c55d64326d95059f0f8284200000000", Network.TestNet); var index = 0U; var km = KeyManager.CreateNew(out _, "", Network.Main); var hdpk1 = km.GenerateNewKey(SmartLabel.Empty, KeyState.Clean, false); var hdpk2 = km.GenerateNewKey(SmartLabel.Empty, KeyState.Clean, false); tx.Outputs[0].ScriptPubKey = hdpk1.P2wpkhScript; tx.Outputs[1].ScriptPubKey = hdpk2.P2wpkhScript; var height = Height.Mempool; var stx = new SmartTransaction(tx, height); var coin = new SmartCoin(stx, index, hdpk1); // If the txId or the index differ, equality should think it's a different coin. var differentCoin = new SmartCoin(stx, index + 1, hdpk2); // If the txId and the index are the same, equality should think it's the same coin. var sameCoin = new SmartCoin(stx, index, hdpk1); Assert.Equal(coin, sameCoin); Assert.NotEqual(coin, differentCoin); }
private void ProcesarViaje(int idViaje, bool regenera) { using (var transaction = SmartTransaction.BeginTransaction(IsolationLevel.ReadUncommitted)) { try { var viaje = DaoFactory.ViajeDistribucionDAO.FindById(idViaje); if (!regenera && HasBeenProcessed(idViaje)) { STrace.Trace(GetType().FullName, string.Format("Viaje ya procesado: {0}", idViaje)); } else { DaoFactory.DatamartViajeDAO.DeleteRecords(idViaje); ProcessViaje(viaje); STrace.Trace(GetType().FullName, string.Format("Viaje procesado: {0}", idViaje)); } transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); throw ex; } finally { ClearData(); } } }
protected void BtnGuardar_OnClick(object sender, EventArgs e) { ValidarDatosVigencia(); using (var transaction = SmartTransaction.BeginTransaction()) { if (EditObject.Id == 0) { GuardarNuevaLinea(); } var nuevaVigencia = new VigenciaPlanLinea { Inicio = SecurityExtensions.ToDataBaseDateTime(dtDesde.SelectedDate.Value), LineaTelefonica = EditObject, Plan = cbPlan.Selected > 0 ? DAOFactory.PlanDAO.FindById(cbPlan.Selected) : null }; ValidarCondicionesVigencia(nuevaVigencia); EditObject.Vigencias.Add(nuevaVigencia); DAOFactory.LineaTelefonicaDAO.SaveOrUpdate(EditObject); transaction.Commit(); } Response.Redirect(RedirectUrl); }
private void DoDeleteAudit(TDaotype obj, Usuario user) { using (var transaction = SmartTransaction.BeginTransaction()) { try { DoDeleteAuditWithoutTransaction(obj, user); try { transaction.Commit(); } catch (Exception ex) { STrace.Exception(typeof(GenericDAO <TDaotype>).FullName, ex, "Exception in Update(TDaotype) -> transaction.Commit();"); throw ex; } } catch (Exception ex) { STrace.Exception(typeof(GenericDAO <TDaotype>).FullName, ex, "Exception in Update(TDaotype)"); try { transaction.Rollback(); } catch (Exception ex2) { STrace.Exception(typeof(GenericDAO <TDaotype>).FullName, ex2, "Exception in Update(TDaotype) -> transaction.Rollback();"); } throw ex; } } }
/// <summary> /// Updates the specified object whitin a transaction. /// </summary> /// <param name="obj"></param> public virtual void Update(TDaotype obj) { using (var transaction = SmartTransaction.BeginTransaction()) { try { UpdateWithoutTransaction(obj); try { transaction.Commit(); } catch (Exception ex) { STrace.Exception(typeof(GenericDAO <TDaotype>).FullName, ex, "Exception in Update(TDaotype) -> transaction.Commit();"); throw ex; } } catch (Exception ex) { STrace.Exception(typeof(GenericDAO <TDaotype>).FullName, ex, "Exception in Update(TDaotype)"); try { transaction.Rollback(); } catch (Exception ex2) { STrace.Exception(typeof(GenericDAO <TDaotype>).FullName, ex2, "Exception in Update(TDaotype) -> transaction.Rollback();"); } throw ex; } } }
public async Task SendTransactionAsync(SmartTransaction transaction) { try { // Broadcast to a random node. // Wait until it arrives to at least two other nodes. // If something's wrong, fall back broadcasting with rpc, then backend. if (Network == Network.RegTest) { throw new InvalidOperationException($"Transaction broadcasting to nodes does not work in {Network.RegTest}."); } Node node = Nodes.ConnectedNodes.RandomElement(); while (node is null || !node.IsConnected || Nodes.ConnectedNodes.Count < 5) { // As long as we are connected to at least 4 nodes, we can always try again. // 3 should be enough, but make it 5 so 2 nodes could disconnect in the meantime. if (Nodes.ConnectedNodes.Count < 5) { throw new InvalidOperationException("We are not connected to enough nodes."); } await Task.Delay(100).ConfigureAwait(false); node = Nodes.ConnectedNodes.RandomElement(); } await BroadcastTransactionToNetworkNodeAsync(transaction, node).ConfigureAwait(false); } catch (Exception ex) { Logger.LogInfo($"Random node could not broadcast transaction. Reason: {ex.Message}."); Logger.LogDebug(ex); if (RpcClient is { })
public void SmartTransactionSerialization() { var tx = Transaction.Parse("02000000040aa8d0af84518df6e3a60c5bb19d9c3fcc3dc6e26b2f2449e8d7bf8d3fe84b87010000006a473044022018dfe9216c1209dd6c2b6c1607dbac4e499c1fce4878bc7d5d83fccbf3e24c9402202cac351c9c6a2b5eef338cbf0ec000d8de1c05e96a904cbba2b9e6ffc2d4e19501210364cc39da1091b1a9c12ec905a14a9e8478f951f7a1accdabeb40180533f2eaa5feffffff112c07d0f5e0617d720534f0b2b84dc0d5b7314b358c3ab338823b9e5bfbddf5010000006b483045022100ec155e7141e74661ee511ae980150a6c89261f31070999858738369afc28f2b6022006230d2aa24fac110b74ef15b84371486cf76c539b335a253c14462447912a300121020c2f41390f031d471b22abdb856e6cdbe0f4d74e72c197469bfd54e5a08f7e67feffffff38e799b8f6cf04fd021a9b135cdcd347da7aac4fd8bb8d0da9316a9fb228bb6e000000006b483045022100fc1944544a3f96edd8c8a9795c691e2725612b5ab2e1c999be11a2a4e3f841f1022077b2e088877829edeada0c707a9bb577aa79f26dafacba3d1d2d047f52524296012102e6015963dff9826836400cf8f45597c0705757d5dcdc6bf734f661c7dab89e69feffffff64c3f0377e86625123f2f1ee229319ed238e8ca8b7dda5bc080a2c5ecb984629000000006a47304402204233a90d6296182914424fd2901e16e6f5b13b451b67b0eec25a5eaacc5033c902203d8a13ef0b494c12009663475458e51da6bd55cc67688264230ece81d3eeca24012102f806d7152da2b52c1d9ad928e4a6253ccba080a5b9ab9efdd80e37274ac67f9bfeffffff0290406900000000001976a91491ac4e49b66f845180d98d8f8be6121588be6e3b88ac52371600000000001976a9142f44ed6749e8c84fd476e4440741f7e6f55542fa88acadd30700", Network.TestNet); var tx2 = Transaction.Parse("02000000040aa8d0af84518df6e3a60c5bb19d9c3fcc3dc6e26b2f2449e8d7bf8d3fe84b87010000006a473044022018dfe9216c1209dd6c2b6c1607dbac4e499c1fce4878bc7d5d83fccbf3e24c9402202cac351c9c6a2b5eef338cbf0ec000d8de1c05e96a904cbba2b9e6ffc2d4e19501210364cc39da1091b1a9c12ec905a14a9e8478f951f7a1accdabeb40180533f2eaa5feffffff112c07d0f5e0617d720534f0b2b84dc0d5b7314b358c3ab338823b9e5bfbddf5010000006b483045022100ec155e7141e74661ee511ae980150a6c89261f31070999858738369afc28f2b6022006230d2aa24fac110b74ef15b84371486cf76c539b335a253c14462447912a300121020c2f41390f031d471b22abdb856e6cdbe0f4d74e72c197469bfd54e5a08f7e67feffffff38e799b8f6cf04fd021a9b135cdcd347da7aac4fd8bb8d0da9316a9fb228bb6e000000006b483045022100fc1944544a3f96edd8c8a9795c691e2725612b5ab2e1c999be11a2a4e3f841f1022077b2e088877829edeada0c707a9bb577aa79f26dafacba3d1d2d047f52524296012102e6015963dff9826836400cf8f45597c0705757d5dcdc6bf734f661c7dab89e69feffffff64c3f0377e86625123f2f1ee229319ed238e8ca8b7dda5bc080a2c5ecb984629000000006a47304402204233a90d6296182914424fd2901e16e6f5b13b451b67b0eec25a5eaacc5033c902203d8a13ef0b494c12009663475458e51da6bd55cc67688264230ece81d3eeca24012102f806d7152da2b52c1d9ad928e4a6253ccba080a5b9ab9efdd80e37274ac67f9bfeffffff0290406900000000001976a91491ac4e49b66f845180d98d8f8be6121588be6e3b88ac52371600000000001976a9142f44ed6749e8c84fd476e4440741f7e6f55542fa88acadd30700", Network.Main); var tx3 = Transaction.Parse("02000000040aa8d0af84518df6e3a60c5bb19d9c3fcc3dc6e26b2f2449e8d7bf8d3fe84b87010000006a473044022018dfe9216c1209dd6c2b6c1607dbac4e499c1fce4878bc7d5d83fccbf3e24c9402202cac351c9c6a2b5eef338cbf0ec000d8de1c05e96a904cbba2b9e6ffc2d4e19501210364cc39da1091b1a9c12ec905a14a9e8478f951f7a1accdabeb40180533f2eaa5feffffff112c07d0f5e0617d720534f0b2b84dc0d5b7314b358c3ab338823b9e5bfbddf5010000006b483045022100ec155e7141e74661ee511ae980150a6c89261f31070999858738369afc28f2b6022006230d2aa24fac110b74ef15b84371486cf76c539b335a253c14462447912a300121020c2f41390f031d471b22abdb856e6cdbe0f4d74e72c197469bfd54e5a08f7e67feffffff38e799b8f6cf04fd021a9b135cdcd347da7aac4fd8bb8d0da9316a9fb228bb6e000000006b483045022100fc1944544a3f96edd8c8a9795c691e2725612b5ab2e1c999be11a2a4e3f841f1022077b2e088877829edeada0c707a9bb577aa79f26dafacba3d1d2d047f52524296012102e6015963dff9826836400cf8f45597c0705757d5dcdc6bf734f661c7dab89e69feffffff64c3f0377e86625123f2f1ee229319ed238e8ca8b7dda5bc080a2c5ecb984629000000006a47304402204233a90d6296182914424fd2901e16e6f5b13b451b67b0eec25a5eaacc5033c902203d8a13ef0b494c12009663475458e51da6bd55cc67688264230ece81d3eeca24012102f806d7152da2b52c1d9ad928e4a6253ccba080a5b9ab9efdd80e37274ac67f9bfeffffff0290406900000000001976a91491ac4e49b66f845180d98d8f8be6121588be6e3b88ac52371600000000001976a9142f44ed6749e8c84fd476e4440741f7e6f55542fa88acadd30700", Network.RegTest); var height = Height.MemPool; var smartTx = new SmartTransaction(tx, height); var smartTx2 = new SmartTransaction(tx2, height); var smartTx3 = new SmartTransaction(tx3, height); var serialized = JsonConvert.SerializeObject(smartTx); var deserialized = JsonConvert.DeserializeObject <SmartTransaction>(serialized); var serialized2 = JsonConvert.SerializeObject(smartTx2); var deserialized2 = JsonConvert.DeserializeObject <SmartTransaction>(serialized2); var serialized3 = JsonConvert.SerializeObject(smartTx3); var deserialized3 = JsonConvert.DeserializeObject <SmartTransaction>(serialized3); Assert.Equal(smartTx, deserialized); Assert.Equal(smartTx.Height, deserialized.Height); Assert.Equal(deserialized, deserialized2); Assert.Equal(deserialized, deserialized3); Assert.True(smartTx.Transaction == deserialized3); Assert.True(smartTx.Equals(deserialized2.Transaction)); object sto = deserialized; Assert.True(smartTx.Equals(sto)); object to = deserialized.Transaction; Assert.True(smartTx.Equals(deserialized.Transaction)); // ToDo: Assert.True(smartTx.Equals(to)); }
protected override void OnDelete() { using (var transaction = SmartTransaction.BeginTransaction()) { EditObject.Estado = ConsumoCabecera.Estados.Eliminado; DAOFactory.ConsumoCabeceraDAO.SaveOrUpdate(EditObject); ////// ACTUALIZAR STOCK ////// if (EditObject.Deposito != null || EditObject.DepositoDestino != null) { var detalles = EditObject.Detalles.Cast <ConsumoDetalle>(); foreach (var consumoDetalle in detalles) { if (EditObject.Deposito != null) { var stock = DAOFactory.StockDAO.GetByDepositoAndInsumo(EditObject.Deposito.Id, consumoDetalle.Insumo.Id); stock.Cantidad += consumoDetalle.Cantidad; DAOFactory.StockDAO.SaveOrUpdate(stock); } if (EditObject.DepositoDestino != null) { var stock = DAOFactory.StockDAO.GetByDepositoAndInsumo(EditObject.DepositoDestino.Id, consumoDetalle.Insumo.Id); stock.Cantidad -= consumoDetalle.Cantidad; DAOFactory.StockDAO.SaveOrUpdate(stock); } } } ////////////////////////////// transaction.Commit(); } }
public async Task UpdateTransactionHeightAfterConfirmationAsync() { var transactionProcessor = await CreateTransactionProcessorAsync(); // An unconfirmed segwit transaction for us var key = transactionProcessor.KeyManager.GetKeys().First(); var tx = CreateCreditingTransaction(key.PubKey.WitHash.ScriptPubKey, Money.Coins(1.0m)); transactionProcessor.Process(tx); Assert.True(transactionProcessor.TransactionStore.ConfirmedStore.IsEmpty()); var cachedTx = Assert.Single(transactionProcessor.TransactionStore.MempoolStore.GetTransactions()); var coin = Assert.Single(transactionProcessor.Coins); Assert.Equal(Height.Mempool, cachedTx.Height); Assert.Equal(Height.Mempool, coin.Height); // Now it is confirmed var blockHeight = new Height(77551); tx = new SmartTransaction(tx.Transaction, blockHeight); var relevant = transactionProcessor.Process(tx); Assert.True(relevant); Assert.Single(transactionProcessor.Coins); // Transaction store assertions Assert.True(transactionProcessor.TransactionStore.MempoolStore.IsEmpty()); cachedTx = Assert.Single(transactionProcessor.TransactionStore.ConfirmedStore.GetTransactions()); Assert.Equal(blockHeight, cachedTx.Height); coin = Assert.Single(transactionProcessor.Coins); Assert.Equal(blockHeight, coin.Height); Assert.True(coin.Confirmed); }
public void UpdateTransactionHeightAfterConfirmation() { var transactionProcessor = CreateTransactionProcessor(); // An unconfirmed segwit transaction for us var key = transactionProcessor.KeyManager.GetKeys().First(); var tx = CreateCreditingTransaction(key.PubKey.WitHash.ScriptPubKey, Money.Coins(1.0m)); transactionProcessor.TransactionHashes.Append(tx.GetHash()); // This transaction was already seen before transactionProcessor.Process(tx); var cachedTx = Assert.Single(transactionProcessor.TransactionCache); var coin = Assert.Single(transactionProcessor.Coins); Assert.Equal(Height.Mempool, cachedTx.Height); Assert.Equal(Height.Mempool, coin.Height); // Now it is confirmed var blockHeight = new Height(77551); tx = new SmartTransaction(tx.Transaction, blockHeight); var relevant = transactionProcessor.Process(tx); Assert.True(relevant); Assert.Single(transactionProcessor.Coins); cachedTx = Assert.Single(transactionProcessor.TransactionCache); Assert.NotEqual(Height.Mempool, cachedTx.Height); coin = Assert.Single(transactionProcessor.Coins); Assert.Equal(blockHeight, coin.Height); Assert.Empty(transactionProcessor.TransactionHashes); }
private async Task BroadcastTransactionToBackendAsync(SmartTransaction transaction) { Logger.LogInfo("Broadcasting with backend..."); using (TorHttpClient torHttpClient = Synchronizer.WasabiClientFactory.NewBackendTorHttpClient(isolateStream: true)) { var client = new WasabiClient(torHttpClient); try { await client.BroadcastAsync(transaction).ConfigureAwait(false); } catch (HttpRequestException ex2) when(RpcErrorTools.IsSpentError(ex2.Message)) { if (transaction.Transaction.Inputs.Count == 1) // If we tried to only spend one coin, then we can mark it as spent. If there were more coins, then we do not know. { OutPoint input = transaction.Transaction.Inputs.First().PrevOut; foreach (var coin in WalletManager.CoinsByOutPoint(input)) { coin.SpentAccordingToBackend = true; } } throw; } } BelieveTransaction(transaction); Logger.LogInfo($"Transaction is successfully broadcasted to backend: {transaction.GetHash()}."); }
protected override void OnSave() { using (var transaction = SmartTransaction.BeginTransaction()) { try { EditObject.Cliente = DAOFactory.ClienteDAO.FindById(ddlCliente.Selected); EditObject.Responsable = cbResponsable.Selected > 0 ? DAOFactory.EmpleadoDAO.FindById(cbResponsable.Selected) : null; EditObject.Codigo = txtCodigo.Text; EditObject.Descripcion = txtDescripcion.Text; EditObject.Telefono = txtTelefono.Text; EditObject.Nomenclado = true; EditObject.Comentario1 = txtComentario1.Text; EditObject.Comentario2 = txtComentario2.Text; EditObject.Comentario3 = txtComentario3.Text; if (chkExistente.Checked) { EditObject.ReferenciaGeografica = SelectGeoRef1.Selected > 0 ? DAOFactory.ReferenciaGeograficaDAO.FindById(SelectGeoRef1.Selected) : null; } else { EditObject.ReferenciaGeografica = EditEntityGeoRef1.GetNewGeoRefference(); EditObject.ReferenciaGeografica.Descripcion = EditObject.Descripcion; EditObject.ReferenciaGeografica.Empresa = cbEmpresa.Selected > 0 ? DAOFactory.EmpresaDAO.FindById(cbEmpresa.Selected) : null; EditObject.ReferenciaGeografica.Linea = cbLinea.Selected > 0 ? DAOFactory.LineaDAO.FindById(cbLinea.Selected) : null; var code = EditObject.Codigo; EditObject.ReferenciaGeografica.Codigo = code; var i = 1; var byCode = DAOFactory.ReferenciaGeograficaDAO.FindByCodigoStartWith(cbEmpresa.SelectedValues, cbLinea.SelectedValues, new[] { EditEntityGeoRef1.TipoReferenciaGeograficaId }, code); while (byCode.Any(r => r.Codigo == code && EditObject.ReferenciaGeografica.Id != r.Id)) { code += "(" + i++ + ")"; } EditObject.ReferenciaGeografica.Codigo = code; DAOFactory.ReferenciaGeograficaDAO.SingleSaveOrUpdate(EditObject.ReferenciaGeografica); STrace.Trace("QtreeReset", "PtoEntregaAlta"); } DAOFactory.PuntoEntregaDAO.SaveOrUpdate(EditObject); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); throw ex; } } }
protected override async Task BuildTransaction(string password, PaymentIntent payments, FeeStrategy feeStrategy, bool allowUnconfirmed = false, IEnumerable <OutPoint> allowedInputs = null) { BuildTransactionResult result = await Task.Run(() => Wallet.BuildTransaction(Password, payments, feeStrategy, allowUnconfirmed: true, allowedInputs: allowedInputs, GetPayjoinClient())); MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.SigningTransaction); SmartTransaction signedTransaction = result.Transaction; if (Wallet.KeyManager.IsHardwareWallet && !result.Signed) // If hardware but still has a privkey then it's password, then meh. { try { IsHardwareBusy = true; MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.AcquiringSignatureFromHardwareWallet); var client = new HwiClient(Global.Network); using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(3)); PSBT signedPsbt = null; try { try { signedPsbt = await client.SignTxAsync(Wallet.KeyManager.MasterFingerprint.Value, result.Psbt, cts.Token); } catch (PSBTException ex) when(ex.Message.Contains("NullFail")) { NotificationHelpers.Warning("Fall back to Unverified Inputs Mode, trying to sign again."); // Ledger Nano S hackfix https://github.com/MetacoSA/NBitcoin/pull/888 var noinputtx = result.Psbt.Clone(); foreach (var input in noinputtx.Inputs) { input.NonWitnessUtxo = null; } signedPsbt = await client.SignTxAsync(Wallet.KeyManager.MasterFingerprint.Value, noinputtx, cts.Token); } } catch (HwiException) { await PinPadViewModel.UnlockAsync(); signedPsbt = await client.SignTxAsync(Wallet.KeyManager.MasterFingerprint.Value, result.Psbt, cts.Token); } signedTransaction = signedPsbt.ExtractSmartTransaction(result.Transaction); } finally { MainWindowViewModel.Instance.StatusBar.TryRemoveStatus(StatusType.AcquiringSignatureFromHardwareWallet); IsHardwareBusy = false; } } MainWindowViewModel.Instance.StatusBar.TryAddStatus(StatusType.BroadcastingTransaction); await Task.Run(async() => await Global.TransactionBroadcaster.SendTransactionAsync(signedTransaction)); ResetUi(); }
private static void AnalyzeReceive(SmartTransaction tx) { // No matter how much anonymity a user would had gained in a tx, if the money comes from outside, then make anonset 1. foreach (var key in tx.WalletOutputs.Select(x => x.HdPubKey)) { key.SetAnonymitySet(1, tx.GetHash()); } }
public BuildTransactionResult(SmartTransaction transaction, PSBT psbt, bool signed, Money fee, decimal feePercentOfSent) { Transaction = Guard.NotNull(nameof(transaction), transaction); Psbt = Guard.NotNull(nameof(psbt), psbt); Signed = signed; Fee = fee ?? Money.Zero; FeePercentOfSent = feePercentOfSent; }
public BuildTransactionResult(SmartTransaction transaction, PSBT psbt, bool signed, Money fee, decimal feePercentOfSent) { Transaction = transaction; Psbt = psbt; Signed = signed; Fee = fee; FeePercentOfSent = feePercentOfSent; }
private static QtreeNode GetQtree(int empresa, int linea) { var lastMod = ReferenciaGeograficaDAO.GetLastUpdate(empresa, linea); var key = GetQtreeKey(empresa, linea); var root = Qtrees.ContainsKey(key) ? Qtrees[key] : null; if (root != null && lastMod < root.LastUpdate) { return(root); } if (Monitor.TryEnter(Qtrees)) { try { STrace.Error("ResetQtree", string.Format("qtree UPDATE ---> Empresa: {0} - Linea: {1}", empresa, linea)); using (var transaction = SmartTransaction.BeginTransaction()) { var daoFactory = new DAOFactory(); var geocercas = daoFactory.ReferenciaGeograficaDAO.GetGeocercasFor(empresa, linea); transaction.Commit(); var keyToRemove = string.Empty; if (root != null) { keyToRemove = key; } root = new QtreeNode(); foreach (var geocerca in geocercas) { root.AddValue(geocerca); } if (keyToRemove != string.Empty) { Qtrees.Remove(keyToRemove); } Qtrees.Add(key, root); } STrace.Trace("DispatcherLock", string.Format("qtree NEW ---> {0} | {1}", empresa, linea)); } finally { Monitor.Exit(Qtrees); } } else { STrace.Trace("DispatcherLock", string.Format("qtree OLD ---> {0} | {1}", empresa, linea)); } return(root); }
private void BelieveTransaction(SmartTransaction transaction) { if (transaction.Height == Height.Unknown) { transaction.SetUnconfirmed(); } WalletManager.Process(transaction); }
/// <summary> /// Saves current object. /// </summary> protected override void OnSave() { var oldIcon = EditObject.Icono; var newIcon = SelectIcon2.Selected > 0 ? DAOFactory.IconoDAO.FindById(SelectIcon2.Selected) : null; var iconChanged = oldIcon != newIcon; EditObject.Codigo = txtCodigo.Text.Trim(); EditObject.Descripcion = txtDescripcion.Text.Trim(); EditObject.Icono = newIcon; EditObject.ControlaEntradaSalida = chkControlaES.Checked; EditObject.ControlaVelocidad = chkControlaVelocidad.Checked; EditObject.InhibeAlarma = chkInhibeAlarma.Checked; EditObject.EsZonaDeRiesgo = chkZonaRiesgo.Checked; EditObject.ExcluirMonitor = chkExcluyeMonitor.Checked; EditObject.EsTaller = chkEsTaller.Checked; EditObject.EsControlAcceso = chkEsControlAcceso.Checked; EditObject.ControlaPermanencia = chkControlaPermanencia.Checked; EditObject.ControlaPermanenciaEntrega = chkControlaPermanenciaEntrega.Checked; EditObject.MaximaPermanencia = chkControlaPermanencia.Checked ? Convert.ToInt32((string)txtMaximaPermanencia.Text) : 0; EditObject.MaximaPermanenciaEntrega = chkControlaPermanenciaEntrega.Checked ? Convert.ToInt32((string)txtMaximaPermanenciaEntrega.Text) : 0; EditObject.EsInicio = chkInicio.Checked; EditObject.EsIntermedio = chkIntermedio.Checked; EditObject.EsFin = chkFin.Checked; EditObject.Color.HexValue = ColorPicker.Color; EditObject.Linea = cbLinea.Selected > 0 ? DAOFactory.LineaDAO.FindById(cbLinea.Selected) : null; EditObject.Empresa = EditObject.Linea != null ? EditObject.Linea.Empresa : cbEmpresa.Selected > 0 ? DAOFactory.EmpresaDAO.FindById(cbEmpresa.Selected) : null; if (EditObject.ControlaVelocidad) { AddSpeedLimits(); } using (var transaction = SmartTransaction.BeginTransaction()) { try { DAOFactory.TipoReferenciaGeograficaDAO.SaveOrUpdate(EditObject); if (EditMode && iconChanged) { UpdateGeoRefIcons(oldIcon, newIcon); } transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); throw ex; } } }
public async Task SendTransactionAsync(SmartTransaction transaction) { try { // Broadcast to a random node. // Wait until it arrives to at least two other nodes. // If something's wrong, fall back broadcasting with rpc, then backend. if (Network == Network.RegTest) { throw new InvalidOperationException($"Transaction broadcasting to nodes does not work in {Network.RegTest}."); } Node node = Nodes.ConnectedNodes.RandomElement(); while (node == default(Node) || !node.IsConnected || Nodes.ConnectedNodes.Count < 5) { // As long as we are connected to at least 4 nodes, we can always try again. // 3 should be enough, but make it 5 so 2 nodes could disconnect the meantime. if (Nodes.ConnectedNodes.Count < 5) { throw new InvalidOperationException("We are not connected to enough nodes."); } await Task.Delay(100).ConfigureAwait(false); node = Nodes.ConnectedNodes.RandomElement(); } await BroadcastTransactionToNetworkNodeAsync(transaction, node).ConfigureAwait(false); } catch (Exception ex) { Logger.LogInfo($"Random node could not broadcast transaction. Reason: {ex.Message}."); Logger.LogDebug(ex); if (RpcClient != null) { try { await BroadcastTransactionWithRpcAsync(transaction).ConfigureAwait(false); } catch (Exception ex2) { Logger.LogInfo($"RPC could not broadcast transaction. Reason: {ex2.Message}."); Logger.LogDebug(ex2); await BroadcastTransactionToBackendAsync(transaction).ConfigureAwait(false); } } else { await BroadcastTransactionToBackendAsync(transaction).ConfigureAwait(false); } } finally { BitcoinStore.MempoolService.TryRemoveFromBroadcastStore(transaction.GetHash(), out _); // Remove it just to be sure. Probably has been removed previously. } }
public static SmartTransaction RandomSmartTransaction() { var tx = Transaction.Create(Network.Main); tx.Outputs.Add(Money.Coins(1), new Key()); var stx = new SmartTransaction(tx, Height.Mempool); return(stx); }
public SendSuccessViewModel(Wallet wallet, SmartTransaction finalTransaction) { _wallet = wallet; _finalTransaction = finalTransaction; NextCommand = ReactiveCommand.Create(OnNext); SetupCancel(enableCancel: false, enableCancelOnEscape: true, enableCancelOnPressed: true); }