…eady in mempool
Mempool loads first, wallet second. Second attempt fails, marking that transaction !fInMempool. Those funds will disappear until confirmation is reached.
…eady in mempool
Mempool loads first, wallet second. Second attempt fails, marking that transaction !fInMempool. Those funds will disappear until confirmation is reached.
Hmm, seems like its working around the issue instead of fixing, I think CWalletTx::AcceptToMemoryPool shouldn't unset fInMempool if its already set.
You could add the test to mempool_persist.py instead, as wallet is already a "test everything that has something to do with sending bitcoin"
@TheBlueMatt right, feels quite brittle, but wanted to throw up a working solution/test.
Knowing whether a boolean is already set sounds like boost::optional(?) @MarcoFalke noted, will move
Well, I suppose you mean if it's set true, don't every change the value from that call.
@instagibbs huh? No, just change the third-to-last line in wallet.cpp to fInMempool |= ret from fInMempool = ret.
@TheBlueMatt I honestly still don't understand the current comment in the logic. As long as this is only being called once on startup, your suggestion seems like a correct fix at least.
Knowing whether a boolean is already set sounds like boost::optional(?)
Or std::optional as of C++17 :-)
@instagibbs the entered-mempool callback referred to there is async, so you can create a transaction, put it in the mempool, and then the IsInMempool() call will return false for some time. Thus, change outputs will "not be spendable" until the callbacks catch up if we didnt set fInMempool to true in AcceptToMemoryPool.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Tested ACK f72f5e2576650c3fc314e16f33dbcf24e85520ec
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCgAGBQJaKCkKAAoJENLqSFDnUoslHSkP/2QJqJa6aKFbp4ripP81rep5
jB074r5uPkh6Oa4MgbCI4dte9BQNkfIZ8wTl9sfNax50j8TMeglSHubn6P/F50A/
zo0HJG767dvQMxGd+KSxYAS9nk9Oh4iY6SZs44lVYvOxUjnzlRTl9ElbzmDW+BOY
deqwbH3xv25Ii9+xrvjzHBt/3jiWmdMDJ6NjqJofCmsrLARY3NHL/IQhAG8sqSPR
QSu81crg25IshaO55JPOu2EyXMhnv5M3AF3O4kqaxSFZ3CyioXJhMgggs+n/ZZbI
0hGOxNFHjAznTOFD3/a8/6ritVtpyhUbtPe00k0LcAssTWiqjLtfU2mEpF/HudYV
HvNdDogxXoXjsQTKjxtKYetm1oe/NrGtRpI207cMw5TL+q2XINRApgCJ48Sb5qVr
cOsVokhy1VdPS8OGQHGusiEfmUC60nX8thixbKbhf/z76NEFiPDNT4Nyq5qjIs82
ps2EbX9L66IPCKwP2w25L2EMK3cZaTkox2XNfQS0zKM/reDSzUSlypENA7V/R7dz
CaE7rCOwllHUu/mr9ANKcug3jeikDkrI7kFDg11Dxr9Pdt97YUrJtblYmL97Nlyp
NDZihNY1xCfFLUqQXwpxDma+VEcafeTw1R7mZDHWQwg04Vtd+U/EX+6Rw2Cs4TAU
awhmaenWj7pKls9ql2gW
=MeI2
-----END PGP SIGNATURE-----
@TheBlueMatt although unrelated to this bug, isn't it a good idea in general to check !mempool.exists(...) before trying to add a transaction to the mempool? Or perhaps AcceptToMemoryPool should check if already contains the transaction before proceeding?
Or does that not work due to the concurrency issue you described?
If you move the fix to CWalletTx::AcceptToMemoryPool, it should check for mempool.exists() instead of the |= logic. Imo this better documents by code what is being done.
@Sjors Probably posted that to the wrong thread
I think |= is more correct than it is now anyway - if a transaction isn't in mempool and fails to be added, we shoul unset fInMempool in the callback, not in CWalletTx::AcceptToMemoryPool.
mark as 0.16 milestone? This is a potentially scary bug for users.
moved mempool check logic closer to source, moved test to mempool_persist.py
4113 | @@ -4114,6 +4114,11 @@ int CMerkleTx::GetBlocksToMaturity() const 4114 | 4115 | bool CWalletTx::AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) 4116 | { 4117 | + // Quick check to avoid re-setting fInMempool to false
And to avoid wasting time?
utACK 6697a7089441deded836332e7ce3b4a1a9a3cbcd
post-utACK.
Milestone
0.16.0