In 0.12, a wallet tx thats not in the mempool does not free up its inputs.  So if a tx spends the same inputs as a conflict tx included in a new block, its inputs are explicitly marked dirty so they will be recalculated as spendable again due to having no non-conflicted spends.  However if the in-block conflict is reorged out, the wallet txs inputs should now be market spent again according to the 0.12 regime, but they are not marked dirty as the tx itself is not notified it is no longer conflicted.

This has the odd effect that the cached value is incorrect and so randomly they will be spendable or not depending on whether they have been recalculated.

This is easy enough to fix by marking all inputs of all txs in SyncTransaction dirty regardless of whether AddToWalletIfInvolvingMe returns true or false.  But I'm not sure the performance impact this will have, so I'm not proposing that change now.

It's a minor issue, but I just thought I'd document that that the cached credit available in wallet txs may not always be correct.

For reference, in 0.11, whenever a tx left the mempool it's inputs were respendable.  So if a tx was removed due to a conflict in a block, any remaining inputs would be spendable again.  If the in-block conflict was later reorged out, the wallet txs inputs would remain spendable unless and until the wallet tx reentered the mempool.

int sighash_type = SIGHASH_DEFAULT,
                  bool sign = true,
                  bool bip32derivs = true,
                  size_t* n_signed = nullptr,
                  bool finalize = true) const;
    /**
     * Submit the transaction to the node's mempool and then relay to peers.
     * Should be called after CreateTransaction unless you want to abort
     * broadcasting the transaction.
     *
     * @param[in] tx The transaction to be broadcast.
     * @param[in] mapValue key-values to be set on the transaction.
     * @param[in] orderForm BIP 70 / BIP 21 order form details to be set on the transaction.
     */
    void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm);
    
    bool SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
        EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
    bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, const CCoinControl* coin_control = nullptr) const;
    bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
    bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
    bool ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
    bool ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
    
    void FirstKeyTimeChanged(const ScriptPubKeyMan* spkm, int64_t new_birth_time);
    CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
    unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
    /** Allow Coin Selection to pick unconfirmed UTXOs that were sent from our own wallet if it
     * cannot fund the transaction otherwise. */
    bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};