-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
client/asset/dcr: workaround TxDetails unconfirmed bug #2444
Conversation
if dcr.wallet.SpvMode() { | ||
return txOut, confs, -1, nil // make it do a cfilters scan because GetTransaction lies | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a possible workaround, which unfortunately forces the cfilters scan path even when GetTransaction
did return a result (it's a wallet transaction i.e. checking your own swap confirms, or it's a self-trade)
// Check with TxConfirms and TxBlock now, why not. | ||
confs, err := w.dcrWallet.TxConfirms(ctx, txHash) | ||
if err != nil { | ||
w.log.Warnf("TxConfirms: %v", err) | ||
} else if confs > 0 { | ||
w.log.Warnf("TxConfirms says yes! %d confs", confs) | ||
} | ||
blockHash, blockHeight, err := w.dcrWallet.TxBlock(ctx, txHash) | ||
if err != nil { | ||
w.log.Warnf("TxBlock: %v", err) | ||
} else if blockHeight > 0 { | ||
w.log.Warnf("TxBlock says yes! block %v, height %d", blockHash, blockHeight) | ||
ret.BlockHash = blockHash.String() | ||
ret.Confirmations = int64(tipHeight - blockHeight + 1) | ||
goto gotit | ||
} | ||
_, confs2, blockHashP, err := w.dcrWallet.TransactionSummary(ctx, txHash) | ||
if err != nil { | ||
w.log.Warnf("TransactionSummary: %v", err) | ||
} else if confs2 > 0 { | ||
w.log.Warnf("TransactionSummary says yes! block %v, confs %d", blockHashP, confs2) | ||
ret.BlockHash = blockHashP.String() | ||
ret.Confirmations = int64(confs2) | ||
goto gotit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this is because I wanted to see if any of the other wallet
methods can give a conf or block inspite of TxDetails
. It does not appear to return any different results. This seems to be because they all stop on existsRawUnmined
, just like TxDetails
.
Appears that under normal operation without shutting down, dcrwallet always reaches
Way back at matchingTxs, err = s.scanChain(ctx, rp, bestChain, bmap) which are passed in to On startup though, they add headers via Still poking around. |
Interesting. Just one thing I want to clarify is that when I've reproduced the bug, the wallet started up at the same best block as when it shut down, and only a bit later (minutes) the tx would be really mined. This would correspond to the |
As per convo with @jrick, there's a very long standing known bug with wallet startup when there are unconfirmed transactions, whereby they are often never confirmed without a rescan. That appears to be what we are seeing. Assuming the underlying wallet bug isn't fixed, I propose the workaround I called out in |
Pertains to #2442.
There is an issue given:
I believe you must be both maker and taker (self trade) for it to halt the swap because if you are not also the taker who authored the DCR swap transaction, then for maker, the
SwapConfirmations
method will fallback to cfilters scan whenlookupTxOutput
fails to find the transaction. Or so I would expect since the counterparty contract transaction would not be a wallet transaction.The above is not always reproducible, but I managed to get it to happen twice with the native SPV wallet.
I tracked the culprit down to
dcrwallet/wallet/udb.(*Store).TxDetails
. It will find and return an unmined transaction that it finds withexistsRawUnmined
andunminedTxDetails
(but it's really mined, several confs even).https://github.com/decred/dcrwallet/blob/master/wallet/udb/txquery.go#L180-L194
I do not know if it would find a mined transaction also if it could get down to
latestTxRecord
andminedTxDetails
, but it seems the transaction is left inbucketUnmined
. i.e.deleteRawUnmined
is not called as expected. There are only two call sites fordeleteRawUnmined
:wallet/udb.(*Store).moveMinedTx
wallet/udb.(*Store).RemoveUnconfirmed
I don't know which isn't getting called.
Perhaps one detail worth noting is that I generally use a split tx in the order, meaning the resulting DCR swap contract transaction will have no change, so it's just the input/debit that belongs to the authoring wallet, and the one swap output technically belongs to neither wallet.