private Transaction GetTransactionOrNull(Stratis.Bitcoin.Features.WatchOnlyWallet.TransactionData transactionData)
 {
     try
     {
         var transaction = transactionData?.Transaction;
         return(transaction);
     }
     catch
     {
         return(null);
     }
 }
Esempio n. 2
0
        /// <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();
        }
Esempio n. 3
0
        /// <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();
            }
        }