示例#1
0
        public Transaction GetTransaction(uint256 txId)
        {
            RPCWalletEntry entry = null;

            if (_WalletEntries.TryGetValue(txId, out entry))
            {
                return(entry.Transaction);
            }
            return(null);
        }
示例#2
0
        private void RemoveTxByScriptId(RPCWalletEntry entry)
        {
            IEnumerable <Script> scripts = GetScriptsOf(entry.Transaction);

            lock (_TxByScriptId)
            {
                foreach (var s in scripts)
                {
                    _TxByScriptId.Remove(s, entry);
                }
            }
        }
示例#3
0
        private void AddTxByScriptId(uint256 txId, RPCWalletEntry entry)
        {
            IEnumerable <Script> scripts = GetScriptsOf(entry.Transaction);

            lock (_TxByScriptId)
            {
                foreach (var s in scripts)
                {
                    _TxByScriptId.Add(s, entry);
                }
            }
        }
示例#4
0
        public void ImportTransaction(Transaction transaction, int confirmations)
        {
            var txId  = transaction.GetHash();
            var entry = new RPCWalletEntry()
            {
                Confirmations = confirmations,
                TransactionId = transaction.GetHash(),
                Transaction   = transaction
            };

            if (_WalletEntries.TryAdd(txId, entry))
            {
                AddTxByScriptId(txId, entry);
            }
        }
        List <RPCWalletEntry> ListTransactions(ref HashSet <uint256> knownTransactions)
        {
            List <RPCWalletEntry> array = new List <RPCWalletEntry>();

            knownTransactions = new HashSet <uint256>();
            var removeFromCache     = new HashSet <uint256>(_TransactionsByTxId.Values.Select(tx => tx.GetHash()));
            int count               = 100;
            int skip                = 0;
            int highestConfirmation = 0;

            while (true)
            {
                var result = _RPCClient.SendCommandNoThrows("listtransactions", "*", count, skip, true);
                skip += count;
                if (result.Error != null)
                {
                    return(null);
                }
                var transactions = (JArray)result.Result;
                foreach (var obj in transactions)
                {
                    var entry = new RPCWalletEntry();
                    entry.Confirmations = obj["confirmations"] == null ? 0 : (int)obj["confirmations"];
                    entry.TransactionId = new uint256((string)obj["txid"]);
                    removeFromCache.Remove(entry.TransactionId);
                    if (knownTransactions.Add(entry.TransactionId))
                    {
                        array.Add(entry);
                    }
                    if (obj["confirmations"] != null)
                    {
                        highestConfirmation = Math.Max(highestConfirmation, (int)obj["confirmations"]);
                    }
                }
                if (transactions.Count < count || highestConfirmation >= 1400)
                {
                    break;
                }
            }
            foreach (var remove in removeFromCache)
            {
                Transaction opt;
                _TransactionsByTxId.TryRemove(remove, out opt);
            }
            return(array);
        }
示例#6
0
        void ListTransactions()
        {
            var removeFromWalletEntries = new HashSet <uint256>(_WalletEntries.Keys);

            int count = 100;
            int skip  = 0;
            int highestConfirmation = 0;

            while (true)
            {
                var result = _RPCClient.SendCommand("listtransactions", "*", count, skip, true);
                skip += count;
                var transactions = (JArray)result.Result;

                var batch = _RPCClient.PrepareBatch();
                var fetchingTransactions = new List <Tuple <RPCWalletEntry, Task <Transaction> > >();
                foreach (var obj in transactions)
                {
                    var entry = new RPCWalletEntry();
                    entry.Confirmations = obj["confirmations"] == null ? 0 : (int)obj["confirmations"];
                    entry.TransactionId = new uint256((string)obj["txid"]);
                    removeFromWalletEntries.Remove(entry.TransactionId);

                    RPCWalletEntry existing;
                    if (_WalletEntries.TryGetValue(entry.TransactionId, out existing))
                    {
                        existing.Confirmations = entry.Confirmations;
                        entry = existing;
                    }

                    if (entry.Transaction == null)
                    {
                        fetchingTransactions.Add(Tuple.Create(entry, FetchTransactionAsync(batch, entry.TransactionId)));
                    }
                    if (obj["confirmations"] != null)
                    {
                        highestConfirmation = Math.Max(highestConfirmation, (int)obj["confirmations"]);
                    }
                }
                batch.SendBatchAsync();

                foreach (var fetching in fetchingTransactions)
                {
                    var entry = fetching.Item1;
                    entry.Transaction = fetching.Item2.GetAwaiter().GetResult();
                    if (entry.Transaction != null)
                    {
                        if (_WalletEntries.TryAdd(entry.TransactionId, entry))
                        {
                            AddTxByScriptId(entry.TransactionId, entry);
                        }
                    }
                }

                if (transactions.Count < count || highestConfirmation >= 1400)
                {
                    break;
                }
            }
            foreach (var remove in removeFromWalletEntries)
            {
                RPCWalletEntry opt;
                _WalletEntries.TryRemove(remove, out opt);
            }
        }
