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

multi: Version server API. #1047

Merged
merged 5 commits into from
Apr 16, 2021
Merged

multi: Version server API. #1047

merged 5 commits into from
Apr 16, 2021

Conversation

JoeGruffins
Copy link
Member

Add a version to the server that is communicated in the Config response.
Client checks and saves the version. The burden of conforming to an
API version is placed completely on the client.

depends on #1046
closes #530

@JoeGruffins
Copy link
Member Author

Will add some more tests if the idea looks ok.

@chappjc
Copy link
Member

chappjc commented Apr 12, 2021

Thanks, @JoeGruffins.

The plan we decided on was to introduce the API version and have it communicated asap, but keeping it at v0 until dcrdex 1.0 or SPV (probably same release). v0 because it's not stable, but still communicated and checked so when a major bump to v1 happens the client sees that they're going to need to update to a client that knows the v1 API.

Of course we may have to bump 0->1 sooner than SPV if there are changes we can't solve with clever backward compatibility, but I think it's best if we keep it v0 to indicate that there are no promises yet. In my mind the necessity with this PR is having the version checking machinery in place well in advance of such major breaking version bumps... which this PR totally does, but I wanted to talk through the planned jump to a stable v1 proto.

Copy link
Member

@chappjc chappjc left a comment

Choose a reason for hiding this comment

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

Looks like a good start. Having clients looking at the version starting with 0.2 is important.

The other more fine grained versioning we'll need is for each asset. This PR is the version for the comms protocol and maybe some other agreed upon things, but I believe we'll need to version each asset for when things with an asset are changed that don't affect the dex API (e.g. kind of addresses, transaction structure, coin ID encoding, contract address, lock times, encoding of txdata payload, etc.)... things that concern a particular asset backend rather than the higher level core packages or comms.

Comment on lines 68 to 70
// serverAPIVers are the DEX server API versions this client is capable
// of communicating with.
serverAPIVers = []int{serverdex.InitialAPIVersion}
Copy link
Member

Choose a reason for hiding this comment

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

This makes sense and I'm OK with using a server/dex import for this now, but I suspect we're going to want to break the tight coupling of client -> server packages at some point.

Probably we're just discovering things (like server/account) that would be better in the "common" decred.org/dcrdex/dex packages at some point.

Comment on lines 36 to 39
InitialAPIVersion = iota

// APIVersion is the current API version.
APIVersion = InitialAPIVersion
Copy link
Member

Choose a reason for hiding this comment

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

Good to start at v0 as you have now.

@chappjc chappjc added this to the 0.2 milestone Apr 12, 2021
@JoeGruffins
Copy link
Member Author

The other more fine grained versioning we'll need is for each asset.

Maybe something similar to this but a map of asset id to api versions in the config response?

Comment on lines 4409 to 4430
err = dc.refreshServerConfig() // handleReconnect must too
err = dc.refreshServerConfig(serverAPIVers) // handleReconnect must too
if err != nil {
if errors.Is(err, outdatedClientErr) {
sendOutdatedClientNotification(c, dc)
}
return dc, err
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Might be less awkward if just do the api check in a separate function, although it makes sense to me that the API version is the first thing checked in the response and a quick fail is best.

@JoeGruffins JoeGruffins force-pushed the apiconfig branch 2 times, most recently from 687e723 to d1a8b3c Compare April 13, 2021 06:15
Comment on lines 611 to 615
if apiVer != cfgAPIVer {
// If not initiation, do not allow api changes
// between connections.
if apiVer != -1 {
return fmt.Errorf("server API version unexpectedly changed from %v to %v",
Copy link
Member

@chappjc chappjc Apr 13, 2021

Choose a reason for hiding this comment

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

I've been thinking about this, and this seems to be inevitable, so I don't think we have a choice but to go along with the new version if it's recognized. A server update that changes API version will happen and I don't think we should always torpedo connected clients if they recognize the new api version.

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 agree. I just think it opens some angles possibly, that are hard to notice. Will remove, and we'll just be careful when updating.

Copy link
Member

Choose a reason for hiding this comment

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

K. A warning would probably be good though.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added.

func (dc *dexConnection) refreshServerConfig() error {
// refreshServerConfig fetches and replaces server configuration data. It also
// initially checks that a server's API version is one of apiVers.
func (dc *dexConnection) refreshServerConfig(apiVers []int) error {
Copy link
Member

Choose a reason for hiding this comment

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

Why not use the package-level var serverAPIVers instead of an arg?

Copy link
Member Author

Choose a reason for hiding this comment

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

For testing...
If we use the package level variable, it makes testing in parallel a bit difficult, although doable. Will see what it looks like, I guess will need to add a lock to the test harness.

Copy link
Member

@chappjc chappjc Apr 14, 2021

Choose a reason for hiding this comment

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

Ah, I see. I don't think there will be any concurrency issues though. I think you can just change the slice and call refreshServerConfig for each test case without any risk of concurrent reads. But if for some reason something is a problem with that, I don't think you even need a running tCore. That is, you could manually put together a dexConnection either with testDexConnection or manually with just what's needed to test this method.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just using the top numbers of a uint16 which are probably not going to ever be actual versions.

@chappjc
Copy link
Member

chappjc commented Apr 13, 2021

The other more fine grained versioning we'll need is for each asset.

Maybe something similar to this but a map of asset id to api versions in the config response?

Yeah, that would be appropriate. I think we could put a version in the dex/msgjson.Asset struct.

Add a version to the server that is communicated in the Config response.
Client checks and saves the version. The burden of conforming to an
API version is placed completely on the client.
@chappjc chappjc merged commit c5eeb28 into decred:master Apr 16, 2021
@chappjc
Copy link
Member

chappjc commented Apr 16, 2021

The other more fine grained versioning we'll need is for each asset.

Maybe something similar to this but a map of asset id to api versions in the config response?

Yeah, that would be appropriate. I think we could put a version in the dex/msgjson.Asset struct.

@buck54321 any objections to this?

In short these versions would be for things with an asset are changed that don't affect the dex API (e.g. kind of addresses, transaction structure, coin ID encoding, contract address, lock times, encoding of txdata payload, etc.)... things that concern a particular asset backend rather than the higher level core packages or comms.

Checking the asset version at order placement time for both base and quote seems right to me for that.

@buck54321
Copy link
Member

@buck54321 any objections to this?

In short these versions would be for things with an asset are changed that don't affect the dex API (e.g. kind of addresses, transaction structure, coin ID encoding, contract address, lock times, encoding of txdata payload, etc.)... things that concern a particular asset backend rather than the higher level core packages or comms.

Checking the asset version at order placement time for both base and quote seems right to me for that.

Sounds about right, though it's not readily apparent to me how an upgrade would work. Also not quite clear what to do at the UI level when we know that a server's asset version is incompatible with the client backend. I guess these details will get worked out in time. I think the important bit is to convey the info now so we're not trying to coordinate this in a patch release or something dumb like that.

@chappjc
Copy link
Member

chappjc commented Apr 16, 2021

Yeah, I think at a minimum it's a seatbelt that says "to trade with this asset at X you gotta update to version Y", to prevent making swaps or whatever that will be rejected (or worse with an old version that possibly had a security issue).

@chappjc
Copy link
Member

chappjc commented Apr 16, 2021

I'm doing the asset versioning @JoeGruffins... shoulda mentioned.

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.

multi: Enable client/server API version checking.
3 participants