Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

fix(orders): a restored pending leaves the cancelled take's step start and range slice on a maker's row

Open
#756 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
rust
Domain
backend

Research direction

Start in rust/src/api/orders.rs at apply_restored_status, then read write_maker_step_end, clear_maker_step_start, and forget_range_slice in the same file, plus the two existing callers (resync_republished_maker_order, end_maker_waiting_step) to mirror their order of operations. Check is_maker_waiting_step and existing.order.is_mine guards in rust/src/api/invoice.rs. Done means the five test scenarios in the issue pass: step start reflects the second take (T3), range slice cleared, and non-pending/taker restores unchanged.

Written by the indexing model from the issue text.

Description

A restore that reports a maker's taken order as pending again moves the row to Pending, but leaves behind what the cancelled take recorded: the invoice step start and the range slice. The next take on that order then inherits both. Its pay or add-invoice countdown starts already expired, and a range order shows the old take's amount instead of the full range.

Found in the review of #630 (finding 4b). It predates that PR and is out of its scope.

Why

The other two paths that notice a maker's order is back on the book end the step through write_maker_step_end (rust/src/api/orders.rs):

  • the daemon's new-order, via resync_republished_maker_order;
  • the sweep's SyncPending, via end_maker_waiting_step.

write_maker_step_end clears the step start first (clear_maker_step_start), then writes Pending, then forgets the range slice (forget_range_slice). Its doc says why that order matters, and clear_maker_step_start's doc says that anything that learns the order is back must clear the start.

apply_restored_status is a third such path, and does neither. It records the cursor, writes the restored status with update_trade_fields, and updates the book and the UI.

The step start matters because a maker keeps one trade key for the whole life of the order: mostrod's taker-cancel path clears only the counterparty's pubkeys (edit_pubkeys_order). So the next take's pay-invoice or add-invoice reaches the maker on the same index with the same status. next_step_start (rust/src/api/invoice.rs) then reads it as the same step and keeps the older timestamp: the stored start is WaitingPayment at T2 on the same index, and T3 ≥ T2. This is the maker's half of #567: that function's doc names resync_republished_maker_order as the one that opens the maker's new step, by deleting the key, and the restore was left out.

Scenario

  1. A sell maker's range order (10–1000 ARS) is taken at T2 for 250 ARS. The maker gets pay-invoice at T2: the row is WaitingPayment with the 250 ARS slice, and the step start is WaitingPayment:T2:<index>.
  2. The taker cancels. mostrod republishes the order as pending (cancel_order_by_taker: update_order_to_initial_state, edit_pubkeys_order) and sends the maker new-order, which this client never applies (lost).
  3. The maker runs Account → Refresh. The restore's Orders reply lists the order as pending, and apply_restored_status writes Pending. The step start T2 and the 250 ARS slice stay on the row.
  4. A new taker takes the order at T3 and the maker gets pay-invoice at T3. Expected: the pay-invoice countdown starts at T3. Actual: it starts at T2 and may already be expired. Between steps 3 and 4, the maker's row also shows 250 ARS instead of the 10–1000 range.

The same happens after a fresh-device restore whose history replay rebuilt the row from pay-invoice at T2.

Only a taker's cancel triggers it. When the maker's own step times out (a sell maker at WaitingPayment, a buy maker at WaitingBuyerInvoice), mostrod cancels the order instead of republishing it (scheduler.rs), and there is no next take to inherit anything.

Direction

When the restored status is Pending and the row is a maker's (existing.order.is_mine) at a waiting step (is_maker_waiting_step, which does not look at the role), end the step through write_maker_step_end, as the other two paths do, instead of a bare update_trade_fields. Keep the book update and the emit. If write_maker_step_end returns false, return false without touching the book or emitting, as a failed update_trade_fields does today. Every other restored status keeps today's write.

Out of scope here, and declared as a residual risk in #630: apply_restored_status records the cursor (the restore's sent_at) before a row write that can fail.

Tests

  • A maker whose order was taken via pay-invoice at T2, restored as pending, then taken again via pay-invoice at T3: the step start is T3.
  • The same for add-invoice: a buy maker asked for its payout invoice, whose taker (the seller) cancels after paying the hold invoice. mostrod allows that at WaitingBuyerInvoice, returns the escrow and republishes the order.
  • A range order restored as pending: the row's slice is cleared and the range is back.
  • Regression: a restore that reports a non-pending status on a waiting row still writes it as today, and keeps the step start.
  • A taker's waiting row restored as pending keeps today's write.

Not reproduced on a node yet. The mechanism is from the code above and from the review of #630, which reproduced it in a throwaway test (gap_restored_pending_leaves_the_makers_step_start).

Related: #567, #628, #630.

Dominant language
Dart
Stars
11
Forks
9
Avg merge
1d 40m
Merged PRs (30d)
219

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from MostroP2P/app

All issues in MostroP2P/app

Similar issues

More Dart issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.