public async Task ReorgSameBlockAgainAsync() { int blocks = 300; int transactionsPerBlock = 3; string dir = PrepareWorkDir(); var network = Network.Main; await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); foreach (var height in Enumerable.Range(1, blocks)) { var blockHash = RandomUtils.GetUInt256(); foreach (var n in Enumerable.Range(0, transactionsPerBlock)) { txStore.AddOrUpdate(CreateTransaction(height, blockHash)); } } var storedTxs = txStore.GetTransactions(); Assert.Equal(blocks * transactionsPerBlock, storedTxs.Count()); var newestConfirmedTx = storedTxs.Last(); var tipHeight = blocks; var tipHash = newestConfirmedTx.BlockHash; Assert.Equal(tipHeight, newestConfirmedTx.Height.Value); // reorgs non-existing block var reorgedTxs = txStore.ReleaseToMempoolFromBlock(RandomUtils.GetUInt256()); Assert.Empty(reorgedTxs); // reorgs most recent block reorgedTxs = txStore.ReleaseToMempoolFromBlock(newestConfirmedTx.BlockHash); Assert.Equal(3, reorgedTxs.Count()); Assert.All(reorgedTxs, tx => Assert.False(tx.Confirmed)); Assert.All(reorgedTxs, tx => Assert.True(txStore.TryGetTransaction(tx.GetHash(), out _))); Assert.False(txStore.TryGetTransaction(tipHash, out _)); Assert.DoesNotContain(tipHash, txStore.GetTransactionHashes()); // reorgs the same block again reorgedTxs = txStore.ReleaseToMempoolFromBlock(newestConfirmedTx.BlockHash); Assert.Empty(reorgedTxs); Assert.False(txStore.TryGetTransaction(tipHash, out _)); Assert.DoesNotContain(tipHash, txStore.GetTransactionHashes()); // reorgs deep block var oldestConfirmedTx = storedTxs.First(); var firstBlockHash = oldestConfirmedTx.BlockHash; // What to do here reorgedTxs = txStore.ReleaseToMempoolFromBlock(firstBlockHash); Assert.NotEmpty(reorgedTxs); }
public async Task ReorgAsync() { PrepareTestEnv( out string dir, out Network network, out string mempoolFile, out string txFile, out SmartTransaction uTx1, out SmartTransaction uTx2, out SmartTransaction uTx3, out SmartTransaction _, out SmartTransaction cTx2, out SmartTransaction cTx3); // Duplication is resolved with labels merged. var mempoolFileContent = new[] { uTx1.ToLine(), uTx2.ToLine(), uTx3.ToLine(), }; var txFileContent = new[] { cTx2.ToLine(), cTx3.ToLine() }; await File.WriteAllLinesAsync(mempoolFile, mempoolFileContent); await File.WriteAllLinesAsync(txFile, txFileContent); await using var txStore = new AllTransactionStore(dir, network); await txStore.InitializeAsync(ensureBackwardsCompatibility : false); // Two transactions are in the mempool store and unconfirmed. Assert.True(txStore.MempoolStore.TryGetTransaction(uTx1.GetHash(), out SmartTransaction myUnconfirmedTx1)); Assert.False(myUnconfirmedTx1.Confirmed); Assert.True(txStore.MempoolStore.TryGetTransaction(uTx2.GetHash(), out SmartTransaction myUnconfirmedTx2)); Assert.False(myUnconfirmedTx2.Confirmed); // Create the same transaction but now with a Height to make it confirmed. const int ReorgedBlockHeight = 34532; uint256 reorgedBlockHash = new uint256(5); var tx1Confirmed = new SmartTransaction(uTx1.Transaction, new Height(ReorgedBlockHeight), blockHash: reorgedBlockHash, label: "buz, qux"); var tx2Confirmed = new SmartTransaction(uTx2.Transaction, new Height(ReorgedBlockHeight), blockHash: reorgedBlockHash, label: "buz, qux"); Assert.True(txStore.TryUpdate(tx1Confirmed)); Assert.True(txStore.TryUpdate(tx2Confirmed)); // Two transactions are in the ConfirmedStore store and confirmed. Assert.True(txStore.ConfirmedStore.TryGetTransaction(uTx1.GetHash(), out SmartTransaction mytx1)); Assert.False(txStore.MempoolStore.TryGetTransaction(uTx1.GetHash(), out _)); Assert.True(mytx1.Confirmed); Assert.True(txStore.ConfirmedStore.TryGetTransaction(uTx2.GetHash(), out SmartTransaction mytx2)); Assert.False(txStore.MempoolStore.TryGetTransaction(uTx2.GetHash(), out _)); Assert.True(mytx2.Confirmed); // Now reorg. txStore.ReleaseToMempoolFromBlock(reorgedBlockHash); // Two transactions are in the mempool store and unconfirmed. Assert.True(txStore.MempoolStore.TryGetTransaction(uTx1.GetHash(), out SmartTransaction myReorgedTx1)); Assert.False(txStore.ConfirmedStore.TryGetTransaction(uTx1.GetHash(), out _)); Assert.False(myReorgedTx1.Confirmed); Assert.True(txStore.MempoolStore.TryGetTransaction(uTx2.GetHash(), out SmartTransaction myReorgedTx2)); Assert.False(txStore.ConfirmedStore.TryGetTransaction(uTx2.GetHash(), out _)); Assert.False(myReorgedTx2.Confirmed); }