private Transaction GetTransactionOrNull(Stratis.Bitcoin.Features.WatchOnlyWallet.TransactionData transactionData) { try { var transaction = transactionData?.Transaction; return(transaction); } catch { return(null); } }
/// <inheritdoc /> public void StoreTransaction(Stratis.Bitcoin.Features.WatchOnlyWallet.TransactionData transactionData) { if (this.wallet.WatchedTransactions.ContainsKey(transactionData.Id.ToString())) { this.logger.LogDebug($"already watching transaction: {transactionData.Id}. coin: {this.coinType}"); return; } this.logger.LogDebug($"added transaction: {transactionData.Id} to the watch list. coin: {this.coinType}"); this.wallet.WatchedTransactions.TryAdd(transactionData.Id.ToString(), new Stratis.Bitcoin.Features.WatchOnlyWallet.TransactionData { BlockHash = transactionData.BlockHash, Hex = transactionData.Hex, Id = transactionData.Id, MerkleProof = transactionData.MerkleProof }); //this.SaveWatchOnlyWallet(); }
/// <inheritdoc /> public void ProcessTransaction(Transaction transaction, Block block = null) { uint256 transactionHash = transaction.GetHash(); this.logger.LogDebug($"watch only wallet received transaction - hash: {transactionHash}, coin: {this.coinType}"); // Check the transaction inputs to see if a watched address is affected. foreach (TxIn input in transaction.Inputs) { // See if the previous transaction is in the watch-only wallet. this.txLookup.TryGetValue(input.PrevOut.Hash, out TransactionData prevTransactionData); // If it is null, it can't be related to one of the watched addresses (or it is the very first watched transaction) if (prevTransactionData == null) { continue; } var prevTransaction = Transaction.Load(prevTransactionData.Hex, this.network); // Check if the previous transaction's outputs contain one of our addresses. foreach (TxOut prevOutput in prevTransaction.Outputs) { this.Wallet.WatchedAddresses.TryGetValue(prevOutput.ScriptPubKey.ToString(), out WatchedAddress addressInWallet); if (addressInWallet != null) { // Retrieve a transaction, if present. addressInWallet.Transactions.TryGetValue(transactionHash.ToString(), out TransactionData existingTransaction); if (existingTransaction == null) { var newTransaction = new TransactionData { Id = transactionHash, Hex = transaction.ToHex(), BlockHash = block?.GetHash() }; // Add the Merkle proof to the transaction. if (block != null) { newTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } addressInWallet.Transactions.TryAdd(transactionHash.ToString(), newTransaction); // Update the lookup cache with the new transaction information. // Since the WO record is new it probably isn't in the lookup cache. this.txLookup.TryAdd(newTransaction.Id, newTransaction); } else { // If there was a transaction already present in the WO wallet, // it is most likely that it has now been confirmed in a block. // Therefore, update the transaction record with the hash of the // block containing the transaction. if (existingTransaction.BlockHash == null) { existingTransaction.BlockHash = block?.GetHash(); } if (block != null && existingTransaction.MerkleProof == null) { // Add the Merkle proof now that the transaction is confirmed in a block. existingTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } // Update the lookup cache with the new transaction information. // Since the WO record was not new it probably is already in the lookup cache. // Therefore, unconditionally update it. this.txLookup.AddOrUpdate(existingTransaction.Id, existingTransaction, (key, oldValue) => existingTransaction); } this.SaveWatchOnlyWallet(); } } } // Check the transaction outputs for transactions we might be interested in. foreach (TxOut utxo in transaction.Outputs) { // Check if the outputs contain one of our addresses. this.Wallet.WatchedAddresses.TryGetValue(utxo.ScriptPubKey.ToString(), out WatchedAddress addressInWallet); if (addressInWallet != null) { // Retrieve a transaction, if present. addressInWallet.Transactions.TryGetValue(transactionHash.ToString(), out TransactionData existingTransaction); if (existingTransaction == null) { var newTransaction = new TransactionData { Id = transactionHash, Hex = transaction.ToHex(), BlockHash = block?.GetHash() }; // Add the Merkle proof to the (non-spending) transaction. if (block != null) { newTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } addressInWallet.Transactions.TryAdd(transactionHash.ToString(), newTransaction); // Update the lookup cache with the new transaction information. // Since the WO record is new it probably isn't in the lookup cache. this.txLookup.TryAdd(newTransaction.Id, newTransaction); } else { // If there was a transaction already present in the WO wallet, // it is most likely that it has now been confirmed in a block. // Therefore, update the transaction record with the hash of the // block containing the transaction. if (existingTransaction.BlockHash == null) { existingTransaction.BlockHash = block?.GetHash(); } if (block != null && existingTransaction.MerkleProof == null) { // Add the Merkle proof now that the transaction is confirmed in a block. existingTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } // Update the lookup cache with the new transaction information. // Since the WO record was not new it probably is already in the lookup cache. // Therefore, unconditionally update it. this.txLookup.AddOrUpdate(existingTransaction.Id, existingTransaction, (key, oldValue) => existingTransaction); } this.SaveWatchOnlyWallet(); } } this.Wallet.WatchedTransactions.TryGetValue(transactionHash.ToString(), out TransactionData existingWatchedTransaction); if (existingWatchedTransaction != null && block != null) { // The transaction was previously stored, in an unconfirmed state. // So now update the block hash and Merkle proof since it has // appeared in a block. existingWatchedTransaction.BlockHash = block.GetHash(); existingWatchedTransaction.MerkleProof = new MerkleBlock(block, new[] { transaction.GetHash() }).PartialMerkleTree; // Update the lookup cache with the new transaction information. this.txLookup.AddOrUpdate(existingWatchedTransaction.Id, existingWatchedTransaction, (key, oldValue) => existingWatchedTransaction); this.SaveWatchOnlyWallet(); } }