public AnnotatedTransactionCollection(IEnumerable <AnnotatedTransaction> transactions) : base(transactions) { foreach (var tx in transactions) { var h = tx.Record.Transaction.GetHash(); _TxById.Add(h, tx); foreach (var keyPathInfo in tx.Record.TransactionMatch.Inputs.Concat(tx.Record.TransactionMatch.Outputs)) { if (keyPathInfo.KeyPath != null) { _KeyPaths.TryAdd(keyPathInfo.ScriptPubKey, keyPathInfo.KeyPath); } } } UTXOState state = new UTXOState(); foreach (var confirmed in transactions .Where(tx => tx.Type == AnnotatedTransactionType.Confirmed) .TopologicalSort()) { if (state.Apply(confirmed.Record.Transaction) == ApplyTransactionResult.Conflict || !ConfirmedTransactions.TryAdd(confirmed.Record.Transaction.GetHash(), confirmed)) { Logs.Explorer.LogError("A conflict among confirmed transaction happened, this should be impossible"); throw new InvalidOperationException("The impossible happened"); } } foreach (var unconfirmed in transactions .Where(tx => tx.Type == AnnotatedTransactionType.Unconfirmed || tx.Type == AnnotatedTransactionType.Orphan) .OrderByDescending(t => t.Record.Inserted) // OrderByDescending so that the last received is least likely to be conflicted .TopologicalSort()) { var hash = unconfirmed.Record.Transaction.GetHash(); if (ConfirmedTransactions.ContainsKey(hash)) { DuplicatedTransactions.Add(unconfirmed); } else { if (state.Apply(unconfirmed.Record.Transaction) == ApplyTransactionResult.Conflict) { ReplacedTransactions.TryAdd(hash, unconfirmed); } else { if (!UnconfirmedTransactions.TryAdd(hash, unconfirmed)) { throw new InvalidOperationException("The impossible happened (!UnconfirmedTransactions.TryAdd(hash, unconfirmed))"); } } } } }
public AnnotatedTransactionCollection(IEnumerable <AnnotatedTransaction> transactions, Models.TrackedSource trackedSource) : base(transactions) { foreach (var tx in transactions) { foreach (var keyPathInfo in tx.Record.KnownKeyPathMapping) { _KeyPaths.TryAdd(keyPathInfo.Key, keyPathInfo.Value); } } UTXOState state = new UTXOState(); foreach (var confirmed in transactions .Where(tx => tx.Type == AnnotatedTransactionType.Confirmed).ToList() .TopologicalSort()) { if (state.Apply(confirmed.Record) == ApplyTransactionResult.Conflict) { Logs.Explorer.LogError("A conflict among confirmed transaction happened, this should be impossible"); throw new InvalidOperationException("The impossible happened"); } ConfirmedTransactions.Add(confirmed); _TxById.Add(confirmed.Record.TransactionHash, confirmed); } foreach (var unconfirmed in transactions .Where(tx => tx.Type == AnnotatedTransactionType.Unconfirmed || tx.Type == AnnotatedTransactionType.Orphan) .OrderByDescending(t => t.Record.Inserted) // OrderByDescending so that the last received is least likely to be conflicted .ToList() .TopologicalSort()) { if (_TxById.ContainsKey(unconfirmed.Record.TransactionHash)) { _TxById.Add(unconfirmed.Record.TransactionHash, unconfirmed); DuplicatedTransactions.Add(unconfirmed); } else { _TxById.Add(unconfirmed.Record.TransactionHash, unconfirmed); if (state.Apply(unconfirmed.Record) == ApplyTransactionResult.Conflict) { ReplacedTransactions.Add(unconfirmed); } else { UnconfirmedTransactions.Add(unconfirmed); } } } TrackedSource = trackedSource; }
public bool HasChanges() { return(ConfirmedTransactions.HasChanges() || UnconfirmedTransactions.HasChanges() || ReplacedTransactions.HasChanges()); }