public void AddBlock(ChainedHeader chainedHeader, IEnumerable <BlockTx> blockTxes, CancellationToken cancelToken = default(CancellationToken)) { var confirmedTxes = ImmutableDictionary.CreateBuilder <UInt256, UnconfirmedTx>(); updateLock.DoWrite(() => { using (var handle = storageManager.OpenUnconfirmedTxesCursor()) { var unconfirmedTxesCursor = handle.Item; unconfirmedTxesCursor.BeginTransaction(); var newChain = chain.Value.ToBuilder().AddBlock(chainedHeader).ToImmutable(); foreach (var blockTx in blockTxes) { // remove any txes confirmed in the block from the list of unconfirmed txes UnconfirmedTx unconfirmedTx; if (unconfirmedTxesCursor.TryGetTransaction(blockTx.Hash, out unconfirmedTx)) { // track confirmed txes confirmedTxes.Add(unconfirmedTx.Hash, unconfirmedTx); if (!unconfirmedTxesCursor.TryRemoveTransaction(blockTx.Hash)) { throw new InvalidOperationException(); } } // check for and remove any unconfirmed txes that conflict with the confirmed tx var confirmedTx = blockTx.EncodedTx.Decode().Transaction; foreach (var input in confirmedTx.Inputs) { var conflictingTxes = unconfirmedTxesCursor.GetTransactionsSpending(input.PrevTxOutputKey); if (conflictingTxes.Count > 0) { logger.Warn($"Removing {conflictingTxes.Count} conflicting txes from the unconfirmed transaction pool"); // remove the conflicting unconfirmed txes foreach (var conflictingTx in conflictingTxes.Keys) { if (!unconfirmedTxesCursor.TryRemoveTransaction(conflictingTx)) { throw new StorageCorruptException(StorageType.UnconfirmedTxes, $"{conflictingTx} is indexed but not present"); } } } } } unconfirmedTxesCursor.ChainTip = chainedHeader; commitLock.DoWrite(() => { unconfirmedTxesCursor.CommitTransaction(); chain = new Lazy <Chain>(() => newChain).Force(); }); } }); TxesConfirmed?.Invoke(this, new TxesConfirmedEventArgs(chainedHeader, confirmedTxes.ToImmutable())); }
private void RaiseTxesConfirmed(object sender, TxesConfirmedEventArgs e) { TxesConfirmed?.Invoke(this, e); }