示例#7
0
        void ListTransactions()
        {
            var removeFromWalletEntries = new HashSet <uint256>(_WalletEntries.Keys);

            int count = 100;
            int skip  = 0;
            HashSet <uint256> processedTransacions = new HashSet <uint256>();
            int updatedConfirmationGap             = -1;

            //If this one is true after asking for a batch, just update every "removeFromWalletEntries" transactions by updatedConfirmationGap
            bool canMakeSimpleUpdate = false;

            bool transactionTooOld = false;

            while (true)
            {
                updatedConfirmationGap = -1;
                canMakeSimpleUpdate    = false;
                var result = _RPCClient.SendCommand("listtransactions", "*", count, skip, true);
                skip += count;
                var transactions = (JArray)result.Result;
                if (transactions.Count < count)
                {
                    updatedConfirmationGap = 0;
                    canMakeSimpleUpdate    = false;
                }

                var batch = _RPCClient.PrepareBatch();
                var fetchingTransactions = new List <Tuple <RPCWalletEntry, Task <Transaction> > >();
                foreach (var obj in transactions)
                {
                    var entry = new RPCWalletEntry();
                    entry.Confirmations = obj["confirmations"] == null ? 0 : (int)obj["confirmations"];
                    if (entry.Confirmations >= MaxConfirmations)
                    {
                        transactionTooOld = true;
                        break;
                    }
                    entry.TransactionId = new uint256((string)obj["txid"]);
                    if (!processedTransacions.Add(entry.TransactionId))
                    {
                        continue;
                    }
                    removeFromWalletEntries.Remove(entry.TransactionId);

                    RPCWalletEntry existing;
                    if (_WalletEntries.TryGetValue(entry.TransactionId, out existing))
                    {
                        var confirmationGap = entry.Confirmations - existing.Confirmations;
                        if (entry.Confirmations == 0)
                        {
                            updatedConfirmationGap = 0;
                            canMakeSimpleUpdate    = false;
                        }
                        if (updatedConfirmationGap != -1 && updatedConfirmationGap != confirmationGap)
                        {
                            canMakeSimpleUpdate = false;
                        }

                        if (updatedConfirmationGap == -1)
                        {
                            canMakeSimpleUpdate    = true;
                            updatedConfirmationGap = confirmationGap;
                        }

                        existing.Confirmations = entry.Confirmations;
                        entry = existing;
                    }

                    if (entry.Transaction == null)
                    {
                        fetchingTransactions.Add(Tuple.Create(entry, FetchTransactionAsync(batch, entry.TransactionId)));
                    }
                }
                batch.SendBatchAsync();

                foreach (var fetching in fetchingTransactions)
                {
                    var entry = fetching.Item1;
                    entry.Transaction = fetching.Item2.GetAwaiter().GetResult();
                    if (entry.Transaction != null)
                    {
                        if (_WalletEntries.TryAdd(entry.TransactionId, entry))
                        {
                            AddTxByScriptId(entry.TransactionId, entry);
                        }
                    }
                }
                if (transactions.Count < count || transactionTooOld || canMakeSimpleUpdate)
                {
                    break;
                }
            }

            if (canMakeSimpleUpdate)
            {
                foreach (var tx in removeFromWalletEntries.ToList())
                {
                    RPCWalletEntry entry = null;
                    if (_WalletEntries.TryGetValue(tx, out entry))
                    {
                        if (entry.Confirmations != 0)
                        {
                            entry.Confirmations += updatedConfirmationGap;
                            if (entry.Confirmations <= MaxConfirmations)
                            {
                                removeFromWalletEntries.Remove(entry.TransactionId);
                            }
                        }
                    }
                }
            }

            foreach (var remove in removeFromWalletEntries)
            {
                RPCWalletEntry opt;
                if (_WalletEntries.TryRemove(remove, out opt))
                {
                    RemoveTxByScriptId(opt);
                }
            }
        }