Skip to content

Conversation

@mariocynicys
Copy link
Collaborator

@mariocynicys mariocynicys commented Oct 9, 2025

This PR adds support for broadcasting and persisting finished (either successfully or refundinly) swaps' status for v2 swaps.

Here there are no JSON files or so. We only store the status in the stats DB.
The stats DB has been exteded to account for new optional fields (market_margin & is_maker_bot) and also swap_version that is set to 0 for old persisted swaps.

SwapStatus p2p message was modefied in a backward compatible manner allow the new tpu-status to be sent as it couldn't fit to the existing SavedSwap structure (esp. regarding MakerSavedEvent/TakerSavedEvents).

The FIXMEs should be resolved via discussion here.

also add a couple of columns for new data in stats table. we will be using the same stats table as before with these extra optional columns.
also the events list is sent over but not stored as json like with legacy swaps. will decide later what do to with them (if they are supposed to be stored)
this also wraps the structs found in SwapStatusData inside a box because they are very different in size (i.e. for perf purposes)
we don't do so in aborted states though. we might wanna change that
this is prepared for tests rather than real usage, but could ofc be amended later.
for now it only exposes a couple of fields just to make sure the swap persisted in the db correctly
Comment on lines +106 to +107
// NULL = unknown, 0 = not a bot, 1 = bot
"ALTER TABLE stats_swaps ADD COLUMN is_maker_bot INTEGER;",

Choose a reason for hiding this comment

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

I wonder if making it maker_type with backing it Rust enum would be any good. 🤔 Just for the extensibility.

So it would look something like this:

enum MakerType {
  Unknown,
  WebUser,
  DesktopUser,
  Bot,
  .
  . 
  .
}

and can be extended to anything without changing things on the DB side.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wonder if making it maker_type with backing it Rust enum would be any good.

like the idea. we can have a new issue about that to harvest such data (cc/ @shamardy)

we can ofc do a migration to change the table to the appropriate format later.

Comment on lines +1028 to +1030
common::async_blocking(move || {
if let Some(conn) = ctx.sqlite_conn_opt() {
crate::database::stats_swaps::add_v2swap_to_index(&conn, &swap)

Choose a reason for hiding this comment

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

Why not making add_v2swap_to_index and spawning the task inside of it? If it's a heavy blocking task, then it should do this in a self-contained way as the caller may not always remember to wrap it with a spawning task.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

crate::database::stats_swaps::add_v2swap_to_index is only used by one method which is lp_swap::add_v2swap_to_stats_db_index (the latter is a simple wrapper around the former)

same for crate::database::stats_swaps::add_swap_to_index and lp_swap::add_swap_to_db_index

so having the async_blocking at either level is the doable. i went for adding the async_blocking to the top level as the db-level functions take &Connection which isn't gonna play nice with the requirements of async_blocking (we can ofc pass the whole MmArc to the db-level functions but i think them taking a &Connection is more intuitive).

also other db methods follow the same sync interface, so that aligns with them (except our &AsyncConnection-based code)

Choose a reason for hiding this comment

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

I think other db functions should do the same but I don't want to block this PR with other tech debts. It's fine if you don't want to do it that way.

Comment on lines +1041 to +1043
common::async_blocking(move || {
if let Some(conn) = ctx.sqlite_conn_opt() {
crate::database::stats_swaps::add_swap_to_index(&conn, &swap)

Choose a reason for hiding this comment

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

Same here.

self: Box<Self>,
state_machine: &mut Self::StateMachine,
) -> <Self::StateMachine as StateMachineTrait>::Result {
// FIXME: Do we want to broadcast the swap status here?

Choose a reason for hiding this comment

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

Why not?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this covers other cases like (e.g.) a maker who didn't see the funding transaction for some reason and aborted the swap, or a taker that failed to send the funding transaction and aborted the swap. idk if we want statistics about failures like these.

though a swap finished via a refund is accounted for and sent for stats.

Choose a reason for hiding this comment

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

I think this is something we would like to monitor.

Opinions ? @shamardy @smk762 @dimxy

Copy link
Collaborator

Choose a reason for hiding this comment

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

Swap stat is collected on seed nodes right?
As far as I can see we only store if the swap status is success or not, in the stat db.
So even if one party aborts the swap its status still will be updated by other party when it gets to the last state (and broadcasts the final state)

Copy link

Choose a reason for hiding this comment

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

Reasons for failure could be good intel for future works to mitigate.
Correct, seednodes do collect, in stats_swaps table column is_success.
https://dev.komodo-docs.pages.dev/en/docs/komodo-defi-framework/tutorials/query-the-mm2-database/#stats-swaps

onur-ozkan
onur-ozkan previously approved these changes Oct 21, 2025
Copy link

@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.

LGTM other than #2645 (comment), which is awaiting others responses.

Ok(())
}

async fn broadcast_my_v2swap_status(ctx: &MmArc, status: TPUSwapStatusForStats) -> Result<(), String> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

should this function not be called save_and_broadcast_my_v2swap_status?

Copy link
Collaborator

Choose a reason for hiding this comment

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

hmm save is done only for native, maybe no need to rename then

if let Some(conn) = ctx.sqlite_conn_opt() {
crate::database::stats_swaps::add_swap_to_index(&conn, swap)
}
pub async fn add_v2swap_to_stats_db_index(ctx: &MmArc, swap: TPUSwapStatusForStats) -> Result<(), String> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do we have _index in add_v2swap_to_stats_db_index and add_v2swap_to_index fn names?
I think this mattered for the legacy swaps as there is indeed an index over json files with stat data.

For TPU we have only a db, no jsons, so could we name them, like: save_swap_v2_stat and add_swap_v2_stat_to_db?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i was more or less following the names we have for legacy swaps. that being said, i think of index as tables/sqls.

db used to mean a sqldb to me, but it's used in a different way in our codebase. we treat json files as db (file/directory DB basically), see for example load_from_maker_stats_db.

that's why i find the _index distinction helpful in this case as to denote that such db storage is a table format rather than file dump. but i can remove it too if u find it way off.

@github-actions
Copy link

@shamardy
Please review it again.

@github-actions github-actions bot added the [] label Nov 30, 2025
@shamardy shamardy removed the [] label Dec 1, 2025
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

@shamardy
Please review it again.

@github-actions github-actions bot added the [] label Dec 3, 2025
@github-actions
Copy link

github-actions bot commented Dec 5, 2025

@shamardy
Please review it again.

@shamardy shamardy removed the [] label Dec 9, 2025
@github-actions
Copy link

@shamardy
Please review it again.

@github-actions github-actions bot added the [] label Dec 11, 2025
@github-actions
Copy link

@shamardy
Please review it again.

8 similar comments
@github-actions
Copy link

@shamardy
Please review it again.

@github-actions
Copy link

@shamardy
Please review it again.

@github-actions
Copy link

@shamardy
Please review it again.

@github-actions
Copy link

@shamardy
Please review it again.

@github-actions
Copy link

@shamardy
Please review it again.

@github-actions
Copy link

@shamardy
Please review it again.

@github-actions
Copy link

github-actions bot commented Jan 2, 2026

@shamardy
Please review it again.

@github-actions
Copy link

github-actions bot commented Jan 6, 2026

@shamardy
Please review it again.

@github-actions
Copy link

@shamardy
Please review it again.

1 similar comment
@github-actions
Copy link

@shamardy
Please review it again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants