public void TestDoubleSpendOnForkPending()
{
// Check what happens when a re-org happens and one of our UNconfirmed transactions becomes invalidated by a
// double spend on the new best chain.
Transaction eventDead = null;
Transaction eventReplacement = null;
_wallet.DeadTransaction +=
(sender, e) =>
{
eventDead = e.DeadTx;
eventReplacement = e.ReplacementTx;
};
// Start with 50 coins.
var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);
_chain.Add(b1);
var t1 = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0));
var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams);
var t2 = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0));
_wallet.ConfirmSend(t1);
// t1 is still pending ...
var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
_chain.Add(b2);
Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated));
// Now we make a double spend become active after a re-org.
// genesis -> b1 -> b2 [t1 pending]
// \-> b3 (t2) -> b4
var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
b3.AddTransaction(t2);
b3.Solve();
_chain.Add(b3); // Side chain.
var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
_chain.Add(b4); // New best chain.
// Should have seen a double spend against the pending pool.
Assert.AreEqual(t1, eventDead);
Assert.AreEqual(t2, eventReplacement);
Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance());
// ... and back to our own parallel universe.
var b5 = b2.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
_chain.Add(b5);
var b6 = b5.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
_chain.Add(b6);
// genesis -> b1 -> b2 -> b5 -> b6 [t1 pending]
// \-> b3 [t2 inactive] -> b4
Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated));
}