GX CoreOrder Book

Order Book

The GX Core order book is a high-performance, deterministic matching engine that processes orders using price-time priority. It is implemented in native Rust using BTreeMap data structures for sorted price levels and achieves sub-microsecond match latency.


Design

Price-Time Priority

The order book follows strict price-time priority (also called FIFO matching):

  1. Price priority — The best-priced order is always matched first. For bids, the highest price has priority. For asks, the lowest price has priority.
  2. Time priority — At the same price level, the order that arrived first is matched first.

This is the same matching model used by all major stock exchanges and centralized crypto exchanges (Binance, CME, NYSE).

Data Structure

Each market maintains two sides of the order book:

BTC-USD Order Book:

ASKS (sell orders, sorted ascending by price):
  $67,420: [Order A: 1.5 BTC, Order B: 0.8 BTC]
  $67,410: [Order C: 2.0 BTC]       <-- Best Ask

BIDS (buy orders, sorted descending by price):
  $67,400: [Order D: 3.0 BTC]       <-- Best Bid
  $67,390: [Order E: 1.0 BTC, Order F: 2.5 BTC]

Internally, each side is a BTreeMap<Price, VecDeque<Order>>:

  • BTreeMap provides O(log n) insertion and lookup by price level
  • VecDeque at each price level provides O(1) FIFO ordering
  • The spread is best_ask - best_bid ($67,410 - $67,400 = $10 in this example)

Semantic Ordering

GX Core uses semantic ordering within blocks to ensure fair and safe execution:

PriorityOperationRationale
1LiquidationsProtocol solvency — must execute before new risk is added
2CancellationsRemove stale orders before they can match
3Reduce-only ordersRisk reduction takes priority over new exposure
4New ordersStandard matching flow

Within each priority class, orders are processed in the sequence they were received by the validator (FIFO).


Order Types

TypeBehavior
Limit (GTC)Rests on the book at the specified price until filled or cancelled
MarketMatches immediately against the best available price; any unfilled remainder is cancelled
IOC (Immediate-or-Cancel)Matches as much as possible immediately; unfilled remainder is cancelled
FOK (Fill-or-Kill)Must fill entirely at the specified price or better, or is cancelled entirely
Post OnlyGuaranteed to add liquidity; if the order would cross the spread and take, it is rejected
Reduce OnlyCan only reduce an existing position; rejected if it would increase exposure

Integer Arithmetic

All price and size calculations use integer arithmetic to eliminate floating-point precision errors. This is critical for deterministic consensus — every validator must compute identical results.

FieldRepresentationExample
PriceFixed-point integer, 6 decimals$67,400.50 = 67400500000
SizeFixed-point integer, market-specific1.5 BTC = 1500000000 (9 decimals)
Notionalprice * size / precision_factorInteger multiplication and division
PnLComputed in integer space, rounded at settlementNo floating-point at any stage

This approach mirrors how traditional financial exchanges handle arithmetic. Floating-point is never used in the matching or settlement path.


Matching Algorithm

When a new order arrives, the matching engine executes the following:

fn match_order(incoming: Order, book: &mut OrderBook) -> Vec<Fill> {
    let mut fills = vec![];

    loop {
        // Get the best opposing price level
        let best = match incoming.side {
            Buy  => book.asks.first(),   // lowest ask
            Sell => book.bids.last(),     // highest bid
        };

        // Check if the incoming order can match
        if !can_match(incoming.price, best.price, incoming.side) {
            break; // No match possible
        }

        // Match against orders at this price level (FIFO)
        let resting = best.orders.front();
        let fill_size = min(incoming.remaining, resting.remaining);

        fills.push(Fill {
            price: resting.price,  // Resting order's price
            size: fill_size,
            maker: resting.address,
            taker: incoming.address,
        });

        // Update remaining sizes
        incoming.remaining -= fill_size;
        resting.remaining -= fill_size;

        if resting.remaining == 0 {
            best.orders.pop_front(); // Remove fully filled order
        }
        if incoming.remaining == 0 {
            break; // Incoming order fully filled
        }
    }

    // If incoming has remainder and is GTC, add to book
    if incoming.remaining > 0 && incoming.time_in_force == GTC {
        book.insert(incoming);
    }

    fills
}

Performance

OperationLatencyThroughput
Single matchSub-microsecondMillions of operations/sec
Resting order insertionSub-microsecondMillions of operations/sec
CancelSub-microsecondMillions of operations/sec
Match at 100 price levels7.9 us
Match at 1,000 price levels43.6 us
Match at 10,000 price levels662 us

Performance degrades gracefully with order book depth. Even at 10,000 price levels (an extremely deep book), match latency remains sub-millisecond.


Determinism

The order book is fully deterministic: given the same initial state and the same sequence of operations, every validator produces an identical final state. This is enforced by:

  1. Integer arithmetic — No floating-point rounding variance
  2. Deterministic sortingBTreeMap with a consistent comparator
  3. State hashing — After each block, a Merkle hash of the order book state is computed and included in the block header
  4. Consensus verification — Validators compare state hashes; divergent validators are flagged