diff --git a/qa/rpc-tests/wallet_orchard.py b/qa/rpc-tests/wallet_orchard.py index c6e59a5a9..19806dfdb 100755 --- a/qa/rpc-tests/wallet_orchard.py +++ b/qa/rpc-tests/wallet_orchard.py @@ -177,5 +177,54 @@ class WalletOrchardTest(BitcoinTestFramework): {'pools': {'orchard': {'valueZat': Decimal('100000000')}}, 'minimum_confirmations': 1}, self.nodes[3].z_getbalanceforaccount(acct3)) + # Split the network again + self.split_network() + + # Spend some of acct3's funds on the 2/3 side of the split + recipients = [{"address": ua2, "amount": Decimal('0.5')}] + myopid = self.nodes[3].z_sendmany(ua3, recipients, 1, 0) + rollback_tx = wait_and_assert_operationid_status(self.nodes[3], myopid) + + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('950000000')}}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + + # Generate a majority chain on the 0/1 side of the split, then + # re-join the network. + self.nodes[1].generate(10) + self.join_network() + + # split 2/3's chain should have been rolled back, so their txn should have been + # un-mined and returned to the mempool + assert_equal(set([rollback_tx]), set(self.nodes[3].getrawmempool())) + + # acct2's balance is back to not contain the Orchard->Orchard value + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('900000000')}}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + + # acct3's sole Orchard note is spent by a transaction in the mempool, so our + # confirmed balance is currently 0 + assert_equal( + {'pools': {}, 'minimum_confirmations': 1}, + self.nodes[3].z_getbalanceforaccount(acct3)) + + # Manually resend the transaction in node 3's mempool + self.nodes[2].resendwallettransactions() + + # Sync the network + self.sync_all() + self.nodes[0].generate(1) + self.sync_all() + + # The un-mined transaction should now have been re-mined + assert_equal( + {'pools': {'orchard': {'valueZat': Decimal('950000000')}}, 'minimum_confirmations': 1}, + self.nodes[2].z_getbalanceforaccount(acct2)) + if __name__ == '__main__': WalletOrchardTest().main() diff --git a/src/main.cpp b/src/main.cpp index aabd26d2e..3fe983b00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6850,11 +6850,12 @@ bool static ProcessMessage(const CChainParams& chainparams, CNode* pfrom, string for (uint256 hash : vEraseQueue) EraseOrphanTx(hash); } - // TODO: currently, prohibit joinsplits and shielded spends/outputs from entering mapOrphans + // TODO: currently, prohibit joinsplits and shielded spends/outputs/actions from entering mapOrphans else if (fMissingInputs && tx.vJoinSplit.empty() && tx.vShieldedSpend.empty() && - tx.vShieldedOutput.empty()) + tx.vShieldedOutput.empty() && + !tx.GetOrchardBundle().IsPresent()) { AddOrphanTx(tx, pfrom->GetId());