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

feat(tpu-v2): provide swap protocol versioning #2324

Open
wants to merge 13 commits into
base: dev
Choose a base branch
from

Conversation

laruh
Copy link
Member

@laruh laruh commented Jan 17, 2025

ordermatch structs which got swap_version field:

  • TakerOrderBuilder
  • MakerOrderBuilder
  • MakerOrder
  • MakerReserved
  • TakerRequest

swap structs. if swap started swap_version will be saved in db:

  • MySwapForRpc
  • TakerSwapStateMachine
  • MakerSwapStateMachine
  • TakerSwapDbRepr
  • MakerSwapDbRepr

swap version 2 is tpu v2 protocol
legacy swap protocol is 1 version

When Taker or Maker build order, the value const SWAP_VERSION: u32 = 2; is used for order Builder.
However in create_maker_order/lp_auto_buy if user didnt use ctx.use_trading_proto_v2() in config we set legacy protocol version to the order.

@laruh laruh changed the title feat(tpu-v2) provide swap protocol versioning field feat(tpu-v2): provide swap protocol versioning Jan 17, 2025
Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

Is this blocking anything currently? These changes look like a hacky workaround rather than a being proper solution. It would be great if we can avoid this change.

Comment on lines 1254 to 1256
fn legacy_swap_version() -> u32 { 1 }

