Skip to content
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

core: Check can trade with new wallet. #1055

Merged
merged 4 commits into from
May 12, 2021

Conversation

JoeGruffins
Copy link
Member

If a user has active trades, they must be settled by a wallet that can
complete those trades. Disallow changing to a new wallet that cannot do
this.

closes #968

@JoeGruffins JoeGruffins marked this pull request as ready for review April 19, 2021 06:44
client/core/core_test.go Outdated Show resolved Hide resolved
client/core/core.go Outdated Show resolved Hide resolved
Comment on lines 1908 to 1909
addr := trade.Trade().Address
owns, err := wallet.OwnsAddress(addr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only the right address for the "from asset" (quote asset + buy order, or base asset + sell order). For the other asset, you could in theory check the refund address, but Core doesn't store that and it's not part of the *asset.Contract right now. Hmm. Not sure what to do.

I have to take blame for this situation, since I declined to store the refund address in the OrderMetadata and even removed access to the refund address when asset.Contract was changed from an interface to a concrete type.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's now checking refund addresses should it find any. Do I have my from/to asset terminology backwards?

If a user has active trades, they must be settled by a wallet that can
complete those trades. Disallow changing to a new wallet that cannot do
this.
@JoeGruffins
Copy link
Member Author

Had this strange test error once but don't think it's related to this pr, has this been seen before?

--- FAIL: TestReorg (1.01s)
    btc_test.go:1253: chain A block still mainchain for test 3:3 after reorg
2021-05-03 15:26:54.379 [ERR] TEST: CheckAddress error for btc : decoded address is of unknown format
2021-05-03 15:26:54.381 [ERR] TEST: CheckAddress error for btc 28Zpft83eov56iESWuPpV8XFLJ1b8gMZy7: checksum mismatch
2021-05-03 15:26:54.381 [ERR] TEST: CheckAddress error for btc 3GD2fSQxhkXDAW66i6JBwCqhLFSvhMNrtO: decoded address is of unknown format
2021-05-03 15:26:54.381 [ERR] TEST: CheckAddress error for btc 3GD2fSQx: checksum mismatch
FAIL
FAIL    decred.org/dcrdex/server/asset/btc      2.970s

client/core/core.go Outdated Show resolved Hide resolved
@@ -1687,6 +1687,15 @@ func (btc *ExchangeWallet) AuditContract(coinID, contract, txData dex.Bytes) (*a
}, nil
}

// RefundAddress extracts and returns the refund address from a contract.
func (btc *ExchangeWallet) RefundAddress(contract dex.Bytes) (string, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For *BCHWallet you'll need to convert with RecodeCashAddress. See e.g. (*BCHWallet).Address().

client/core/core.go Outdated Show resolved Hide resolved
Comment on lines 1936 to 1939
script := match.MetaData.Proof.Script
if len(script) == 0 {
continue
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the new wallet doesn't have the balance to cover the trades? What about locked outpoints?

This has the potential to get really messy, I think. I'm not sure that we can reject changes under any circumstances without creating the potential for wedged orders. There are some changes that simply cannot be made with active orders like changing the account, and some that absolutely must be allowed if we are to completely avoid wedged orders, like changing the wallet password.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe once wallets are internalized, this problem goes away? Will that bee real soon? Can consider this a bandaid?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even when we have built-ins, remote wallets will still be an option.

We can probably get away with a simpler filter for now and punt on a comprehensive solution. But maybe just reject any changes when the wallet is the fromWallet on an active match. Don't even check the refund address, just error.

Copy link
Member Author

@JoeGruffins JoeGruffins May 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the new wallet doesn't have the balance to cover the trades? What about locked outpoints?

The purpose is to not allow changing to a different wallet with active trades. I think there is a change of the "toAsset" falling through if not yet matched because we don't have a refund address yet. Will the trade error out later if not enough funds?

changing the account

I see, we really need to check that an address belongs to an account, and not a wallet, to ensure the account hasn't changed?

changing the wallet password.

There shouldn't be a scenario where this blocks that.

Should I work on something more complex, or is it alright to specify this as temporary? Still guessing not an issue once wallets are internal by default.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, ownsAddress does check if it's this account that owns it.

Copy link
Member

@buck54321 buck54321 May 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can maybe roll with the refund address check as you have it. Better to be over-persmissive, I guess. But note that the following situation is problematic.

Our order matches as taker. Counterparty has broadcast. We have received audit request, but are waiting for confirmation before broadcasting our swap. In this case, if the user tries to reconfigure the fromWallet, even changing the account or wallet altogether, they will encounter no resistance, but will definitely error at swap time.

I wonder if we can reject changes in the specific case of being a taker in MakerSwapCast?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still confused with to/from, but we are talking about having no refund address yet here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have it right in the code.You only check the refund address if trade.wallets.fromAsset.ID == waID. The refund address always comes from the fromWallet.

If my thinking is right, then answering this question should help. In what situation would we have no refund address = len(match.MetaData.Proof.Script) == 0?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think no refund address = len(match.MetaData.Proof.Script) == 0 itself it always correct? But it's true from order status epoch up until match status MakerSwapCast for the maker and TakerSwapCast for the taker?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like maybeDifferentWallet resolves my concerns. Will retest and approve.

@JoeGruffins JoeGruffins force-pushed the checkcantrade branch 2 times, most recently from 1620a9e to 6cd26d8 Compare May 4, 2021 01:30
@JoeGruffins
Copy link
Member Author

Sorry for that rebase, commit message was wrong.

Comment on lines +1946 to +1957
}
// Assume all refund addresses
// are owned by the new
// wallet if one is.
return nil
}
// If we did not find a refund address,
// we cannot be sure that this is the
// same wallet.
//
// TODO: Implement a way to check that
// these accounts are the same or not.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Epic indent here! 😄 I think I might have made a package level function or dexConnection method taking an xcWallet instead of a closure, but this is fine.

@chappjc chappjc merged commit 3fa59cf into decred:master May 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ensure new wallet can process existing orders when connecting
3 participants