@@ -1021,5 +1021,41 @@ BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
1021
1021
HasReason (" DB error adding transaction to wallet, write failed" ));
1022
1022
}
1023
1023
1024
+ /* *
1025
+ * Verify the wallet does not crash when the same block is disconnected twice due to an incompatible coinbase transaction state.
1026
+ */
1027
+ BOOST_FIXTURE_TEST_CASE (wallet_crash_during_disconnectBlock, TestChain100Setup)
1028
+ {
1029
+ const auto & chainman = Assert (m_node.chainman );
1030
+ const int64_t BLOCK_TIME = WITH_LOCK (chainman->GetMutex (), return chainman->ActiveChain ().Tip ()->GetBlockTimeMax () + 5 );
1031
+ SetMockTime (BLOCK_TIME); // to by-pass the wallet birth time.
1032
+
1033
+ CKey key;
1034
+ key.MakeNewKey (true );
1035
+ CreateAndProcessBlock ({}, GetScriptForRawPubKey (key.GetPubKey ()));
1036
+ auto wallet = CreateSyncedWallet (*m_node.chain , WITH_LOCK (chainman->GetMutex (), return chainman->ActiveChain ()), key);
1037
+ BOOST_ASSERT (GetBalance (*wallet, /* min_depth=*/ 0 , false ).m_mine_immature == 50 * COIN);
1038
+
1039
+ // Fetch the latest block data.
1040
+ CBlockIndex* tip = WITH_LOCK (chainman->GetMutex (), return chainman->ActiveChain ().Tip ());
1041
+ CBlock block_data;
1042
+ m_node.chain ->findBlock (tip->GetBlockHash (), interfaces::FoundBlock ().data (block_data));
1043
+
1044
+ // Construct block info for disconnection
1045
+ interfaces::BlockInfo info (*tip->phashBlock );
1046
+ info.data = &block_data;
1047
+ info.prev_hash = tip->phashBlock ;
1048
+ info.height = tip->nHeight ;
1049
+ info.chain_time_max = tip->GetBlockTimeMax ();
1050
+
1051
+ // Disconnect block twice
1052
+ wallet->blockDisconnected (info);
1053
+ wallet->blockDisconnected (info);
1054
+
1055
+ // Ensure the balance was updated correctly.
1056
+ assert (GetBalance (*wallet, /* min_depth=*/ 0 , false ).m_mine_immature == 0 * COIN);
1057
+ }
1058
+
1059
+
1024
1060
BOOST_AUTO_TEST_SUITE_END ()
1025
1061
} // namespace wallet
0 commit comments