txflow
Spec reference Open the editor

How it works

Race a double spend between two continents

txflow turns a sentence into a transaction-flow experiment: a spec you can read and rerun, a graph of the transactions it builds, and a run on the Leios Musashi testnet that shows what each relay saw. This page follows one experiment through all four steps.

  1. Describea sentence
  2. Specwhat to build
  3. Graphwhat it builds
  4. Runwhat lands

The question

Two people spend the same coin at the same moment, one through a node in Frankfurt, the other through a node in Tokyo. Only one spend can make it into the ledger. Which one wins, how long until the network agrees, and what happens to transactions that were already built on top of the losing one?

On a network with Leios, transactions travel through endorser blocks as well as ranking blocks, so this race is worth measuring rather than guessing. It is cheap: eight transactions and 22 test ADA, all of it returned at the end except the fees.

1 Describe

In the editor you say what you want in plain words:

Race two chains of four from Frankfurt and Tokyo. The first transaction of each spends the same output and both go out at the same moment; the rest follow half a second apart.

The model answers with a spec, and the page checks it twice before showing anything: against the JSON Schema, and with the same Rust code that builds the transactions. When something is wrong, the errors go back to the model to fix. When the request is too vague, it asks a question instead of guessing.

2 The spec

This is the spec for the race. It never names a transaction id, a key or an amount that depends on the chain, so the same file can run again on the next node build or on another network.

version: 0
experiment: continent-race
seed: 1
params:
  length: 4
wallets:
  alice: {}
patterns:
  - id: race
    use: conflicting_chains
    with:
      length: "{{ length }}"
      conflict: root
schedule:
  releases:
    - { select: { label: side-a }, target: frankfurt, at: 0ms, spacing: 500ms }
    - { select: { label: side-b }, target: tokyo, at: 0ms, spacing: 500ms }
params
Named numbers you can change in one place. length: 4 gives each side four transactions.
conflicting_chains
A pattern: two chains, a1 → a4 and b1 → b4. With conflict: root only the first pair spends a shared output, so a1 and b1 are a double spend and everything after them depends on who wins.
schedule
Where and when each transaction goes. Side A goes to frankfurt, side B to tokyo, both starting at 0ms, each next transaction 500ms after the one before.

Every field and pattern is in the spec reference; its first chapter walks you through writing a spec by hand.

3 The graph

The checked spec expands into a graph: every output as a dot, every transaction as a box, with the relay it is sent to under it. Tap or hover anything for details.

  • Red: c1 is contested. a1 and b1 both spend it, so at most one of them lands.
  • Dashed: a2…a4 and b2…b4 can be orphaned. If their side's first transaction loses, they lose with it.
  • Filled dots are outputs something spends, hollow ones are left unspent. wa and wb fund each side's fees.

4 The run

Run on Musashi does the rest on the server, so you can close the page and come back:

  1. Build. It leases a funding lane of test ADA and builds and signs all eight transactions against it.
  2. Fund. One funding transaction creates wa, wb and c1 and waits until it is in a block.
  3. Send. At 0 ms a1 goes to Frankfurt and b1 to Tokyo, then the rest of each chain every 500 ms.
  4. Watch. It follows each relay's own log of what its node took into its mempool, dropped and put in a block, so you see each one move from waiting to in a mempool to landed, or end as rejected or never landed, relay by relay.
  5. Sweep. Whatever is left goes back to the lane, so the next run can use it.
One possible outcome, played on the graph: Frankfurt's spend wins. A real run finds out which side wins.

What to expect: each relay accepts the spend that reached it first and rejects the other as a double spend. Within seconds the relays agree on one side. That side's chain lands, and the other side, every transaction after its first included, never lands. Which side wins, how long the relays disagree and how far apart the two chains' blocks are is what the run measures, and it can change from one run and one node build to the next.

Open it in the editor → Then press Run on Musashi.

Change one thing

Each of these is one edit to the spec above. Open any of them, run it, and compare.

Where next

  • The editor: describe your own experiment, or start from one of the shapes on the start screen.
  • Your first experiment: write a spec by hand, step by step.
  • Patterns: chains, fan-outs, merges and double spends you can combine.
  • Schedule: every way to pick transactions and time their sends.