fn is_legacy_swap_version(swap_version: &u32) -> bool { *swap_version == 1 }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
fn legacy_swap_version() -> u32 { 1 }
fn is_legacy_swap_version(swap_version: &u32) -> bool { *swap_version == 1 }
const fn legacy_swap_version() -> u32 { 1 }
fn is_legacy_swap_version(swap_version: &u32) -> bool { *swap_version == legacy_swap_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.

Provided const fn 998e75a

@laruh
Copy link
Member Author

laruh commented Jan 20, 2025

Is this blocking anything currently? These changes look like a hacky workaround rather than a being proper solution. It would be great if we can avoid this change.

We need swap versioning to do a legacy fallback on order matching

/// In the future alls users will be using TPU V2 by default without "use_trading_proto_v2" configuration.
pub fn use_trading_proto_v2(mut self, use_trading_proto_v2: bool) -> Self {
if !use_trading_proto_v2 {
self.swap_version = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we reserve only single value for legacy swaps?
I think legacy swaps may exist for sometime and we should allow version grow for them too.
I suggest use a structured encoding, for e.g.:
for legacy swaps: 1.x.y
for TPU: 2.x.y
(we could encode it into u32 as 1 * 10000 + x * 100 + y)

Copy link
Member Author

Choose a reason for hiding this comment

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

Explain how this is supposed to work and to be supported for kickstart process for example.

I really doubt we will use minor and patch versions in the current repo.
We can start legacy from 0 and reserve 1 version for legacy kmd burn implementation.
I think it will be the first and the last feature in legacy which will require explicit version separation.
zero fee shouldn't make many changes in utxo and evm code?

anyway everything which changes backward compatibility should update swap version "major" integer.

will legacy and legacy burn fee/zero fee be incompatible or not? That is only matters. Even if we dont reserve numbers before 2 for legacy, we could use next numbers after 2 for newer legacy versions. its just numbers.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you plz add some info how swap_version is used, to the PR description?
Was it meant to have just 1 and 2 values?

I am referring to the discussion in the team chat where it was discussed to get swap parties versions from the order matching. Maybe this PR should be reconsidered after we work out that concept.

Copy link
Member Author

@laruh laruh Jan 21, 2025

Choose a reason for hiding this comment

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

I updated PR description

I am referring to the discussion in the team chat where it was discussed to get swap parties versions from the order matching.

This PR provides swap version from order matching

Maybe this PR should be reconsidered after we work out that concept.

This PR exists due to the reason that we still dont have any conclusion related to versioning. It is blocking TPU, to launch TPU in production, we need support for a legacy fallback.

I would tell we can change versioning later in other PRs, when we see by practice what versioning approach is preferable

Copy link
Collaborator

Choose a reason for hiding this comment

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

thanks

/// In the future alls users will be using TPU V2 by default without "use_trading_proto_v2" configuration.
pub fn use_trading_proto_v2(mut self, use_trading_proto_v2: bool) -> Self {
if !use_trading_proto_v2 {
self.swap_version = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

we should use a const like LEGACY_SWAP_VERSION (indicating current version this code supports)

Copy link
Member Author

@laruh laruh Jan 21, 2025

Choose a reason for hiding this comment

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

Current version this code/repo supports is this const SWAP_VERSION.
If use_trading_proto_v2:false it means user didnt enable TPU

reused const fn 53d4b40
we need const function for #[serde(default = "legacy_swap_version")], so no need to create one more const variable.

UPD: I refactored this function a bit according to Onur notes, so please check newer commits

Comment on lines 1420 to 1425
pub fn use_trading_proto_v2(mut self, use_trading_proto_v2: bool) -> Self {
if !use_trading_proto_v2 {
self.swap_version = legacy_swap_version();
}
self
}
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 this?

Suggested change
pub fn use_trading_proto_v2(mut self, use_trading_proto_v2: bool) -> Self {
if !use_trading_proto_v2 {
self.swap_version = legacy_swap_version();
}
self
}
pub fn use_trading_proto_v2(mut self) -> Self {
self.swap_version = legacy_swap_version();
self
}

or, at least rename it to something like maybe_**

Copy link
Member Author

Choose a reason for hiding this comment

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

u suggested to change version to legacy protocol calling use_trading_proto_v2
please re read doc comment

    /// When a new [TakerOrderBuilder::new] is created, it sets [SWAP_VERSION] by default.
    /// However, if user has not specified in the config to use TPU V2,
    /// the TakerOrderBuilder's swap_version is changed to legacy.
    /// In the future alls users will be using TPU V2 by default without "use_trading_proto_v2" configuration.
    pub fn use_trading_proto_v2(mut self, use_trading_proto_v2: bool) -> Self {

Copy link
Member

Choose a reason for hiding this comment

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

What I suggest is, either remove this boolean from the function and check it on the caller side or declare that in the function name with "maybe" prefix.

Copy link
Member Author

Choose a reason for hiding this comment

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

What I suggest is, either remove this boolean from the function and check it on the caller side

I dont get it, on the caller side it is where? Right now it looks like, you call use_trading_proto_v2 and set legacy

    pub fn use_trading_proto_v2(mut self) -> Self {
        self.swap_version = legacy_swap_version();
        self
    }

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 updated function name e37c74e

Copy link
Member

@onur-ozkan onur-ozkan Jan 21, 2025

Choose a reason for hiding this comment

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

I didn't pay attention to the logic, the usage was just unclear. Looking at the logic, it's even more unclear.. Function is called use_trading_proto_v2 but it downgrades version to legacy if given boolean is false.

Why not just this:

    pub fn use_trading_proto_legacy(mut self) -> Self {
        self.swap_version = legacy_swap_version();
        self
    }

and call it only when use_trading_proto_v2 is false?

Copy link
Member Author

Choose a reason for hiding this comment

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

the thing is that use_trading_proto_v2 initially is a config boolean flag, so use_trading_proto_legacy is supposed to be a question

ok I refactored function, now its purpose is only to set legacy protocol a62f56a

Comment on lines 1926 to 1930
pub fn use_trading_proto_v2(mut self, use_trading_proto_v2: bool) -> Self {
if !use_trading_proto_v2 {
self.swap_version = legacy_swap_version();
}
self
Copy link
Member

Choose a reason for hiding this comment

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

same as above

let alice_swap_v = maker_match.request.swap_version;

// Start legacy swap if taker uses legacy protocol (version 1) or if conditions for trading_proto_v2 aren't met.
if alice_swap_v == 1u32 || !ctx.use_trading_proto_v2() {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if alice_swap_v == 1u32 || !ctx.use_trading_proto_v2() {
if alice_swap_v == legacy_swap_version() || !ctx.use_trading_proto_v2() {

Copy link
Member Author

Choose a reason for hiding this comment

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

Done d4c5a16

let bob_swap_v = taker_match.reserved.swap_version;

// Start legacy swap if maker uses legacy protocol (version 1) or if conditions for trading_proto_v2 aren't met.
if bob_swap_v == 1u32 || !ctx.use_trading_proto_v2() {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if bob_swap_v == 1u32 || !ctx.use_trading_proto_v2() {
if bob_swap_v == legacy_swap_version() || !ctx.use_trading_proto_v2() {

Copy link
Member Author

Choose a reason for hiding this comment

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

Done d4c5a16

@@ -706,6 +706,8 @@ mod tests {

wasm_bindgen_test_configure!(run_in_browser);

const LEGACY_SWAP_V: u32 = 1;
Copy link
Member

Choose a reason for hiding this comment

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

legacy_swap_version can replace this need

Copy link
Member Author

Choose a reason for hiding this comment

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

Done d4c5a16

@laruh laruh added the priority: high Important tasks that need attention soon. label Jan 23, 2025
@laruh laruh mentioned this pull request Jan 26, 2025
27 tasks
mm2src/mm2_main/src/lp_ordermatch.rs Outdated Show resolved Hide resolved
Comment on lines 268 to 270
#[serde(default = "legacy_swap_version")]
#[serde(skip_serializing_if = "is_legacy_swap_version")]
pub swap_version: u32,
Copy link
Member

Choose a reason for hiding this comment

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

It's worth to create a separate type (or even a separate module for handling everyting related to versioning for swaps) for swap versioning, e.g., something like:

struct SwapVersion {
    #[serde(default = "legacy_swap_version")]
    #[serde(skip_serializing_if = "is_legacy_swap_version")]
    swap_version: u32,
}

which can help us to avoid this serialization rules applied all around the codebase.

I think this is a non-blocker improvement and I am okay to approve this PR without it. If you don't want to do it in this PR, can you leave a TODO note on one of them?

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 like this idea!
it will be safer to work with version field wrapped into structure with all annotations which we need, then adding manually version with annotations to p2p messages structures.
Im going to do it in the current pr to not refactoring everything in next PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's worth to create a separate type (or even a separate module for handling everyting related to versioning for swaps) for swap versioning, e.g., something like:

struct SwapVersion {
    #[serde(default = "legacy_swap_version")]
    #[serde(skip_serializing_if = "is_legacy_swap_version")]
    swap_version: u32,
}

which can help us to avoid this serialization rules applied all around the codebase.

I tested such wrapper, deserialisation and serialisation dont work as we would like if you dont provide serde annotation above the pub swap_version: SwapVersion, field.
https://github.com/laruh/benchmarks_and_tests/blob/merge-candidate/serde_example/src/tests.rs

So we still have to add annotations, but I think that looks better:
image

And everything is in separate module
image

I will push changes for review

Copy link
Member Author

Choose a reason for hiding this comment

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

Here 6687599

mm2src/mm2_main/src/ordermatch_tests.rs Outdated Show resolved Hide resolved
@shamardy shamardy requested a review from dimxy February 3, 2025 10:08
onur-ozkan
onur-ozkan previously approved these changes Feb 5, 2025
Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

Thanks!

LGTM other than 2 minor notes which are not blockers.

Comment on lines 18 to 19
impl SwapVersion {
pub(crate) fn is_legacy(&self) -> bool { self.version == legacy_swap_version() }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
impl SwapVersion {
pub(crate) fn is_legacy(&self) -> bool { self.version == legacy_swap_version() }
impl SwapVersion {
pub(crate) const fn is_legacy(&self) -> bool { self.version == legacy_swap_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.

Hmm why we can use const here if actual self.version value will be known at runtime?
I mean I can compile it, I thought it wont work. Is it bcz version has a primitive type?

Copy link
Member

Choose a reason for hiding this comment

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

version size is known at compile time.


#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct SwapVersion {
pub version: u32,
Copy link
Member

Choose a reason for hiding this comment

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

Not a blocker but u32 doesn't seem necessary for swap versioning, u8 should be more than enough.

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 wont be a problem to move to u32, so we can start with u8
bab63f1

@laruh
Copy link
Member Author

laruh commented Feb 5, 2025

@onur-ozkan I noticed if user update the app having old swap entries in db, there could be error when we try to get such data, as structs expect version field
Added this commit de60aae

Well, changes are about TPU (not in production yet), but I think if migration 13 adds swap_version column, then it should also handle setting old swaps to version 1.

@mariocynicys
Copy link
Collaborator

mariocynicys commented Feb 6, 2025

@laruh you should add this in a new migration 14. Existing DBs that ran migration 13 will not run it again.
p.s. migrations should never be changed after written in general.

@laruh
Copy link
Member Author

laruh commented Feb 6, 2025

@laruh you should add this in a new migration 14. Existing DBs that ran migration 13 will not run it again. p.s. migrations should never be changed after written in general.

The current pr adds 13 migration. Dev doesn have it

async fn statements_for_migration(ctx: &MmArc, current_migration: i64) -> Option<Vec<(&'static str, Vec<String>)>> {
match current_migration {
1 => Some(migration_1(ctx).await),
2 => Some(migration_2(ctx).await),
3 => Some(migration_3()),
4 => Some(migration_4()),
5 => Some(migration_5()),
6 => Some(migration_6()),
7 => Some(migration_7()),
8 => Some(migration_8()),
9 => Some(migration_9()),
10 => Some(migration_10(ctx).await),
11 => Some(migration_11()),
12 => Some(migration_12()),
_ => None,
}

@mariocynicys
Copy link
Collaborator

The current pr adds 13 migration. Dev doesn have it

ah my bad. only checked the commit diff u linked :)

Base automatically changed from fix-tpu-v2-wait-for-payment-spend to dev February 8, 2025 14:04
@shamardy shamardy dismissed onur-ozkan’s stale review February 8, 2025 14:04

The base branch was changed.

@laruh laruh force-pushed the fix-tpu-v2-wait-for-payment-spend-swap-version branch from de60aae to fe1bfc3 Compare February 8, 2025 14:56
@laruh
Copy link
Member Author

laruh commented Feb 8, 2025

Since the base branch was changed, I force-pushed an updated branch (cherry picked feature commits) with a clean git history to resolve conflicts

@laruh laruh requested a review from onur-ozkan February 8, 2025 15:23
@shamardy
Copy link
Collaborator

shamardy commented Feb 8, 2025

Since the base branch was changed, I force-pushed an updated branch (cherry picked feature commits) with a clean git history to resolve conflicts

ooh, I deleted the base branch after merging to dev, sorry about that. No need for another review from @onur-ozkan as I will give it a review before merging.

@laruh
Copy link
Member Author

laruh commented Feb 8, 2025

ooh, I deleted the base branch after merging to dev, sorry about that. No need for another review from @onur-ozkan as I will give it a review before merging.

Its ok, I have old original branches locally and can push them if someone needs it

@laruh laruh removed the request for review from onur-ozkan February 8, 2025 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.4.0-beta priority: high Important tasks that need attention soon. status: pending review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants