Skip to content

feat: bundle pending bids into a single multi-tx bid - #934

Open
MavenRain wants to merge 1 commit into
primev:mainfrom
MavenRain:feat/preconf-bundle-bids
Open

feat: bundle pending bids into a single multi-tx bid#934
MavenRain wants to merge 1 commit into
primev:mainfrom
MavenRain:feat/preconf-bundle-bids

Conversation

@MavenRain

Copy link
Copy Markdown

Closes #728.

This PR bundles eligible pending transactions from different senders into one multi-transaction bid on the first bid attempt in preconf-rpc. The bid protocol already supports this: raw_transactions is a repeated field and providers accept or reject a bid digest as a unit.

What changes

  • The queue loop groups fresh, unconstrained, regular transactions from different senders into bundles of at most 5. A bundle needs at least 2 members; a single eligible transaction bids solo as before.
  • Bundle dispatch is all-or-nothing: the loop reserves one worker slot per member before it starts any goroutine. A partial dispatch cannot occur, so a member can never be re-queued while a bundle bid that includes it is still outstanding.
  • One member (the leader) sends a single bid for the bundle. The bid amount is the sum of the per-member costs. Each stored commitment copy records its member's own share as BidAmount.
  • A member that fails simulation, balance, or fee checks before the bid is dropped from the bundle and falls back to the solo path. Its consumed block attempt is rolled back, so its solo retry is a true first attempt. If fewer than 2 members survive the pre-checks, no bundle bid is placed and every survivor falls back the same way.
  • If the bundle bid does not get commitments from all connected providers, every member falls back to the existing solo bid loop. Later bid attempts are always solo, so behavior after the first attempt is unchanged.
  • A member that collects enough commitments is fast-tracked: the leader persists its pre-confirmation immediately. A later context cancellation cannot revert a fast-tracked member to a failed state.
  • The commitments table primary key becomes (commitment_digest, transaction_hash) so one bid digest can map to more than one transaction. The migration is idempotent and safe to re-run.
  • Settlement and payment subscriptions split the comma-joined transaction_hashes field and emit one message per hash. The settlement tracker attributes amounts pro rata by the stored shares. Share lookups are scoped to the digest that covers the whole bundle, with the newest dispatch timestamp as the tie-break. All members of one notification burst use one split source, and the member shares sum exactly to the aggregate amount. If shares are not available, the tracker falls back to an equal split, never to the full amount per member.
  • New flag --bundle-bids (env PRECONF_RPC_BUNDLE_BIDS, default true) turns bundling off if set to false.

Design decisions open to change

  • Default on: bundling is enabled by default. If you prefer opt-in, the flag default flips to false in one line.
  • Bundle size: the cap is 5. Any other value works.
  • Pro-rata settlement split: if you prefer to keep settlement attribution whole, the tracker part of this change can be dropped without effect on the bidding path.

Tests

  • Bundle happy path: one Bid call, distinct per-member costs, amount equals the exact sum, each commitment carries its own member's share.
  • Fallbacks: bundle bid failure, pre-check drops, and single-eligible cases all reach the solo path; deposits and constrained transactions never bundle.
  • Cancellation: a cancelled context cannot produce a false pre-confirmation, cannot revert a fast-tracked member, and fails deposits visibly instead of stranding them; terminal status writes survive the cancellation that caused them.
  • Dispatch: an all-or-nothing regression test pins the slot pre-acquisition against the interleaved dispatch it replaced.
  • Settlement math: pro-rata and equal-split paths sum exactly to the aggregate, including the remainder assignment; the split source is stable across one notification burst; a closed subscription channel triggers a backed-off resubscribe instead of zero-hash writes.
  • Store: a composite-PK migration test (idempotence, two hashes under one digest, share lookup) runs under testcontainers in CI.

All tests pass with -race. gofmt, go build, and go vet are clean.

🤖 Generated with Claude Code

Bundle eligible pending transactions from different senders into one
multi-transaction bid on the first bid attempt. The wire protocol
already supports this: bidderapi.v1.Bid.raw_transactions is repeated
and providers accept or reject a bid digest as a unit.

- Eligibility: regular transactions with no constraint and no prior
  commitments; at least 2 eligible; at most 5 per bundle.
- All-or-nothing dispatch: worker slots for the whole bundle are
  reserved before any goroutine starts, so a partial dispatch cannot
  re-queue a member that a live bundle bid still covers.
- The leader sends one bid whose amount is the sum of the per-member
  costs. Each stored commitment copy carries its member share as
  BidAmount. Fast-tracked members are persisted by the leader and
  survive context cancellation.
- A member dropped by a pre-check falls back to the solo path with its
  block attempt rolled back, so the retry is a true first attempt. If
  the bundle gets no full acceptance, every member falls back to the
  existing solo loop unchanged.
- Storage: commitments primary key becomes
  (commitment_digest, transaction_hash) via an idempotent migration.
- Settlement: subscriptions split comma-joined transaction_hashes; the
  tracker attributes amounts pro rata by stored shares, scoped to the
  digest covering the whole bundle. One split source per notification
  burst; shares sum exactly to the aggregate; the fallback is an equal
  split, never the full amount per member.
- New flag --bundle-bids (env PRECONF_RPC_BUNDLE_BIDS, default true).

Closes primev#728

Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
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.

Preconf RPC improvements: Bundle bids

1 participant