From ff323d140e6ad0830bdd9e0b399841a2f69955ac Mon Sep 17 00:00:00 2001 From: AwokenLazarus <262377448+AwokenLazarus@users.noreply.github.com> Date: Thu, 22 Oct 2026 04:55:31 +0000 Subject: [PATCH 1/2] Lightning Stream whitepaper draft 10: a short paper and four pages The whitepaper had grown to some 24,000 words. It is now the idea alone: the problem, a ticket, the lottery, many sellers, HTTP and agents, the costs, a short prior art, the status, and the credits. The rest moved, mostly word for word, to four pages beside it: - design/: tickets in detail, slots, dust and fee rates, the lottery's two forms, how a session comes together, the costs stated plainly, prior art and the full reference list - tests/: every measurement, what it ran on and what it does not show, the film demo, and the evidence anyone can check - progress/: status and limits, built and not built, the packages, the earlier design and the changes by draft - uses/: what it is for, each use marked built, demo, designed or only conceived, with paying over HTTP, checked content and the agent wallet Anchors of the old single page still land: sections that moved keep their ids on the main page as links to their new place. Nothing in the design or the code changed. Co-Authored-By: Claude Opus 5.5 --- .../map-site/public/stream/design/index.html | 416 +++++++++++ cloudflare/map-site/public/stream/index.html | 681 +++--------------- .../public/stream/progress/index.html | 202 ++++++ .../map-site/public/stream/tests/index.html | 295 ++++++++ .../map-site/public/stream/uses/index.html | 271 +++++++ 5 files changed, 1281 insertions(+), 584 deletions(-) create mode 100644 cloudflare/map-site/public/stream/design/index.html create mode 100644 cloudflare/map-site/public/stream/progress/index.html create mode 100644 cloudflare/map-site/public/stream/tests/index.html create mode 100644 cloudflare/map-site/public/stream/uses/index.html diff --git a/cloudflare/map-site/public/stream/design/index.html b/cloudflare/map-site/public/stream/design/index.html new file mode 100644 index 0000000..00cef1c --- /dev/null +++ b/cloudflare/map-site/public/stream/design/index.html @@ -0,0 +1,416 @@ + + + + + +Lightning Stream: Design Details + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

Lightning Stream · DesignDesign details

+

For readers who want the depth: how a ticket behaves in each case, why the defaults are what they are, what it costs at real fee rates, the lottery's two forms, how a session comes together, prior art, and the full list of references.

+

This page accompanies Draft 10 of the Lightning Stream whitepaper, 22 October 2026. Back to the whitepaper.

+ + +
+ +
+
+

1Tickets in detail

+

The steps of a ticket, in full. The whitepaper has the short version and the figures.

+
+
Terms
The seller answers the first request with its price and terms: its Lightning node, the size of a ticket, how many tickets it will hold for one buyer, and how long a ticket lives.
+
Lock
The wallet makes one secret for each ticket and sends the seller only the hashes. For each hash the seller's node issues a hold invoice: an invoice that can be paid but not collected until its secret is shown. Hold invoices are not ours: Joost Jager added them to lnd in 2019 [5]. The wallet checks each invoice (who is paid, how much, that it is an XBT invoice, and that it expires no later than the owner allows) and pays it through the owner's Lightning node.
+
Pay
When the balance with the seller runs out, the wallet releases the next secret. The seller hashes it, confirms that the matching ticket is locked, collects it, and adds a ticket's worth to the session's balance. Requests are served from that balance: inside one ticket, pieces are counted in millisatoshis against a running total that the seller signs in its receipt. Where a secret travels has one answer: in a short request of its own within the session, a release, which asks for no resource. Every seller must accept a secret there, and the wallet sends one nowhere else. The draft wire also lets a seller take a secret inside a paid request; the gateway built here does, but a seller that took secrets only there could not be paid by this wallet. One path means one signed answer to each secret, and a request that is refused or lost has cost no secret.
+
Refill
The wallet keeps two tickets locked. When one is left it locks the next in the background, which took about a fifth of a second through one routing node. No request waits for a payment.
+
Stop
The wallet tells the seller it is done, and the seller cancels the unreleased tickets, which frees the buyer's money at once. If the seller does not, a Lightning Fork seller's node cancels each ticket 18 blocks before the ticket expires, or the ticket times out along the route. The 18 is a setting of the node's runner (lnd's invoices.holdexpirydelta, 12 on upstream lnd), which the gateway cannot read, so it takes the number from its config and refuses to start above 18.
+
+

Which nodes can sell. A ticket needs three calls on the seller's node: make a hold invoice, collect it, cancel it. lnd and its forks have all three as they ship, so they need no change; of them only Lightning Fork was run. A Core Lightning node cannot be a seller's node for held tickets today, for four reasons. It has no hold-invoice call of its own. Of the two published hold plugins, one issues invoices without XBT's feature bit, which a Lightning Fork buyer refuses, and the other keeps the secret on the seller's node, where a ticket's secret must be the buyer's. Nothing on it cancels a held ticket before the ticket expires: in our lab, a Core Lightning seller that neither collected nor cancelled ended with the buyer's node force-closing its own channel to it. And the gateway speaks to lnd-family nodes only, and will not start against any other. As a buyer's node or a routing node a Core Lightning node needed nothing.

+
+ + + + + + + + + + +
WhoWorst caseWhy it stops there
BuyerOne ticket, and its routing fee.A secret is spent when it leaves the wallet. A seller can take it and serve nothing. It cannot take the next one. At the forks' default policy a hop takes about 1 sat a ticket: 0.1% of a 1,000 sat ticket (measured), and 0.18% of a 546 sat one, 0.37% through two hops (computed).
BuyerMoney locked, not lost, for a ticket's life.Measured with 40-block tickets: 25 blocks when the seller neither collected nor cancelled, 51 blocks through one routing node when the seller vanished.
SellerNothing while its channel peer stays, if it serves only on a good secret for a locked ticket and collects at once.The payment is already committed to it. Measured: collecting still completed after a restart of each of the three nodes, and after the routing node had been down. But a collected ticket is the seller's for certain only once the hop before it has passed the secret back. If that hop goes away, the ticket has to be claimed on the chain, which costs more than a 1,000 sat ticket from a few sat/vB, and on a channel where the ticket has no output it cannot be claimed at all; see Fee rates. So a seller should not count a collected ticket as income until its node no longer lists it as pending. The gateway does not look, and counts it when the collect returns.
SellerTickets it served on but did not collect in time.Its own node, on Lightning Fork, cancels a held ticket 18 blocks before expiry. So a seller collects on use, never later.
SellerA force-closed channel, if its node is offline when locked tickets expire.Measured: the routing node closed its channel to the seller 43 blocks after the lock.
Routing nodeCapacity and payment slots held, with no fee for a ticket that is cancelled; on a channel it funded, the fee for each held ticket's output; and no co-operative close while a ticket is pending.This is the exposure every Lightning routing node already has to held payments. Tickets use it on purpose; see what it costs. A channel can be closed co-operatively only when nothing is pending on it, so every channel on a ticket's route can be closed only by force until the ticket is collected, cancelled or expired (from the protocol's rules; not run).
+
+ +

By default the buyer goes first: it releases a ticket before the requests it pays for, so the seller risks nothing and the buyer risks one ticket. For content that can be checked piece by piece the order turns round: the buyer checks the piece, then releases the ticket, and it is the seller who risks one piece (see Paying only for what checks out). The seller's terms say which order applies.

+

A seller the owner has not named. An owner cannot name every seller an agent may find, and a seller cannot know a buyer that has never paid it. So since 17 October 2026 a session with such a seller starts with one prepaid ticket: an ordinary payment that the seller collects as it arrives, which holds nothing on any channel. The wallet holds tickets with that seller only after its own node shows the prepaid one paid, and then one at a time, against two with a seller the owner named. A seller the owner has not named that offers no prepaid tickets is not held with at all, and is paid by the next way its terms offer, such as the lottery. The seller's side has the same rule from the other end: the gateway issues hold invoices only to a session that has paid it something, so a buyer it has never been paid by gets no held place. Before that rule, 2,000 lock requests from one client took every held place of a gateway in half a second, and cost that client nothing (measured on a regtest lab, our own nodes). Since then a lock for held tickets from a session that has paid nothing is refused, and the invoices of a first lock lapse after 20 s. The rule is built on both sides and in their tests. The gateway's lab script now sends the same 2,000 locks against it, and no report of a run of that check is in the tree yet.

+

The default settings are 1,000 sat tickets, 2 locked at a time with a seller the owner named and 1 with one it did not, a life of about 40 blocks, and no held ticket under 546 sat, or under a higher floor that follows from the fee rate where a channel without anchors may be on the route (Fee rates). The seller sets them and the owner's policy caps them. Earlier drafts locked 8 at a time. It is 2 now because a locked ticket takes up a place, a slot, on every channel it crosses, and some channels have only 30 slots for everybody who uses them; Slots and dust explains. A buyer that spends faster than two tickets can be refilled takes larger tickets, not more of them.

+

These steps are the design. They were first run in our lab by scripts driving three Lightning nodes. Since then both sides have been built and run on a regtest: the ticket book in the wallet and the seller's gateway. The wallet now pays a gateway from end to end on a regtest, through a routing node. The code now has the defaults described here; see Built and not built.

+

2What it gives and what it costs

+

The measurements in this section come from a three-node regtest lab with one hop: a buyer, one routing node and a seller, all on Lightning Fork, on channels of the anchor type, at regtest's fee rate of 1 sat/vB. The figures for Core Lightning come from a later run on six nodes. What changes at higher fee rates, and on channels without anchors, is under Fee rates. Numbers has the full tables and what was not measured.

+

What it gives

+
+
No request waits for a Lightning payment
Tickets are locked ahead, and a released ticket's balance pays for the requests after it. The seller's check of a secret took 0.93 ms (median) and collecting the ticket 3.5 ms (measured on a three-node regtest lab, one hop). It is not free of round trips: the wallet sends every call once without payment, reads the seller's 402, and sends it again with its payment, and a release is one more request. On loopback paying added 0.3 to 0.4 ms to a call; over a real network every call is one more round trip to the seller, and none of that was measured.
+
Pieces metered to the millisatoshi
Pieces are counted in millisatoshis, while money moves a ticket at a time: 1,000 sat by default, and never less than 546 sat for a ticket that is held. The part of the last ticket that was not used is trusted to the seller. For pieces worth less than a ticket there is a second way to pay: the lottery.
+
A bounded loss
The buyer can lose at most one ticket, and its routing fee. A ticket that was not released is never paid. A prepaid ticket, the first one with a seller the owner has not named, is spent when it is paid, used or not, and it too is one ticket.
+
Lightning's reach
A buyer can pay any seller a Lightning route reaches. The routing, the liquidity and the nodes are Lightning's own. Lightning Stream runs no network and no hub.
+
The owner's policy
The agent still pays under the owner's signed policy and still holds no key. In the lab the node permissions the wallet's Lightning payer already uses were enough to pay tickets. The seller's software needed only the permissions to read and write invoices, and its node refused it when it tried to send coins.
+
+

What it costs

+
+
Unused tickets are locked until cancelled or expired
A buyer that stops gets its unused tickets back at once only if the seller cancels them. Otherwise it waits: 25 blocks for 40-block tickets when the seller did nothing, 51 blocks through one routing node when the seller vanished (measured on a three-node regtest lab, one hop). At XBT's block spacing of about 7 minutes that is about 3 hours and about 6 hours.
+
The seller runs a Lightning node
A seller needs an lnd-family Lightning node with inbound capacity, online while tickets are locked. This is a real demand, and it is also the aim of the design: every seller is one more Lightning node on XBT, and more nodes is what the network needs. A buyer needs a Lightning node with a channel, which the wallet's Lightning payer already asks for.
+
Tickets are held payments
While a ticket is locked it occupies capacity, and one of a channel's payment slots, on every channel along the route. A channel has between 30 and 483 slots in each direction, depending on the node software at each end [4]: 483 between two Lightning Fork nodes, and 30 where either end is a Core Lightning node at its default. A routing node earns a fee only when a ticket is collected, and nothing when it is cancelled. XBT's Lightning network today is two implementations and about forty channels, and there this is tolerable. On a large network it is the behaviour that defences against channel jamming [10] are designed to stop: fees that are paid whether or not a payment completes [11], fees for the time a payment is held [12], and reputation carried with each payment [13]. So tickets must stay few, small and short-lived, and the defaults are modest for that reason. The rules that keep them so, such as the half rule below, are rules of this software: nothing makes another wallet, another seller or a routing node keep them, and a routing node that sees a peer's channel fill with held payments can raise its fees to that peer or close the channel. If hold fees arrive on Lightning, or fees paid whether or not a payment completes, tickets pay them, and a cancelled ticket then costs its buyer something. The written fallback for that day: held tickets are for a seller the buyer stays with, where such a fee is small beside what the session pays, and for a stranger prepaid tickets or the lottery become the only way to pay. Both are built, and the wire needs no change for it. Neither kind of fee exists on XBT's Lightning network today.
+
Slots are few, and shared
A channel's slots are shared by every buyer, every seller and every ordinary payment that crosses it. In our lab, of 40 tickets offered to a Core Lightning seller on one channel, 30 locked and 10 failed, and while the 30 were held an ordinary payment over that channel failed too. So the wallet holds little: 2 tickets with a seller the owner named, 1 with one it did not, and never more than half the slots of a channel it can see, which is 15 of 30. When a lock fails because a route is full, the wallet does not try harder. It drops to one ticket, waits, and then stops holding tickets with that seller and pays another way.
+
No small held tickets
A locked payment below a channel's dust limit (354 sat on a Lightning Fork node, 546 sat on a Core Lightning node) cannot be claimed on the chain, and if the channel is force-closed while it is locked, its value goes to the miners. So a held ticket is never under 546 sat. On a channel without anchors the limit rises with the fee rate, and the floor for held tickets rises with it: 2,304 sat through a routing node at mainnet's default (Fee rates). Smaller amounts are not held at all: they are paid at once, by a prepaid ticket or by the lottery. The cost is that a ticket cannot be made small to suit a small seller.
+
A routing fee per ticket
At the forks' default policy a routing node charges 1 sat, plus one part per million, for each ticket that is collected: 0.1% of a 1,000 sat ticket per hop. With 10 tickets locked and 5 collected, the buyer paid 5,005 sat and the seller received 5,000 (measured on a three-node regtest lab, one hop). What nodes on mainnet charge is not known to us.
+
The seller must collect on use and stay online
A ticket not collected 18 blocks before its expiry is cancelled by the seller's own Lightning Fork node, and a seller offline when locked tickets expire had its channel force-closed (measured on a three-node regtest lab, one hop).
+
Hold invoices, BOLT 11 only, lnd-family sellers only
Tickets need a seller's node that can hold a payment. Lightning Fork [61] has hold invoices for BOLT 11 invoices and not for BOLT 12 offers [4]. The other XBT Lightning implementation, the Core Lightning fork [63], works as a buyer's node and as a routing node with nothing added, and cannot be a seller's node for held tickets today. It has no hold invoice of its own: it holds a ticket only through a plugin [67], and neither of the two published hold plugins [68][69] works for tickets on XBT. In our lab a small plugin of our own, a test instrument and not a product, held and collected tickets on it. Nothing on a Core Lightning node cancels a held ticket before it expires. A prepaid ticket needs no hold invoice, so it is what a Core Lightning seller could offer as its node ships, but no seller's software for a Core Lightning node exists here, for prepaid tickets or held ones. The wallet and the gateway speak to Lightning Fork nodes only.
+
What others can see
No transaction on the chain ties a buyer to a seller, and the seller does not learn the buyer's node. But the nodes along the route see a run of equal payments to one seller and can see when each is released, and every node on a ticket's route sees the same hash.
+
+

Slots and dust: why the defaults are small

+

Think of a channel as a road with a small car park beside it. Every payment on its way parks in one space on each road it travels, and drives off when it is done. An ordinary payment is parked for a fraction of a second. A ticket is different: it stays parked until the buyer uses it or the seller cancels it. The spaces are the channel's slots. They are counted in payments, not in money, so a full car park turns away a payment of any size, however much money the channel holds. And the car park is shared by everyone whose payments use that road.

+

How many spaces there are depends on the node software at each end of the channel. The protocol allows up to 483 in each direction [4]. Lightning Fork uses 483. Core Lightning uses 30 unless its operator sets another number, and a channel with a Core Lightning node at either end carries 30 each way. The number is fixed when the channel opens. A buyer can read it for its own channels. For a channel further along the route it cannot: it finds out only when a payment fails there.

+

Our first measurements were made between Lightning Fork nodes only, and the defaults were sized for 483 slots: 8 tickets locked ahead with each seller. On a 30-slot channel, 8 tickets are more than a quarter of what everybody has, and three buyers with 8 each leave 6 slots for everyone else. Kyle Santiago, who read the design, pointed out both limits: this one, and the dust limit below. We then ran the XBT Core Lightning fork in the lab (see Numbers) and changed the defaults.

+
+
Two tickets, not eight
A session keeps 2 tickets locked and locks the next when 1 is left. A buyer that spends faster takes larger tickets, never more of them.
+
Never more than half
Held tickets take at most half the slots of a channel their holder can see, counting what is already pending there: the buyer on the channel its payments leave on, the seller on the channels it is paid over. That is 15 of 30. The other half stays free for ordinary payments and for everyone else. Where the number cannot be read, it is taken to be 30.
+
A full route means hold less
A lock that fails for lack of a slot cuts the session to one ticket and a wait. If one ticket will not lock either, the wallet stops holding tickets with that seller and pays another way: after a win in the lottery, or with a prepaid ticket that the seller collects as it arrives. Both are built.
+
A held ticket is never dust
Dust is the second limit. A locked payment smaller than a channel's dust limit is too small to get an output of its own in the channel's transaction: under 354 sat on a Lightning Fork node, under 546 sat on a Core Lightning node. Nobody can claim it on the chain, and it goes to the miners if the channel is force-closed while it is locked. In the lab, with tickets of 400, 600 and 1,000 sat held, a Core Lightning node's force close had outputs for the 600 and the 1,000 only. So a held ticket is at least 546 sat, the larger of the two limits, and the default stays 1,000. Anything smaller is paid at once and never held. That holds on channels of the anchor type, which both forks open by default. On a channel without anchors the limit rises with the fee rate, and so does the floor; see Fee rates.
+
Dust has a second cap
A node also limits the total of dust it will carry in one channel: 50,000 sat on Core Lightning. On a Core Lightning channel opened with 483 slots, 100 tickets of 500 sat locked and the next 30 were refused, and the buyer's node then found no route to that seller even for a 1,000 sat ticket. Tickets of 546 sat were all accepted.
+
+

These are the design's defaults as of this draft. The ticket book and the gateway in the public tree now have them. The tree's docs/LIMITS.md says what that means on a 30-slot channel.

+

Fee rates: what changes above 1 sat/vB

+

Every on-chain figure above was measured on regtest, at 1 sat/vB, on channels of the anchor type, and holds for that case only. Mainnet fee rates are often far higher, and many Lightning channels are of the older type without anchors. Two things change with the rate. On a channel without anchors, a pending payment has an output in the channel's transaction only if it is still above the dust limit after the fee of the transaction that would claim it, so the effective dust limit rises with the fee rate. And on any channel, every held ticket with an output adds 172 weight units to the transaction its funder pays for, and claiming a ticket on the chain costs its own fee. The table gives the default 1,000 sat ticket at three rates. It is computed from the transaction weights in BOLT 3, or scaled from the lab's 1 sat/vB figures where it says so. Nothing was run at 10 or 50 sat/vB, and no channel without anchors was run.

+
+ + + + + + + + + + + + + + + +
In sat, for 1,000 sat tickets1 sat/vB10 sat/vB50 sat/vB
Smallest payment with an output, anchors (Lightning Fork; Core Lightning)354; 546354; 546354; 546
Smallest payment with an output, no anchors, against a dust limit of 5467222,3049,334
Does a 1,000 sat ticket have an output? Anchors / no anchorsyes / yesyes / noyes / no
The channel funder's fee for one held ticket's output, for as long as it is held434302,150
Claiming one 1,000 sat ticket on the chain, anchors177 or more1,765 or more8,825 or more
The same, no anchors176, and 824 leftno output: lost to the minersno output: lost to the miners
A seller whose peer is gone after it collected 3 tickets (3,000 sat), anchors900 to 1,700 to close (measured)9,000 to 17,000 (scaled)45,000 to 85,000 (scaled)
The same, no anchors527 in claim fees, 2,473 keptnothing to claim: 3,000 of service unpaidthe same
A buyer whose own channel is force-closed with its 2 tickets held, no anchors834 back a ticketboth lost: 2,000both lost: 2,000
A routing node whose channel is force-closed with 15 tickets held on it, no anchorsabout 2,486 in claim feesall 15 lost: 15,000all 15 lost: 15,000
A force close with 100 tickets pending: the commitment transaction's fee4,635 (measured, anchors)46,350 (scaled)231,750 (scaled)
+
+

On an anchor channel an lnd-family node keeps the commitment transaction's own fee rate under a cap, 10 sat/vB by default as commonly documented (not checked in the fork's source), and whoever closes pays the rest, so the 50 sat/vB figures are in full a commitment fee only without anchors. What follows: a force close of a channel without anchors loses every ticket held on it that is below the threshold, not one; on any channel, an on-chain claim pays only in aggregate, where many tickets and the seller's whole balance share the cost of the close; and nobody on a route can see the type of a channel further along it, since it is not in gossip.

+

The floor for held tickets (built 17 October 2026). The default ticket stays 1,000 sat. Where a channel without anchors may be on the route, the wallet holds a ticket only if it is at least the larger of 546 sat and the dust limit plus the claim's fee at a fee-rate cap the owner sets. The cap is 10 sat/vB by default on mainnet and about 1 sat/vB on regtest and the test networks. On its own channels the wallet reads the type and the dust limit. Every channel past the first it takes to be without anchors, with a dust limit of 546 sat, because it cannot see them. So the floor through a routing node is 724 sat on regtest and 2,304 sat on mainnet at the defaults (computed), and a seller that is the wallet's direct peer has its channel's own floor. A ticket below the floor is not held: the wallet asks the seller for a larger size where its terms allow one, and otherwise pays the call by a prepaid ticket or the lottery. On mainnet, at the defaults, no ticket is held through a routing node, since the owner's largest ticket is 1,000 sat; those calls are paid with prepaid tickets or by the lottery. An owner who wants held tickets there raises the largest ticket to 2,304 sat or more, with a seller that offers that size. The gateway reads no dust limit and no channel type, and applies no floor of its own.

+

3The lottery in detail

+

The whitepaper has the idea and its figure; this is the rest. What the built form did in the lab is under Tests and numbers.

+

Why neither side can steer the roll

+

Each roll is made from two halves. The seller fixes its half of every roll before the session starts and shows only a fingerprint of them, so it cannot change one later. The buyer adds its half only after the piece has arrived, and for content it can check, only after the check passed. The two halves are hashed together and the result decides. When each side fixed its half it could not know the other's, and afterwards both can work out the result for themselves. Because the buyer's half comes after the piece, a seller cannot serve only the pieces that win. This argument treats the hash function, SHA-256, as a fair source of randomness. It is our own. Chris Guida's second review read it and the code that does it, and found no way for either side to steer a roll; that was one person's reading, not a proof and not an audit.

+ +

What it feels like

+

Uneven in the short run, exact in the long run. A miner knows the feeling: no block for a while, then one, and over a year the income matches the work. A seller's income from rolls evens out with the number of wins, and a seller chooses how often it wins by choosing the size of a win: wins in a day are the day's earnings divided by the win size. A buyer sees the same from the other side. One cheap download may cost a third more or a third less than its price, and over many downloads the average is the price. The costs, stated plainly has the figures.

+

How far "on average" reaches. The lottery is exact in expectation, and only in expectation. What one buyer pays one seller is a whole number of wins, and where n wins are expected the spread is about 1 over the square root of n. To be within 20% of the price nine times in ten takes about 68 wins between the same two parties, which is 4,350 sat at wins of 64 sat; to be within 5% takes about 1,080 wins, some 69,000 sat (computed). Below that it is luck. A call worth 10 sat, paid through a routing node where a win is 64 sat, expects a sixth of a win: about 85% of the time it pays nothing, and otherwise 64 sat or more. A session pools the calls of one buyer to one seller. Nothing pools across sellers or across buyers, and there is no bank, so more wins between the same two parties is the only thing that evens it out. For that reason, since 17 October 2026, the wallet keeps a call that expects fewer than 4 wins off the lottery where the seller also offers prepaid tickets, and pays it with a ticket: as shipped, that is every call that may use less than 256 sat through a routing node. Where the seller offers no prepaid tickets, such a call is paid by rolls as before. The owner can change the number of wins, or turn the rule off.

+ +

Two forms

+
+
The buyer pays after a win
Nothing is locked ahead. When a roll wins, the seller sends an ordinary Lightning invoice for the win, and the wallet, which has worked out the roll itself, pays it at once. This is simple, and it needs nothing but ordinary invoices. Its weakness is plain: a buyer can see a win and not pay. The seller serves on for a short while, then stops, and by then the cheat has had about one win's worth of service for free. Measured on a regtest lab, our own nodes, with pieces of a quarter of a sat and wins of 64 sat: a buyer that never paid was served 1.4 wins' worth on average before it was stopped (ten sessions, 3.3 wins' worth at the most in one; 0.8 to 1.4 on average over four runs). Where a seller would earn less than one win from a buyer in any case, a buyer that never pays gets everything for free. A buyer that sends no halves at all, or names every piece as lost (a void), is served the seller's window of 8 pieces in a session and no more: since 14 October 2026 a void counts against the window instead of making room in it, and the gateway ends a session after 4 voids. Before that, a buyer that voided every piece was served 24 pieces a session. Because the lottery is offered only for pieces of a quarter of a win or less, those 8 pieces are 2 wins' worth at the most, for each session a buyer is given; the gateway's caps on sessions, 64 in all and 4 from one address, bound how many. So this form is a cheap and exact way for honest buyers to pay tiny amounts, with a small, bounded loss to each cheat. It is not enforcement. Because nothing is held, neither a channel's slots nor its dust limit stands in the way: a win is in flight for about a quarter of a second, as any payment is. That makes this form the way to pay many sellers at once. The wallet paces the wins: at most 8 payments are on their way at a time, in the order the wins were found, except that a win a seller's answer is standing still for goes first.
+
A win that pays itself
The aim of this form, a win over Lightning that the loser cannot refuse to pay, was set out and first built by Paul Gerhart, Jay Taylor and Sri Aravinda Krishnan Thyagarajan in May 2026 [44]. What follows is our own way of reaching it, and it differs from theirs; see Prior art. The buyer first sets money aside in a locked box at the seller: an ordinary stream ticket, locked over Lightning, which only its key opens. Each roll then gives the seller a small chance of drawing the key, in a way that hides from the buyer whether it did. A seller that draws the key opens the box itself. The buyer cannot refuse to pay a win, because it learns of the win only when the money moves. After every roll, won or lost, the seller can check that the key really was there to be drawn. In our tests a buyer that offered rolls with no key in them was caught on half of those rolls, so a cheat gets about two pieces for free in place of a whole win's worth. The box is a held ticket, so it is at least 546 sat, and 1,000 by default. That makes this a form for a seller that earns several thousand sat from one buyer, not for a small one.
+
+

Where the two forms stand. The first form is built. It is in the wallet and in the seller's gateway in the public tree, and it runs on a regtest, on our own nodes. The gateway offers it beside tickets only where the dearest piece of a service is a quarter of a win or less, which is also the highest odds the wallet's owner allows by default, and the wallet chooses: tickets for a piece worth a ticket or more, for a seller it stays with and for a small call where prepaid tickets are offered, rolls for the rest and whenever it pays more sellers than tickets can be held with. A lottery session outlives a restart of the gateway: its rolls, its open pieces and its unpaid wins are kept in a journal on disk, written before a roll is revealed. The wallet's own side of a session does not outlive a restart of its signer; what it keeps on disk is every win's payment, written down before it is sent. The wallet works out every roll itself and pays only a win it found, so neither a seller nor an agent can talk it into paying a win that is not one. The argument that the roll is fair is still our own; one outside reviewer has read it and the code, and nobody has proved it. The second form is designed and was measured in a lab with a prototype. It is not built. It rests on an argument of our own, that a cheating buyer fails the seller's check on at least half of its rolls, which no cryptographer has reviewed; it will not be built until one has. On today's Lightning it also needs one proof for each locked payment, to show the seller that the box's lock and the rolls use the same key. We measured one such proof at a quarter of a second to make, and it needs a setup step that must not be trusted to one party.

+

What the second form is built from. None of its parts is ours. The roll uses oblivious transfer, in which a receiver takes one of two values and the sender does not learn which: the prototype uses the protocol of Chou and Orlandi [46], whose proof has since been questioned [47], extended to many transfers by the method of Ishai, Kilian, Nissim and Petrank [48]. That extension is safe only against a seller that follows the rules, so a real build needs a hardened one [49][50]. The transfers are combined by Gilboa's multiplication [51], the same step that threshold signing uses [52][53]. The proof that ties a lock to its rolls is a Groth16 proof [54] over the curve BLS12-381 [55] with the key on Jubjub [56], made with the arkworks libraries [57]; who may run its setup is the question studied in [58][59]. Only the way these are put together is ours, and that is the part nobody has reviewed.

+

4How it comes together

+

This is one session from the first request to the last, with a seller the buyer stays with and pieces smaller than a ticket, in the form where a win pays itself. That form is the design, and it is not built. In the form that is built, where the buyer pays after a win, two of the steps fall away: nothing is set aside and nothing is topped up, and a win is paid by an ordinary payment as soon as the wallet has found it.

+
+
Terms
A node runner puts a gateway in front of a service it already runs and sets a price for a piece. The gateway answers a first request with its terms: the price of a piece, the size of a win, and so the odds.
+
Limits
The wallet checks those terms against the owner's limits: the largest win, the highest odds, what any one seller may be paid, and the budget for the task. Terms outside the limits are refused before anything is paid.
+
Set aside
The wallet locks one payment with the seller over Lightning, of at least 546 sat as every held ticket is. Nothing has been spent. It is money set aside.
+
Roll
Each request carries the buyer's half of a roll. The roll rides on the request, so the service does not wait for it.
+
Win
When a roll wins, the seller collects the payment that was set aside. The wallet sees the money move on its own node, and books what its node paid, never a number the seller sends.
+
Top up
The wallet sets the next payment aside in the background, and the session goes on.
+
Stop
When the buyer stops, the seller cancels the payment that was set aside, and what was not won comes back, as an unused ticket does.
+
+

Which way of paying is used follows from the size of a piece and from how long the buyer stays with a seller. This is the rule the wallet has today.

+
+ + + + + + + + + + +
CaseHow it is paid
A piece worth a ticket or moreIt releases a ticket.
A call that expects fewer than 4 wins, from a seller that also offers prepaid ticketsA ticket: held, where the owner named the seller and one fits; a prepaid one first, where it did not.
A seller the buyer stays with: the call may spend four tickets' worth or more there, and a ticket can be heldTickets. With a seller the owner has not named, one prepaid ticket first, then held tickets one at a time.
Anything smaller, and any seller no ticket can be held with, as most sellers in a swarm areA roll, paid after a win, with nothing set aside, where the seller offers the lottery for that piece (a quarter of a win or less). The win is sized so that the session expects about sixteen wins, and it is never so small that the routing fee takes most of it: at least 64 sat through a routing node.
Rolls were chosen and no size of win fits the owner's limitsTickets, and a prepaid ticket where none can be held.
A single call from a buyer with no sessionOne ordinary Lightning payment.
+
+

If the win that pays itself is built one day, it would take the place of rolls with a seller the buyer stays with. Its win is a held ticket, so it would never be below 546 sat, and a seller that earns less than that from a buyer would still be paid after a win.

+

5Many sellers at once

+

Nothing in a ticket ties a buyer to one seller: each ticket is its own Lightning payment. But each held ticket takes a slot on every channel of its route, and the number that binds is the smallest over the whole route, shared by every buyer who uses it. From one channel of 30 slots, keeping to half of them, a buyer holds tickets with 7 sellers at two tickets each, or with 15 at one each. At 15 sellers with two each the channel is full and nothing else can pass through it. So on today's network held tickets are for one seller or a few.

+

Earlier drafts gave a much larger number of sellers that one channel could hold tickets with at once. That number is withdrawn. What the five-node lab behind it showed (a buyer, one routing node and three seller nodes, all Lightning Fork, every channel with 483 slots) is narrower: a Lightning Fork node accepts 483 pending payments on one channel, the most the protocol allows, and its router kept 400 tickets in flight at once, two each to 200 seller sessions spread over three nodes, locked in 11 seconds. It did not show a route that carries that many. A channel with a Core Lightning node at either end carries 30 at its default, as does eclair, and LDK carries 50, as commonly documented. The same lab showed that a seller that had just appeared could be paid a quarter of a second later through one routing node, and a tenth of a second later over a direct channel.

+

Many sellers at once are paid after a win in the lottery, which holds nothing. In the five-node lab, 200 seller sessions that all won in the same instant had all been paid 4.6 s later, with nothing held for any of them beforehand. On a 30-slot channel the wallet has to pace such payments: 200 payments of 64 sat all went through in 7.1 s when sent 8 at a time, and 139 of the 200 failed when sent 64 at a time.

+

Those were the design's measurements, made by scripts. The wallet and the gateway that are now built have done it too, on a regtest lab, our own nodes, through one routing node on channels of 30 slots. With 20 sellers paid at once, three small files from each: 3,840 rolls, 68 wins where 60 were expected, every file whole, no payment failed, 4.8 s. With 100 sellers: 19,200 rolls, 288 wins where 300 were expected, every file whole, no payment failed, 20 s, which is 14 wins a second. There were never more than 8 wins on the channel at once, and an ordinary payment of 5,000 sat that somebody else sent over the same channel meanwhile went through in half a second. One caution: the 100 sellers were 100 gateways beside one seller node. The channels carried what 100 sellers' wins would, and the seller's side was one node's worth of work. A second caution: those figures are from an idle machine. On a busy one the same check at first had a seller cut a file short, and the wallet's order of paying was changed for it; see A file cut short with 100 sellers.

+

Three limits remain, and each has an answer.

+
+
A ticket cannot be re-aimed
Once a Lightning payment is locked, its route and its receiver are sealed. Money cannot be locked first and pointed at a seller later, and a locked ticket cannot be moved to another seller. What can be done is to lock a new one, which is the quarter second above. The answer is not to wait for it: for content the buyer can check, the seller serves the first piece while the ticket locks, and paying after a win needs no lock at all. Serving a stranger one piece before it has paid is BitTorrent's "optimistic unchoke" [30], borrowed here.
+
Tickets are too coarse for small sellers
Through a routing node each collected payment costs about 1 sat, so paying one seller less than about 100 sat wastes more than 1%, below 1 sat nothing can be paid, and no ticket under 546 sat is held. In a swarm most sellers earn far less than that. The answer is the lottery.
+
Held tickets are a shared, limited resource
A channel carries between 30 and 483 held payments in each direction, for all sellers and every other user together, and the wallet takes at most half: 15 on a 30-slot channel. A seller that leaves without cancelling keeps its tickets locked for hours, and in a swarm sellers leave all the time. The answer is to hold little: two tickets with a seller the buyer stays with, one with a seller the owner has not named, one each when there are a few, one where a win pays itself, and none where the buyer pays after a win, which is how a swarm is paid.
+
+

An owner cannot list sellers it has never heard of. In place of a list of names it approves a kind of spending: a budget for the task, and a small cap on what any one unknown seller can be paid. The wallet has that part of the policy, for tickets and for wins. A seller the owner has not named is paid wins of 250 sat at the most, and no more than 32 wins in a task's window; with tickets, it is paid one prepaid ticket first and then held with one ticket at a time (A seller the owner has not named).

+

6The costs, stated plainly

+

The spreads below are simulations, except where a line says it was measured. "Nine days in ten" means the middle nine tenths of the days simulated.

+
+
Uneven income for a seller
A seller that earns about 4,000 sat a day in pieces of a tenth of a sat, with wins of 64 sat, is paid between 80% and 120% of what it earned nine days in ten, and between 96% and 104% over a month. A seller that earns 1,000 sat a day sees 58% to 141% on a day and 92% to 108% over a month. A seller that earns 100 sat a day gets no win at all one day in five. The rule behind these figures is the horizon above: about 68 wins for 20%, about 1,080 for 5% (How far "on average" reaches).
+
The seller chooses the trade
A smaller win means steadier income and a larger share lost to routing fees, because each win costs about 1 sat for each routing node it passes: 6.25% of a 16 sat win, 1.6% of 64, 0.4% of 250, 0.1% of 1,000. A node that runs several services gets steadier income for nothing, because all their wins land on one node: twenty services that each earn 1,000 sat a day bring that node within 9% of its earnings on a day.
+
Uneven cost for a buyer
A download priced at 1,638 sat (4 GiB at a tenth of a sat a piece, wins of 64 sat) cost between 1,152 and 2,176 sat nine times in ten. For it not to stall on an unlucky run more than once in a thousand, the owner must allow 2,795 sat, fees included. The budget is a ceiling. The average stays at the price. Measured on a regtest lab, our own nodes: a file priced at 381.5 sat, bought five times, cost 520, 780, 390, 260 and 325 sat with routing fees. The wallet stops asking for more pieces when the wins of one call run far above its price (for a call of 1,000 sat on wins of 64 sat, at 1,848 sat), and the budget the owner gave the task holds whatever the rolls do.
+
The seller goes first when the buyer pays after a win
By about one win's worth for each new buyer, and by everything where a seller earns less than one win from a buyer. Measured on a regtest lab, our own nodes: a buyer that never paid was served 1.4 wins' worth on average with pieces of a quarter of a sat, and 3.9 wins' worth with pieces of a quarter of a win, because the gateway bears two unpaid wins and serves 8 pieces ahead. A buyer that sends no halves at all, or voids every piece, gets the window of 8 pieces a session, which is 2 wins' worth at most, since no piece dearer than a quarter of a win is drawn for. Behind a reverse proxy the gateway's cap on sessions from one address counts only if the runner names the proxy and the header it reports a buyer's address in; otherwise every buyer has the proxy's address. Nothing on today's Lightning can force a buyer to pay a seller it touched only briefly.
+
What routing nodes carry
Tickets are held payments, and a win that pays itself needs one held for each seller. Each takes a slot on every channel of its route for as long as it is held. A routing node is paid nothing for one that is cancelled. If a seller vanishes with tickets locked, the routing node that opened the channel to it bears a forced close: with 100 tickets of 1,000 sat locked that cost about 29,000 sat in all at 1 sat/vB, which is 29% of the tickets' value, and with 3 tickets 1,530 sat (measured on regtest, anchor channels); scaled to 10 sat/vB the first is about 290,000 sat (Fee rates). A locked payment below a channel's dust limit, 354 sat on a Lightning Fork node and 546 sat on a Core Lightning node, cannot be claimed on the chain at all, which is why no ticket under 546 sat is held. Paying after a win holds nothing, and pays the routing node for every payment it carries.
+
A win that pays itself cannot be small
Its win is a held ticket, so it is at least 546 sat. Larger wins mean lumpier income: over a month, a seller that earns about 4,000 sat a day is paid between 85% and 115% of it with wins of 1,000 sat, against 96% to 104% with wins of 64 sat (simulated). A small seller is better paid after a win, where a win can be any size.
+
Pooling does not work here
Miners even out their income in pools, and Meni Rosenfeld's analysis of how pools pay [45] is where we took the comparison from. Pooling does not carry over, because a mining share is proof of work that anyone can check, and a piece served proves nothing to anyone who was not there: a seller and a friendly buyer could invent pieces and draw on the pool for free.
+
The deeper help is in Lightning itself
Changes to Lightning would do more than anything we can add on top of it. Point locks [14][15] first: with them the self-paying win would no longer need its proof. Then a fee for held payments [11][12], which would pay routing nodes for what tickets ask of them. Both are proposals made by others for Lightning as a whole. Neither exists on the XBT Lightning forks. They are other people's software. We can ask for them, and we cannot promise them.
+
+

7Prior art

+

Nothing in a ticket is a new mechanism. It is the hold invoice Lightning nodes already have [5], used to the end that "stuckless payments" were proposed for in 2019 [6], and bound to HTTP 402 and to an agent's spending policy. The numbers in square brackets point to References. The policy wallet is the part we think is most useful.

+
+
L402
Lightning Labs' HTTP 402 binding [23]: a macaroon plus a Lightning invoice. Used for metered services it becomes a prepaid balance at the seller. A seller that collects each ticket on arrival, before it is used, is running exactly that in ticket-sized units, and a seller whose node has no hold invoices can do so.
+
Keysend streaming
Podcast apps stream sats for each minute listened, usually as one spontaneous Lightning payment a minute [8][9]. That is a payment per piece: it suits a service where a wait of a tenth of a second or more per piece does not matter. AMP [7] is the other spontaneous payment Lightning has; in neither does the payer hold anything back, so neither is a ticket.
+
x402
The HTTP payment standard whose shape Lightning Stream uses [22]. Its batch-settlement scheme, where the client commits at request time and value settles later, is the name the earlier channel was carried under before it was removed. The ticket and lottery entries are our own, and the upstream clients do not speak them.
+
Nostr Wallet Connect
NIP-47 [25] gives each app its own connection to a wallet, which the owner can limit or revoke, and wallets that speak it put spending budgets on those connections. The policy wallet applies the same idea to agents, with an owner-signed policy.
+
Routstr and Cashu
Inference paid for request by request with Cashu ecash [27][28]. Payments are instant and private, but the mint holds the money. A locked ticket is held by nobody: it sits in Lightning channels until the buyer releases it or it returns.
+
Ark
One operator serving many recipients off chain [29], the shape the retired hub had. Users can exit on chain alone at any time before their coins expire, and must come back before then to refresh them. Lightning Stream now has no operator of its own.
+
+

Paying by lottery

+

Paying small amounts by lottery is an old idea, and none of it is ours. David Wheeler proposed "transactions using bets" in 1996 [33], and Ronald Rivest described "Electronic Lottery Tickets as Micropayments" in 1997 [34], with a bank that honours the winning tickets; Rivest's paper names still earlier forms of the idea. Silvio Micali and Rivest removed the back-and-forth in 2002 [35]. Rafael Pass and abhi shelat put an escrow on a chain in the bank's place in 2015 [36], in one form with no third party and in two with a third party whose conduct anyone can check. Orchid [39] and Livepeer [40] run such lotteries with a contract that holds the payer's deposit and pays a winner without the payer's help. Chiesa and others added privacy and defined a transfer that succeeds with a set probability [37], which Mitani and Otsuka built for payment hubs [38]. For Bitcoin itself the idea was raised by Mike Caldwell in 2012 [41], sketched inside Lightning channels by Tadge Dryja in 2016 [42], and built from specially made keys by Oleksandr Kurbatov in 2025 [43]. Lightning has neither a bank nor such a contract, and that is why the plain form here leaves the seller exposed by about one win. The plain form adds nothing to these but the binding to a request and to an owner's policy.

+

In May 2026 Paul Gerhart, Jay Taylor and Sri Aravinda Krishnan Thyagarajan published "Probabilistic Atomic Swaps for Bitcoin and Friends" (arXiv:2605.04975) [44], which builds an exchange that completes with a set probability and enforces itself, runs it between two test networks, and shows it over Lightning with a prototype of two nodes. The aim of a win that enforces itself off the chain is theirs first, and so is the proof that ties a hash lock to a key, which we measured after them. As we read their paper, each of their rolls is a small paid exchange of its own, where ours keeps one payment locked and lets the roll ride on a request the buyer sends anyway; theirs is built from adaptor signatures and an oblivious pseudorandom function, where ours uses oblivious transfer; and theirs comes with a formal treatment, where the check ours depends on is our own argument and has not been reviewed. Where the two differ, theirs is the one that has been set down properly.

+

Where tickets sit

+

Tickets sit between a prepaid balance and a payment per piece. A prepaid balance hands the seller the money before the service. A payment per piece hands it over piece by piece and makes each piece wait. A ticket commits the money before the service and hands it over a ticket at a time, inside the request.

+
+ + + + + + + + + + +
Prepaid balance (L402 with credit)Stream ticketsA Lightning payment per piece
Wait per requestNone once the balance is paid.None waits for a Lightning payment: a released ticket's balance pays the requests. The seller's check of a secret took 0.93 ms.110 ms on a direct channel, 210 ms through one routing node (median).
The buyer can loseThe whole balance.One ticket.One piece.
Money tied upThe balance, which is already the seller's.The unused tickets, until cancelled or expired.None.
Routing fee, one hop, default policyOne fee per top-up.1 sat per collected ticket: 0.1% at 1,000 sat.1 sat per piece: more than 1% for a piece under 100 sat.
Load on routing nodesAn ordinary payment.Held payments, a slot each, unpaid if cancelled.Many ordinary payments.
The seller's node needsAny Lightning node.Hold invoices: an lnd-family node today.Any Lightning node.
+
+

The timings and fees in this table were measured on a three-node regtest lab, one hop. A seller's 402 can list more than one of the three.

+

8References

+

Each of these was opened and read against what this paper says of it on 12 October 2026. Where we could only read an archived copy, or only part of a source, the entry says so.

+

Payment channels and Lightning

+
    +
  1. J. Spilman. "Anti DoS for tx replacement". bitcoin-development mailing list, 20 April 2013. archived copy.
  2. +
  3. P. Todd. "BIP 65: OP_CHECKLOCKTIMEVERIFY". 2014. Its section "Payment Channels" describes "Jeremy Spilman style payment channels". bip-0065.
  4. +
  5. J. Poon, T. Dryja. "The Bitcoin Lightning Network: Scalable Off-Chain Instant Payments". Draft 0.5.9.2, 14 January 2016. lightning.network.
  6. +
  7. Lightning Network developers. "BOLT: Basis of Lightning Technology". BOLT 2 (the peer protocol: the most pending payments a node may accept in a channel, 483, and the cap a node may put on dust), BOLT 3 (which pending payments get an output in a channel's transaction), BOLT 11 (invoices), BOLT 12 (offers; R. Russell, merged 2024). lightning/bolts.
  8. +
  9. J. Jager. "htlcswitch: hodl invoice". lnd pull request 2022, merged March 2019; released in lnd v0.6-beta, April 2019. The calls are AddHoldInvoice, SettleInvoice and CancelInvoice of lnd's invoices service. pull request, Optech: hold invoices.
  10. +
  11. H. Gondo. "Proposal for Stuckless Payment". lightning-dev mailing list, 25 June 2019. archived copy.
  12. +
  13. O. Osuntokun, with C. Fromknecht. "AMP: Atomic Multi-Path Payments over Lightning". lightning-dev mailing list, 6 February 2018. archived copy.
  14. +
  15. V. Wallace. "bLIP 3: Keysend". 2021. blip-0003.
  16. +
  17. Satoshis Stream. "bLIP 10: Podcasting 2.0 Streaming payments, Boosts and Boostagrams". 2022. blip-0010.
  18. +
  19. Bitcoin Optech. "Channel jamming attacks". Topic page. bitcoinops.org.
  20. +
  21. C. Shikhelman, S. Tikhomirov. "Unjamming Lightning: A Systematic Approach". Cryptology ePrint Archive 2022/1454, 2022. ePrint 2022/1454.
  22. +
  23. J. Jager. "Hold fee rates as DoS protection (channel spamming and jamming)". lightning-dev mailing list, 11 February 2021. archived copy.
  24. +
  25. C. Kirk-Cohen. "bLIP 4: Experimental Endorsement Signaling". 2024. blip-0004, Optech: HTLC endorsement.
  26. +
  27. Bitcoin Optech. "Point Time Locked Contracts (PTLCs)". Topic page. See also "Multi-Hop Locks from Scriptless Scripts", Blockstream Research. bitcoinops.org, multi-hop locks.
  28. +
  29. G. Malavolta, P. Moreno-Sanchez, C. Schneidewind, A. Kate, M. Maffei. "Anonymous Multi-Hop Locks for Blockchain Scalability and Interoperability". NDSS 2019. ePrint 2018/472.
  30. +
  31. A. Poelstra. "Scriptless Scripts". Slides, MIT Bitcoin Expo, 4 March 2017. slides.
  32. +
  33. L. Aumayr, O. Ersoy, A. Erwig, S. Faust, K. Hostakova, M. Maffei, P. Moreno-Sanchez, S. Riahi. "Generalized Channels from Limited Blockchain Scripts and Adaptor Signatures". Asiacrypt 2021. ePrint 2020/476.
  34. +
  35. Blockstream Research. libsecp256k1-zkp, module ecdsa_adaptor, which follows L. Fournier, "One-Time Verifiably Encrypted Signatures A.K.A. Adaptor Signatures". secp256k1-zkp. We read the module's header, which names Fournier's paper; we did not read the paper itself.
  36. +
  37. E. Heilman, L. AlShenibr, F. Baldimtsi, A. Scafuro, S. Goldberg. "TumbleBit: An Untrusted Bitcoin-Compatible Anonymous Payment Hub". NDSS 2017. ePrint 2016/575.
  38. +
  39. E. Tairi, P. Moreno-Sanchez, M. Maffei. "A2L: Anonymous Atomic Locks for Scalability in Payment Channel Hubs". IEEE Symposium on Security and Privacy 2021. ePrint 2019/589.
  40. +
+

HTTP, agents and other payment systems

+
    +
  1. R. Fielding and others. "Hypertext Transfer Protocol: HTTP/1.1". RFC 2068, January 1997, section 10.4.3: "402 Payment Required. This code is reserved for future use." It is still reserved in RFC 9110 (2022), section 15.5.3. RFC 2068, RFC 9110.
  2. +
  3. x402 Foundation. "x402", protocol version 2, with its schemes exact (and exact on Lightning, 2026), upto and batch-settlement. Created by Coinbase; since April 2026 kept by the x402 Foundation under the Linux Foundation. Apache-2.0. x402-foundation/x402, announcement.
  4. +
  5. Lightning Labs. "L402 Protocol Specification". lightninglabs/L402.
  6. +
  7. S. Warta, ligi, P. Gomes, A. Herzog. "CAIP-2: Blockchain ID Specification". 2019. With the bip122 namespace (Warta, ligi, Gomes), which follows M. Pontello, "BIP 122: URI scheme for Blockchain references / exploration". CAIP-2, bip122 namespace.
  8. +
  9. Nostr contributors. "NIP-47: Nostr Wallet Connect". 2023. NIP-47.
  10. +
  11. Anthropic. "Introducing the Model Context Protocol". 25 November 2024. Since December 2025 the protocol is kept by the Agentic AI Foundation, under the Linux Foundation. announcement, modelcontextprotocol.io.
  12. +
  13. Cashu contributors (calle and others). "Cashu NUTs", the Cashu protocol specifications; "NUT-24: HTTP 402 Payment Required". cashubtc/nuts, NUT-24.
  14. +
  15. Routstr. "routstr-core". Routstr/routstr-core.
  16. +
  17. Burak. "Ark: An Alternative Privacy-preserving Second Layer Solution". bitcoin-dev mailing list, 22 May 2023. For expiry and refresh as built: Second, "VTXO lifetime". archived copy, second.tech.
  18. +
  19. B. Cohen. "Incentives Build Robustness in BitTorrent". 22 May 2003. Section 3.3, "Optimistic Unchoking". bittorrent.org.
  20. +
  21. G. Maxwell. "Zero Knowledge Contingent Payment". Bitcoin Wiki, page created 28 November 2011. Bitcoin Wiki. The page names no author in its text; the author and date are from its history.
  22. +
  23. R. C. Merkle. "A Digital Signature Based on a Conventional Encryption Function". Crypto '87, Springer, 1988. doi:10.1007/3-540-48184-2_32.
  24. +
+

Paying by lottery

+
    +
  1. D. Wheeler. "Transactions Using Bets". Security Protocols, LNCS 1189, Springer, 1996. doi:10.1007/3-540-62494-5_7. We read its record and what Rivest and later authors say of it, not the paper itself.
  2. +
  3. R. L. Rivest. "Electronic Lottery Tickets as Micropayments". Financial Cryptography 1997. author's copy.
  4. +
  5. S. Micali, R. L. Rivest. "Micropayments Revisited". CT-RSA 2002. author's copy.
  6. +
  7. R. Pass, a. shelat. "Micropayments for Decentralized Currencies". ACM CCS 2015. ePrint 2016/332.
  8. +
  9. A. Chiesa, M. Green, J. Liu, P. Miao, I. Miers, P. Mishra. "Decentralized Anonymous Micropayments". Eurocrypt 2017. ePrint 2016/1033.
  10. +
  11. T. Mitani, A. Otsuka. "Anonymous probabilistic payment in payment hub". Cryptology ePrint Archive 2020/748, 2020 (a preprint). ePrint 2020/748.
  12. +
  13. J. S. Cannell, J. Sheek, J. Freeman, G. Hazel, J. Rodriguez-Mueller, E. Hou, B. J. Fox, S. Waterhouse. "Orchid: A Decentralized Network Routing Market". Version 2.0, 2019. whitepaper.
  14. +
  15. D. Petkanics, Y. Fu. "Livepeer Streamflow Paper". 2018. The contract is TicketBroker in the Livepeer protocol. Streamflow, contract.
  16. +
  17. M. Caldwell (casascius). "Sustainable nanopayment idea: Probabilistic Payments". Bitcoin Forum, 4 February 2012. bitcointalk.org.
  18. +
  19. T. Dryja. "LN as a Directed Graph: Single-Funded Channel Topology". Slides, 11 April 2016. slides.
  20. +
  21. O. Kurbatov. "Emulating OP_RAND in Bitcoin". arXiv:2501.16451, January 2025, and the Delving Bitcoin thread "Emulating OP_RAND". arXiv:2501.16451, thread, Optech: probabilistic payments.
  22. +
  23. P. Gerhart, J. Taylor, S. A. K. Thyagarajan. "Probabilistic Atomic Swaps for Bitcoin and Friends". arXiv:2605.04975, 6 May 2026. arXiv:2605.04975.
  24. +
  25. M. Rosenfeld. "Analysis of Bitcoin Pooled Mining Reward Systems". arXiv:1112.4980, 2011. arXiv:1112.4980.
  26. +
+

Building blocks of the sealed draw

+
    +
  1. T. Chou, C. Orlandi. "The Simplest Protocol for Oblivious Transfer". Latincrypt 2015. ePrint 2015/267.
  2. +
  3. Z. A. Genç, V. Iovino, A. Rial. "'The Simplest Protocol for Oblivious Transfer' Revisited". Information Processing Letters, 2020. It finds a flaw in the security proof of the protocol above. ePrint 2017/370.
  4. +
  5. Y. Ishai, J. Kilian, K. Nissim, E. Petrank. "Extending Oblivious Transfers Efficiently". Crypto 2003. doi:10.1007/978-3-540-45146-4_9.
  6. +
  7. M. Keller, E. Orsini, P. Scholl. "Actively Secure OT Extension with Optimal Overhead". Crypto 2015, revised 2022. The authors' 2022 note says the original proof does not hold and gives a repair that uses Roy's technique. ePrint 2015/546.
  8. +
  9. L. Roy. "SoftSpokenOT: Quieter OT Extension From Small-Field Silent VOLE in the Minicrypt Model". Crypto 2022. ePrint 2022/192.
  10. +
  11. N. Gilboa. "Two Party RSA Key Generation". Crypto '99. doi:10.1007/3-540-48405-1_8.
  12. +
  13. J. Doerner, Y. Kondi, E. Lee, a. shelat. "Secure Two-party Threshold ECDSA from ECDSA Assumptions". IEEE Symposium on Security and Privacy 2018. ePrint 2018/499.
  14. +
  15. J. Doerner, Y. Kondi, E. Lee, a. shelat. "Threshold ECDSA in Three Rounds". IEEE Symposium on Security and Privacy 2024. ePrint 2023/765.
  16. +
  17. J. Groth. "On the Size of Pairing-based Non-interactive Arguments". Eurocrypt 2016. ePrint 2016/260.
  18. +
  19. Electric Coin Company. "BLS12-381: New zk-SNARK Elliptic Curve Construction". 11 March 2017. blog post.
  20. +
  21. D.-E. Hopwood, S. Bowe, T. Hornby, N. Wilcox. "Zcash Protocol Specification". Section 5.4.9.3, "Jubjub". zips.z.cash. Read from an archived copy of 21 September 2026; the address given did not answer us.
  22. +
  23. arkworks contributors. ark-groth16, ark-bls12-381 and ark-ed-on-bls12-381, Rust libraries. MIT or Apache-2.0. arkworks-rs.
  24. +
  25. M. Campanelli, R. Gennaro, S. Goldfeder, L. Nizzardo. "Zero-Knowledge Contingent Payments Revisited: Attacks and Payments for Services". ACM CCS 2017. ePrint 2017/566.
  26. +
  27. G. Fuchsbauer. "Subversion-zero-knowledge SNARKs". PKC 2018. ePrint 2017/587.
  28. +
+

Software this work runs on

+
    +
  1. Bitcoin Knots, maintained by Luke Dashjr. Release 29.4.1 (September 2026) carries the BLAKE2b proof of work (L. Dashjr) and the unified opt-in signature hash (K. Santiago; specified in the tree's doc/unified-sighash.md), activated at block 961,640 together with the reduced-data rules of BIP 110 (D. Ohm). MIT. bitcoinknots/bitcoin, unified-sighash.md.
  2. +
  3. Lightning Fork, by Paul Lamb: lnd for the BLAKE2b chain. Measured here at tag v0.21.3-beta-blake2b.17 (commit cebc10fe), in the regtest lab of the same author, lightning-fork-lab, at commit a5cadc5. Lightning Fork is MIT; the lab carries no licence file. paulscode/lightning-fork, paulscode/lightning-fork-lab.
  4. +
  5. lnd, the Lightning Network Daemon, by Lightning Labs and the Lightning Network developers. MIT. lightningnetwork/lnd.
  6. +
  7. The Core Lightning fork for the BLAKE2b chain, by PrivKey, built on Core Lightning (R. Russell, Blockstream, and contributors). Measured here at release v26.06.9-blake2b.7 (commit 482c8c52), from the released binaries, as buyer, routing node and seller. Its documentation at that tag (doc/lightningd-config.5.md) gives the default of 30 pending payments in each direction of a channel. privkeyio/lightning, release, ElementsProject/lightning.
  8. +
  9. electrs, by Roman Zeyde. MIT. romanz/electrs.
  10. +
  11. libsecp256k1, by Pieter Wuille and the Bitcoin Core developers. MIT. bitcoin-core/secp256k1.
  12. +
  13. OCEAN. DATUM Gateway (Bitcoin Ocean, LLC, Jason Hughes and contributors; MIT), and J. Hughes, "TIDES: Transparent Index of Distinct Extended Shares", 2024. OCEAN-xyz/datum_gateway, TIDES.
  14. +
  15. Core Lightning documentation. "htlc_accepted", the plugin hook through which a plugin can fail an incoming payment, let it continue, or settle it with a secret. docs.corelightning.org.
  16. +
  17. Boltz. "hold", a hold invoice plugin for Core Lightning. MIT. Tried at v0.3.3. BoltzExchange/hold. We loaded it on the fork and asked it for one invoice, which lacked the XBT feature bit, so a Lightning Fork node refused to pay it; we tried nothing more.
  18. +
  19. daywalker90. "holdinvoice", a hold invoice plugin for Core Lightning. MIT. Read at v4.0.0. daywalker90/holdinvoice. Not run by us. By its README it settles an invoice by its hash, so the secret is the seller's; the repository is archived and points to the plugin above.
  20. +
+ +

Back to the whitepaper · Draft 10, 22 October 2026.

+
+
+ +
+ + + + diff --git a/cloudflare/map-site/public/stream/index.html b/cloudflare/map-site/public/stream/index.html index 07f2399..96c4a00 100644 --- a/cloudflare/map-site/public/stream/index.html +++ b/cloudflare/map-site/public/stream/index.html @@ -41,7 +41,7 @@ "url": "https://lazarus-xbt.xyz/stream/", "image": "https://lazarus-xbt.xyz/assets/og.png", "datePublished": "2026-10-07", - "dateModified": "2026-10-18", + "dateModified": "2026-10-22", "inLanguage": "en", "author": { "@type": "Organization", "name": "Lightning Stream", "url": "https://github.com/AwokenLazarus/Lightning-Stream" }, "publisher": { "@id": "https://lazarus-xbt.xyz/#org" }, @@ -66,13 +66,16 @@

Whitepaper · XBTLightning Stream: pay as it arrives

-

The people who run Lightning nodes should be able to connect any service they want to offer to the network (a file or media server, AI compute, storage, software of their own) and be paid for it piece by piece, by anyone. Sometimes that is one buyer and one seller, as with a streamed film. Sometimes it is many sellers at once, as in a torrent swarm, or people lending their hardware for AI.

+

The people who run Lightning nodes should be able to connect any service they want to offer to the network (a file or media server, AI compute, storage, software of their own) and be paid for it piece by piece, by anyone. Sometimes that is one buyer and one seller, as with a streamed film. Sometimes it is many sellers at once, as in a torrent swarm.

Lightning Stream is an upgrade to Lightning built for that: a way for people and AI agents to pay for a service while it is being delivered, an answer token by token, a file chunk by chunk, an API call by call. A few small payments are locked ahead of the service, each request releases one, and the ones not used come back. For pieces too small to be worth a payment of their own, a fair roll decides which pieces are paid: the price is exact on average, and evens out only over many wins.

-

Draft 9 · 18 October 2026, answering a second outside review, with packages for node boxes · Lightning Stream (source). The direction on this page is decided. Stream tickets are built on both sides, the ticket book in the wallet and the seller's gateway, and the wallet pays a gateway from end to end. The lottery for amounts smaller than a ticket is built too, in its first form, where the buyer pays after a win: the gateway offers it beside tickets and the wallet chooses between them. Its second form, a win that pays itself, is designed and not built, and waits for an outside review. New in this draft, most of it from Chris Guida's second review: the claim of "no change to the node" is narrowed to the nodes it holds for (How a ticket works); the costs are given at three fee rates, with a floor for held tickets that follows from them (Fee rates); a seller the owner has not named is paid a prepaid ticket first; the lottery's limits are tighter and its horizon is stated (The lottery); the software refuses mainnet unless it is asked for; the evidence can be checked from outside; and there are packages for Umbrel and StartOS (Packages). All of this runs on a test network (a regtest, our own nodes) and nowhere else. Nothing here runs on XBT mainnet. A small test on mainnet is planned and has not started; see Status.

-

What the name means. Lightning Stream is built on Lightning, not beside it. It adds the stream ticket to ordinary XBT Lightning channels, with a lottery for amounts smaller than a ticket, and uses Lightning's own routing, liquidity and nodes for everything else. It is not a separate channel system. An earlier draft of this paper described one, with its own channel on the chain and its own hub. Both have been removed from the code; what became of them is in The earlier design.

+

Draft 10 · 22 October 2026 · Lightning Stream (source). This draft is the short version: it explains the idea, and the detail lives on four pages of its own, listed below. Everything here is built and runs on a regtest, a private test network of our own nodes. Nothing of Lightning Stream has run on XBT mainnet yet; see Status.

+
@@ -84,11 +87,10 @@

Whitepaper · XBTLightning Stream: pay as it 1The problem

More and more of what we buy arrives over time: the tokens of a model's answer, the minutes of a stream, the pages of a dataset, the thousandth call to an API. Machines are now the buyers as often as people, and the prices are tiny: fractions of a cent, thousands of times an hour.

Most ways to pay for that ask someone to trust someone. Pay up front and you trust the seller to deliver. Pay afterwards and the seller trusts you. A subscription or an API key trusts a company with your card. An on-chain payment for each piece is honest but far too slow and too costly.

-

Lightning [3] already moves small payments between strangers in a moment, with nobody holding the money in the middle. What it lacks is a way to pay for something that arrives in thousands of pieces without making every piece wait for its payment. In our lab (Lightning Fork nodes on a regtest; see Numbers) one Lightning payment per piece took 110 ms on a direct channel and 210 ms through one routing node (median), and each payment through a routing node paid that node's base fee. Lightning Stream adds the missing part, and leaves the rest of Lightning as it is.

+

Lightning [3] already moves small payments between strangers in a moment, with nobody holding the money in the middle. What it lacks is a way to pay for something that arrives in thousands of pieces without making every piece wait for its payment. In our lab (Lightning Fork nodes on a regtest) one Lightning payment per piece took 110 ms on a direct channel and 210 ms through one routing node (median), and each payment through a routing node paid that node's base fee. Lightning Stream adds the missing part, and leaves the rest of Lightning as it is.

2The idea

Lock a few small Lightning payments before the service starts. Release one with each request. Take back the ones you did not use.

-
A session with tickets: keep two small payments locked, release one each time the balance runs out and lock the next, and get the unused ones back. @@ -128,12 +130,10 @@

2The idea

Figure 1. A stream ticket is a small Lightning payment that is locked along the route but not yet released. Here the service used five tickets' worth, and five were released. Only two are locked at any moment, and the two left at the end were never the seller's to take.
- -

That is the whole addition. It needs no change to an lnd-family node, that is lnd [62] and its forks, which have hold invoices: in our lab it ran through a routing node, on Lightning Fork [61], the fork of lnd that runs on XBT, as it ships today. Of that family only Lightning Fork was run. A Core Lightning node cannot be a seller's node for held tickets today; the next section says why. Everything else in this paper is what a ticket gives, what it costs, and how software that should never be trusted with a key can use it.

+

That is the whole addition. Lightning Stream is built on Lightning, not beside it: Lightning's own routing, liquidity and nodes carry everything else, and Lightning Stream runs no network and no hub of its own. It needs no change to an lnd-family node, that is lnd [62] and its forks, which have hold invoices; of that family only Lightning Fork [61], the fork of lnd that runs on XBT, has been run. A Core Lightning node can be a buyer's node or a routing node, but not a seller's node for held tickets today (which nodes can sell).

3How a ticket works

An ordinary Lightning payment is locked to a hash, and whoever shows the secret behind the hash collects it. Normally the seller picks that secret, so the money is the seller's the moment it arrives. A ticket turns that round: the buyer picks the secret.

-
The buyer keeps the secret; routing nodes and the seller see only its hash until the buyer releases the secret to the seller. @@ -157,98 +157,20 @@

3How a ticket works

Figure 2. The payment is committed along an ordinary Lightning route, and nobody can take it, because only the buyer knows the secret.
-
Terms
The seller answers the first request with its price and terms: its Lightning node, the size of a ticket, how many tickets it will hold for one buyer, and how long a ticket lives.
-
Lock
The wallet makes one secret for each ticket and sends the seller only the hashes. For each hash the seller's node issues a hold invoice: an invoice that can be paid but not collected until its secret is shown. Hold invoices are not ours: Joost Jager added them to lnd in 2019 [5]. The wallet checks each invoice (who is paid, how much, that it is an XBT invoice, and that it expires no later than the owner allows) and pays it through the owner's Lightning node.
-
Pay
When the balance with the seller runs out, the wallet releases the next secret. The seller hashes it, confirms that the matching ticket is locked, collects it, and adds a ticket's worth to the session's balance. Requests are served from that balance: inside one ticket, pieces are counted in millisatoshis against a running total that the seller signs in its receipt. Where a secret travels has one answer: in a short request of its own within the session, a release, which asks for no resource. Every seller must accept a secret there, and the wallet sends one nowhere else. The draft wire also lets a seller take a secret inside a paid request; the gateway built here does, but a seller that took secrets only there could not be paid by this wallet. One path means one signed answer to each secret, and a request that is refused or lost has cost no secret.
-
Refill
The wallet keeps two tickets locked. When one is left it locks the next in the background, which took about a fifth of a second through one routing node. No request waits for a payment.
-
Stop
The wallet tells the seller it is done, and the seller cancels the unreleased tickets, which frees the buyer's money at once. If the seller does not, a Lightning Fork seller's node cancels each ticket 18 blocks before the ticket expires, or the ticket times out along the route. The 18 is a setting of the node's runner (lnd's invoices.holdexpirydelta, 12 on upstream lnd), which the gateway cannot read, so it takes the number from its config and refuses to start above 18.
+
Lock
The wallet makes one secret for each ticket and sends the seller only the hashes. For each hash the seller's node issues a hold invoice, which can be paid but not collected until its secret is shown. Hold invoices are not ours: Joost Jager added them to lnd in 2019 [5]. The wallet checks each invoice and pays it through the owner's Lightning node.
+
Pay
When the balance with the seller runs out, the wallet releases the next secret, in a short request of its own. The seller confirms that the matching ticket is locked, collects it, and serves requests from a ticket's worth of balance, counted in millisatoshis and signed for in a receipt.
+
Refill
The wallet keeps two tickets locked, and locks the next in the background as one is used. No request waits for a payment.
+
Stop
The seller cancels the unused tickets, and the buyer's money is free at once. If the seller does not, the tickets expire and the money returns by itself.
+

A payment that the payer releases in a second step is not our idea: Hiroki Gondo proposed "stuckless payments" for Lightning in 2019 [6], with point locks, which Lightning does not have yet. Tickets get a similar effect from hold invoices, which Lightning nodes already have. It has a price: the secret no longer proves payment, because the buyer always knew it. The proof is the seller's signed receipt, together with the settled payment on the buyer's own node.

+

What each side risks. The buyer can lose at most one ticket and its routing fee: a seller can take a released secret and serve nothing, but it cannot take the next one. Unused tickets are locked, not lost, until they are cancelled or expire; with 40-block tickets that took 25 to 51 blocks in our lab, about 3 to 6 hours at XBT's block spacing. A seller that serves only on a good secret for a locked ticket, and collects at once, has its payment committed to it; it should count a ticket as income only once its node no longer lists it as pending. Routing nodes carry the held tickets meanwhile. The full table of worst cases is under Design details.

+

Why the defaults are small. A ticket is 1,000 sat by default; 2 are held at a time with a seller the owner named and 1 with one it did not, for about 40 blocks. A held ticket takes a payment slot on every channel it crosses, and a channel with a Core Lightning node at either end has only 30 slots in each direction for everybody who uses it, so the wallet never holds more than half of them. And a held payment below a channel's dust limit cannot be claimed on the chain, so no held ticket is under 546 sat, or under a higher floor where the fee rate requires one: 2,304 sat through a routing node at mainnet's defaults. So on mainnet, at the defaults, no ticket is held through a routing node; those calls are paid by a prepaid ticket or by the lottery. Kyle Santiago pointed out both limits, slots and dust, and the defaults changed because of it. A seller the owner has not named is first paid one prepaid ticket, an ordinary payment it collects as it arrives, before anything is held with it. Slots and dust and Fee rates have the reasons and the figures.

-

A payment that the payer releases in a second step is not our idea. In 2019 Hiroki Gondo proposed "stuckless payments" for Lightning [6]: the payer holds back a key the payee needs, and gives it up only once the payment is locked along the route. His proposal uses point locks, with a key from each side, and Lightning does not have those yet. Tickets get a similar effect from hold invoices, which Lightning nodes already have, by letting the buyer pick the secret behind the hash. It has a price: the secret no longer proves payment, because the buyer always knew it. The proof is the seller's signed receipt, together with the settled payment on the buyer's own node.

-

Which nodes can sell. A ticket needs three calls on the seller's node: make a hold invoice, collect it, cancel it. lnd and its forks have all three as they ship, so they need no change; of them only Lightning Fork was run. A Core Lightning node cannot be a seller's node for held tickets today, for four reasons. It has no hold-invoice call of its own. Of the two published hold plugins, one issues invoices without XBT's feature bit, which a Lightning Fork buyer refuses, and the other keeps the secret on the seller's node, where a ticket's secret must be the buyer's. Nothing on it cancels a held ticket before the ticket expires: in our lab, a Core Lightning seller that neither collected nor cancelled ended with the buyer's node force-closing its own channel to it. And the gateway speaks to lnd-family nodes only, and will not start against any other. As a buyer's node or a routing node a Core Lightning node needed nothing.

- -
- - - - - - - - - - -
WhoWorst caseWhy it stops there
BuyerOne ticket, and its routing fee.A secret is spent when it leaves the wallet. A seller can take it and serve nothing. It cannot take the next one. At the forks' default policy a hop takes about 1 sat a ticket: 0.1% of a 1,000 sat ticket (measured), and 0.18% of a 546 sat one, 0.37% through two hops (computed).
BuyerMoney locked, not lost, for a ticket's life.Measured with 40-block tickets: 25 blocks when the seller neither collected nor cancelled, 51 blocks through one routing node when the seller vanished.
SellerNothing while its channel peer stays, if it serves only on a good secret for a locked ticket and collects at once.The payment is already committed to it. Measured: collecting still completed after a restart of each of the three nodes, and after the routing node had been down. But a collected ticket is the seller's for certain only once the hop before it has passed the secret back. If that hop goes away, the ticket has to be claimed on the chain, which costs more than a 1,000 sat ticket from a few sat/vB, and on a channel where the ticket has no output it cannot be claimed at all; see Fee rates. So a seller should not count a collected ticket as income until its node no longer lists it as pending. The gateway does not look, and counts it when the collect returns.
SellerTickets it served on but did not collect in time.Its own node, on Lightning Fork, cancels a held ticket 18 blocks before expiry. So a seller collects on use, never later.
SellerA force-closed channel, if its node is offline when locked tickets expire.Measured: the routing node closed its channel to the seller 43 blocks after the lock.
Routing nodeCapacity and payment slots held, with no fee for a ticket that is cancelled; on a channel it funded, the fee for each held ticket's output; and no co-operative close while a ticket is pending.This is the exposure every Lightning routing node already has to held payments. Tickets use it on purpose; see what it costs. A channel can be closed co-operatively only when nothing is pending on it, so every channel on a ticket's route can be closed only by force until the ticket is collected, cancelled or expired (from the protocol's rules; not run).
-
- -

By default the buyer goes first: it releases a ticket before the requests it pays for, so the seller risks nothing and the buyer risks one ticket. For content that can be checked piece by piece the order turns round: the buyer checks the piece, then releases the ticket, and it is the seller who risks one piece (see Paying only for what checks out). The seller's terms say which order applies.

-

A seller the owner has not named. An owner cannot name every seller an agent may find, and a seller cannot know a buyer that has never paid it. So since 17 October 2026 a session with such a seller starts with one prepaid ticket: an ordinary payment that the seller collects as it arrives, which holds nothing on any channel. The wallet holds tickets with that seller only after its own node shows the prepaid one paid, and then one at a time, against two with a seller the owner named. A seller the owner has not named that offers no prepaid tickets is not held with at all, and is paid by the next way its terms offer, such as the lottery. The seller's side has the same rule from the other end: the gateway issues hold invoices only to a session that has paid it something, so a buyer it has never been paid by gets no held place. Before that rule, 2,000 lock requests from one client took every held place of a gateway in half a second, and cost that client nothing (measured on a regtest lab, our own nodes). Since then a lock for held tickets from a session that has paid nothing is refused, and the invoices of a first lock lapse after 20 s. The rule is built on both sides and in their tests. The gateway's lab script now sends the same 2,000 locks against it, and no report of a run of that check is in the tree yet.

-

The default settings are 1,000 sat tickets, 2 locked at a time with a seller the owner named and 1 with one it did not, a life of about 40 blocks, and no held ticket under 546 sat, or under a higher floor that follows from the fee rate where a channel without anchors may be on the route (Fee rates). The seller sets them and the owner's policy caps them. Earlier drafts locked 8 at a time. It is 2 now because a locked ticket takes up a place, a slot, on every channel it crosses, and some channels have only 30 slots for everybody who uses them; Slots and dust explains. A buyer that spends faster than two tickets can be refilled takes larger tickets, not more of them.

-

These steps are the design. They were first run in our lab by scripts driving three Lightning nodes. Since then both sides have been built and run on a regtest: the ticket book in the wallet and the seller's gateway. The wallet now pays a gateway from end to end on a regtest, through a routing node. The code now has the defaults described here; see Built and not built.

- -

4What it gives and what it costs

-

The measurements in this section come from a three-node regtest lab with one hop: a buyer, one routing node and a seller, all on Lightning Fork, on channels of the anchor type, at regtest's fee rate of 1 sat/vB. The figures for Core Lightning come from a later run on six nodes. What changes at higher fee rates, and on channels without anchors, is under Fee rates. Numbers has the full tables and what was not measured.

-

What it gives

-
-
No request waits for a Lightning payment
Tickets are locked ahead, and a released ticket's balance pays for the requests after it. The seller's check of a secret took 0.93 ms (median) and collecting the ticket 3.5 ms (measured on a three-node regtest lab, one hop). It is not free of round trips: the wallet sends every call once without payment, reads the seller's 402, and sends it again with its payment, and a release is one more request. On loopback paying added 0.3 to 0.4 ms to a call; over a real network every call is one more round trip to the seller, and none of that was measured.
-
Pieces metered to the millisatoshi
Pieces are counted in millisatoshis, while money moves a ticket at a time: 1,000 sat by default, and never less than 546 sat for a ticket that is held. The part of the last ticket that was not used is trusted to the seller. For pieces worth less than a ticket there is a second way to pay: the lottery.
-
A bounded loss
The buyer can lose at most one ticket, and its routing fee. A ticket that was not released is never paid. A prepaid ticket, the first one with a seller the owner has not named, is spent when it is paid, used or not, and it too is one ticket.
-
Lightning's reach
A buyer can pay any seller a Lightning route reaches. The routing, the liquidity and the nodes are Lightning's own. Lightning Stream runs no network and no hub.
-
The owner's policy
The agent still pays under the owner's signed policy and still holds no key. In the lab the node permissions the wallet's Lightning payer already uses were enough to pay tickets. The seller's software needed only the permissions to read and write invoices, and its node refused it when it tried to send coins.
-
-

What it costs

-
-
Unused tickets are locked until cancelled or expired
A buyer that stops gets its unused tickets back at once only if the seller cancels them. Otherwise it waits: 25 blocks for 40-block tickets when the seller did nothing, 51 blocks through one routing node when the seller vanished (measured on a three-node regtest lab, one hop). At XBT's block spacing of about 7 minutes that is about 3 hours and about 6 hours.
-
The seller runs a Lightning node
A seller needs an lnd-family Lightning node with inbound capacity, online while tickets are locked. This is a real demand, and it is also the aim of the design: every seller is one more Lightning node on XBT, and more nodes is what the network needs. A buyer needs a Lightning node with a channel, which the wallet's Lightning payer already asks for.
-
Tickets are held payments
While a ticket is locked it occupies capacity, and one of a channel's payment slots, on every channel along the route. A channel has between 30 and 483 slots in each direction, depending on the node software at each end [4]: 483 between two Lightning Fork nodes, and 30 where either end is a Core Lightning node at its default. A routing node earns a fee only when a ticket is collected, and nothing when it is cancelled. XBT's Lightning network today is two implementations and about forty channels, and there this is tolerable. On a large network it is the behaviour that defences against channel jamming [10] are designed to stop: fees that are paid whether or not a payment completes [11], fees for the time a payment is held [12], and reputation carried with each payment [13]. So tickets must stay few, small and short-lived, and the defaults are modest for that reason. The rules that keep them so, such as the half rule below, are rules of this software: nothing makes another wallet, another seller or a routing node keep them, and a routing node that sees a peer's channel fill with held payments can raise its fees to that peer or close the channel. If hold fees arrive on Lightning, or fees paid whether or not a payment completes, tickets pay them, and a cancelled ticket then costs its buyer something. The written fallback for that day: held tickets are for a seller the buyer stays with, where such a fee is small beside what the session pays, and for a stranger prepaid tickets or the lottery become the only way to pay. Both are built, and the wire needs no change for it. Neither kind of fee exists on XBT's Lightning network today.
-
Slots are few, and shared
A channel's slots are shared by every buyer, every seller and every ordinary payment that crosses it. In our lab, of 40 tickets offered to a Core Lightning seller on one channel, 30 locked and 10 failed, and while the 30 were held an ordinary payment over that channel failed too. So the wallet holds little: 2 tickets with a seller the owner named, 1 with one it did not, and never more than half the slots of a channel it can see, which is 15 of 30. When a lock fails because a route is full, the wallet does not try harder. It drops to one ticket, waits, and then stops holding tickets with that seller and pays another way.
-
No small held tickets
A locked payment below a channel's dust limit (354 sat on a Lightning Fork node, 546 sat on a Core Lightning node) cannot be claimed on the chain, and if the channel is force-closed while it is locked, its value goes to the miners. So a held ticket is never under 546 sat. On a channel without anchors the limit rises with the fee rate, and the floor for held tickets rises with it: 2,304 sat through a routing node at mainnet's default (Fee rates). Smaller amounts are not held at all: they are paid at once, by a prepaid ticket or by the lottery. The cost is that a ticket cannot be made small to suit a small seller.
-
A routing fee per ticket
At the forks' default policy a routing node charges 1 sat, plus one part per million, for each ticket that is collected: 0.1% of a 1,000 sat ticket per hop. With 10 tickets locked and 5 collected, the buyer paid 5,005 sat and the seller received 5,000 (measured on a three-node regtest lab, one hop). What nodes on mainnet charge is not known to us.
-
The seller must collect on use and stay online
A ticket not collected 18 blocks before its expiry is cancelled by the seller's own Lightning Fork node, and a seller offline when locked tickets expire had its channel force-closed (measured on a three-node regtest lab, one hop).
-
Hold invoices, BOLT 11 only, lnd-family sellers only
Tickets need a seller's node that can hold a payment. Lightning Fork [61] has hold invoices for BOLT 11 invoices and not for BOLT 12 offers [4]. The other XBT Lightning implementation, the Core Lightning fork [63], works as a buyer's node and as a routing node with nothing added, and cannot be a seller's node for held tickets today. It has no hold invoice of its own: it holds a ticket only through a plugin [67], and neither of the two published hold plugins [68][69] works for tickets on XBT. In our lab a small plugin of our own, a test instrument and not a product, held and collected tickets on it. Nothing on a Core Lightning node cancels a held ticket before it expires. A prepaid ticket needs no hold invoice, so it is what a Core Lightning seller could offer as its node ships, but no seller's software for a Core Lightning node exists here, for prepaid tickets or held ones. The wallet and the gateway speak to Lightning Fork nodes only.
-
What others can see
No transaction on the chain ties a buyer to a seller, and the seller does not learn the buyer's node. But the nodes along the route see a run of equal payments to one seller and can see when each is released, and every node on a ticket's route sees the same hash.
-
-

Slots and dust: why the defaults are small

-

Think of a channel as a road with a small car park beside it. Every payment on its way parks in one space on each road it travels, and drives off when it is done. An ordinary payment is parked for a fraction of a second. A ticket is different: it stays parked until the buyer uses it or the seller cancels it. The spaces are the channel's slots. They are counted in payments, not in money, so a full car park turns away a payment of any size, however much money the channel holds. And the car park is shared by everyone whose payments use that road.

-

How many spaces there are depends on the node software at each end of the channel. The protocol allows up to 483 in each direction [4]. Lightning Fork uses 483. Core Lightning uses 30 unless its operator sets another number, and a channel with a Core Lightning node at either end carries 30 each way. The number is fixed when the channel opens. A buyer can read it for its own channels. For a channel further along the route it cannot: it finds out only when a payment fails there.

-

Our first measurements were made between Lightning Fork nodes only, and the defaults were sized for 483 slots: 8 tickets locked ahead with each seller. On a 30-slot channel, 8 tickets are more than a quarter of what everybody has, and three buyers with 8 each leave 6 slots for everyone else. Kyle Santiago, who read the design, pointed out both limits: this one, and the dust limit below. We then ran the XBT Core Lightning fork in the lab (see Numbers) and changed the defaults.

-
-
Two tickets, not eight
A session keeps 2 tickets locked and locks the next when 1 is left. A buyer that spends faster takes larger tickets, never more of them.
-
Never more than half
Held tickets take at most half the slots of a channel their holder can see, counting what is already pending there: the buyer on the channel its payments leave on, the seller on the channels it is paid over. That is 15 of 30. The other half stays free for ordinary payments and for everyone else. Where the number cannot be read, it is taken to be 30.
-
A full route means hold less
A lock that fails for lack of a slot cuts the session to one ticket and a wait. If one ticket will not lock either, the wallet stops holding tickets with that seller and pays another way: after a win in the lottery, or with a prepaid ticket that the seller collects as it arrives. Both are built.
-
A held ticket is never dust
Dust is the second limit. A locked payment smaller than a channel's dust limit is too small to get an output of its own in the channel's transaction: under 354 sat on a Lightning Fork node, under 546 sat on a Core Lightning node. Nobody can claim it on the chain, and it goes to the miners if the channel is force-closed while it is locked. In the lab, with tickets of 400, 600 and 1,000 sat held, a Core Lightning node's force close had outputs for the 600 and the 1,000 only. So a held ticket is at least 546 sat, the larger of the two limits, and the default stays 1,000. Anything smaller is paid at once and never held. That holds on channels of the anchor type, which both forks open by default. On a channel without anchors the limit rises with the fee rate, and so does the floor; see Fee rates.
-
Dust has a second cap
A node also limits the total of dust it will carry in one channel: 50,000 sat on Core Lightning. On a Core Lightning channel opened with 483 slots, 100 tickets of 500 sat locked and the next 30 were refused, and the buyer's node then found no route to that seller even for a 1,000 sat ticket. Tickets of 546 sat were all accepted.
-
-

These are the design's defaults as of this draft. The ticket book and the gateway in the public tree now have them. The tree's docs/LIMITS.md says what that means on a 30-slot channel.

-

Fee rates: what changes above 1 sat/vB

-

Every on-chain figure above was measured on regtest, at 1 sat/vB, on channels of the anchor type, and holds for that case only. Mainnet fee rates are often far higher, and many Lightning channels are of the older type without anchors. Two things change with the rate. On a channel without anchors, a pending payment has an output in the channel's transaction only if it is still above the dust limit after the fee of the transaction that would claim it, so the effective dust limit rises with the fee rate. And on any channel, every held ticket with an output adds 172 weight units to the transaction its funder pays for, and claiming a ticket on the chain costs its own fee. The table gives the default 1,000 sat ticket at three rates. It is computed from the transaction weights in BOLT 3, or scaled from the lab's 1 sat/vB figures where it says so. Nothing was run at 10 or 50 sat/vB, and no channel without anchors was run.

-
- - - - - - - - - - - - - - - -
In sat, for 1,000 sat tickets1 sat/vB10 sat/vB50 sat/vB
Smallest payment with an output, anchors (Lightning Fork; Core Lightning)354; 546354; 546354; 546
Smallest payment with an output, no anchors, against a dust limit of 5467222,3049,334
Does a 1,000 sat ticket have an output? Anchors / no anchorsyes / yesyes / noyes / no
The channel funder's fee for one held ticket's output, for as long as it is held434302,150
Claiming one 1,000 sat ticket on the chain, anchors177 or more1,765 or more8,825 or more
The same, no anchors176, and 824 leftno output: lost to the minersno output: lost to the miners
A seller whose peer is gone after it collected 3 tickets (3,000 sat), anchors900 to 1,700 to close (measured)9,000 to 17,000 (scaled)45,000 to 85,000 (scaled)
The same, no anchors527 in claim fees, 2,473 keptnothing to claim: 3,000 of service unpaidthe same
A buyer whose own channel is force-closed with its 2 tickets held, no anchors834 back a ticketboth lost: 2,000both lost: 2,000
A routing node whose channel is force-closed with 15 tickets held on it, no anchorsabout 2,486 in claim feesall 15 lost: 15,000all 15 lost: 15,000
A force close with 100 tickets pending: the commitment transaction's fee4,635 (measured, anchors)46,350 (scaled)231,750 (scaled)
-
-

On an anchor channel an lnd-family node keeps the commitment transaction's own fee rate under a cap, 10 sat/vB by default as commonly documented (not checked in the fork's source), and whoever closes pays the rest, so the 50 sat/vB figures are in full a commitment fee only without anchors. What follows: a force close of a channel without anchors loses every ticket held on it that is below the threshold, not one; on any channel, an on-chain claim pays only in aggregate, where many tickets and the seller's whole balance share the cost of the close; and nobody on a route can see the type of a channel further along it, since it is not in gossip.

-

The floor for held tickets (built 17 October 2026). The default ticket stays 1,000 sat. Where a channel without anchors may be on the route, the wallet holds a ticket only if it is at least the larger of 546 sat and the dust limit plus the claim's fee at a fee-rate cap the owner sets. The cap is 10 sat/vB by default on mainnet and about 1 sat/vB on regtest and the test networks. On its own channels the wallet reads the type and the dust limit. Every channel past the first it takes to be without anchors, with a dust limit of 546 sat, because it cannot see them. So the floor through a routing node is 724 sat on regtest and 2,304 sat on mainnet at the defaults (computed), and a seller that is the wallet's direct peer has its channel's own floor. A ticket below the floor is not held: the wallet asks the seller for a larger size where its terms allow one, and otherwise pays the call by a prepaid ticket or the lottery. On mainnet, at the defaults, no ticket is held through a routing node, since the owner's largest ticket is 1,000 sat; those calls are paid with prepaid tickets or by the lottery. An owner who wants held tickets there raises the largest ticket to 2,304 sat or more, with a seller that offers that size. The gateway reads no dust limit and no channel type, and applies no floor of its own.

- -

5Smaller than a ticket: the lottery

-

Some things are worth less than the smallest payment worth sending. One piece of a shared file may be worth a tenth of a sat. Lightning carries nothing below 1 sat, and at the forks' default policy a routing node charges about 1 sat to carry any payment at all. A ticket does not help a seller who will earn less than one ticket from a buyer, and in a swarm of forty sellers that is most of them. Nor can a ticket be made small to fit: a held ticket is never under 546 sat (Slots and dust).

+

4Smaller than a ticket: the lottery

+

Some things are worth less than the smallest payment worth sending. One piece of a shared file may be worth a tenth of a sat. Lightning carries nothing below 1 sat, a routing node charges about 1 sat to carry any payment at its default policy, and a held ticket is never under 546 sat. In a swarm of forty sellers, most will earn less than one ticket from a buyer.

The answer is old and simple, and it is not ours: David Wheeler and Ronald Rivest described it in 1996 and 1997 [33][34]. Do not pay for every piece. Roll a fair die for every piece instead. Most rolls pay nothing. Now and then a roll wins, and a win pays an amount large enough to be worth sending. The odds are set so that the average is the price. With pieces at a tenth of a sat and a win of 64 sat, the odds are 1 in 640: over 640 pieces the buyer pays 64 sat on average, which is a tenth of a sat for each. Most pieces move no money at all.

-
Each piece is a roll made from a half the seller fixed beforehand and a half the buyer sends after the piece arrives; most rolls pay nothing and a win pays 64 sat. @@ -303,522 +225,113 @@

5Smaller than a ticket: the lottery

Figure 3. One roll for each piece. The seller's half was fixed before the session and the buyer's half comes after the piece, so neither can choose the result, and both can check it.
- -

Why neither side can steer the roll

-

Each roll is made from two halves. The seller fixes its half of every roll before the session starts and shows only a fingerprint of them, so it cannot change one later. The buyer adds its half only after the piece has arrived, and for content it can check, only after the check passed. The two halves are hashed together and the result decides. When each side fixed its half it could not know the other's, and afterwards both can work out the result for themselves. Because the buyer's half comes after the piece, a seller cannot serve only the pieces that win. This argument treats the hash function, SHA-256, as a fair source of randomness. It is our own. Chris Guida's second review read it and the code that does it, and found no way for either side to steer a roll; that was one person's reading, not a proof and not an audit.

- -

What it feels like

-

Uneven in the short run, exact in the long run. A miner knows the feeling: no block for a while, then one, and over a year the income matches the work. A seller's income from rolls evens out with the number of wins, and a seller chooses how often it wins by choosing the size of a win: wins in a day are the day's earnings divided by the win size. A buyer sees the same from the other side. One cheap download may cost a third more or a third less than its price, and over many downloads the average is the price. The costs, stated plainly has the figures.

-

How far "on average" reaches. The lottery is exact in expectation, and only in expectation. What one buyer pays one seller is a whole number of wins, and where n wins are expected the spread is about 1 over the square root of n. To be within 20% of the price nine times in ten takes about 68 wins between the same two parties, which is 4,350 sat at wins of 64 sat; to be within 5% takes about 1,080 wins, some 69,000 sat (computed). Below that it is luck. A call worth 10 sat, paid through a routing node where a win is 64 sat, expects a sixth of a win: about 85% of the time it pays nothing, and otherwise 64 sat or more. A session pools the calls of one buyer to one seller. Nothing pools across sellers or across buyers, and there is no bank, so more wins between the same two parties is the only thing that evens it out. For that reason, since 17 October 2026, the wallet keeps a call that expects fewer than 4 wins off the lottery where the seller also offers prepaid tickets, and pays it with a ticket: as shipped, that is every call that may use less than 256 sat through a routing node. Where the seller offers no prepaid tickets, such a call is paid by rolls as before. The owner can change the number of wins, or turn the rule off.

- -

Two forms

-
-
The buyer pays after a win
Nothing is locked ahead. When a roll wins, the seller sends an ordinary Lightning invoice for the win, and the wallet, which has worked out the roll itself, pays it at once. This is simple, and it needs nothing but ordinary invoices. Its weakness is plain: a buyer can see a win and not pay. The seller serves on for a short while, then stops, and by then the cheat has had about one win's worth of service for free. Measured on a regtest lab, our own nodes, with pieces of a quarter of a sat and wins of 64 sat: a buyer that never paid was served 1.4 wins' worth on average before it was stopped (ten sessions, 3.3 wins' worth at the most in one; 0.8 to 1.4 on average over four runs). Where a seller would earn less than one win from a buyer in any case, a buyer that never pays gets everything for free. A buyer that sends no halves at all, or names every piece as lost (a void), is served the seller's window of 8 pieces in a session and no more: since 14 October 2026 a void counts against the window instead of making room in it, and the gateway ends a session after 4 voids. Before that, a buyer that voided every piece was served 24 pieces a session. Because the lottery is offered only for pieces of a quarter of a win or less, those 8 pieces are 2 wins' worth at the most, for each session a buyer is given; the gateway's caps on sessions, 64 in all and 4 from one address, bound how many. So this form is a cheap and exact way for honest buyers to pay tiny amounts, with a small, bounded loss to each cheat. It is not enforcement. Because nothing is held, neither a channel's slots nor its dust limit stands in the way: a win is in flight for about a quarter of a second, as any payment is. That makes this form the way to pay many sellers at once. The wallet paces the wins: at most 8 payments are on their way at a time, in the order the wins were found, except that a win a seller's answer is standing still for goes first.
-
A win that pays itself
The aim of this form, a win over Lightning that the loser cannot refuse to pay, was set out and first built by Paul Gerhart, Jay Taylor and Sri Aravinda Krishnan Thyagarajan in May 2026 [44]. What follows is our own way of reaching it, and it differs from theirs; see Prior art. The buyer first sets money aside in a locked box at the seller: an ordinary stream ticket, locked over Lightning, which only its key opens. Each roll then gives the seller a small chance of drawing the key, in a way that hides from the buyer whether it did. A seller that draws the key opens the box itself. The buyer cannot refuse to pay a win, because it learns of the win only when the money moves. After every roll, won or lost, the seller can check that the key really was there to be drawn. In our tests a buyer that offered rolls with no key in them was caught on half of those rolls, so a cheat gets about two pieces for free in place of a whole win's worth. The box is a held ticket, so it is at least 546 sat, and 1,000 by default. That makes this a form for a seller that earns several thousand sat from one buyer, not for a small one.
-
-

Where the two forms stand. The first form is built. It is in the wallet and in the seller's gateway in the public tree, and it runs on a regtest, on our own nodes. The gateway offers it beside tickets only where the dearest piece of a service is a quarter of a win or less, which is also the highest odds the wallet's owner allows by default, and the wallet chooses: tickets for a piece worth a ticket or more, for a seller it stays with and for a small call where prepaid tickets are offered, rolls for the rest and whenever it pays more sellers than tickets can be held with. A lottery session outlives a restart of the gateway: its rolls, its open pieces and its unpaid wins are kept in a journal on disk, written before a roll is revealed. The wallet's own side of a session does not outlive a restart of its signer; what it keeps on disk is every win's payment, written down before it is sent. The wallet works out every roll itself and pays only a win it found, so neither a seller nor an agent can talk it into paying a win that is not one. The argument that the roll is fair is still our own; one outside reviewer has read it and the code, and nobody has proved it. The second form is designed and was measured in a lab with a prototype. It is not built. It rests on an argument of our own, that a cheating buyer fails the seller's check on at least half of its rolls, which no cryptographer has reviewed; it will not be built until one has. On today's Lightning it also needs one proof for each locked payment, to show the seller that the box's lock and the rolls use the same key. We measured one such proof at a quarter of a second to make, and it needs a setup step that must not be trusted to one party.

-

What the built form did in the lab

-

Every figure under this heading was measured on a regtest lab, our own nodes: three Lightning Fork nodes (a buyer, one routing node and a seller) on one machine, the buyer's channel and the seller's channel opened with 30 slots, and the wallet, the gateway and an ordinary file server as they are in the public tree. They are one run's figures. A roll is random, so the wins differ from run to run. Numbers has the table.

-
-
A 100 MB file, bought by rolls
The file was 1,526 pieces at a quarter of a sat each, 381.5 sat in all, and an agent bought it five times with the wallet's pay tool. It arrived whole each time, in 1.2 to 2.3 s. The five downloads won 8, 12, 6, 4 and 5 times, where 6 wins were expected, and cost 520, 780, 390, 260 and 325 sat with routing fees. What the buyer's node paid was what the wallet had booked, to the millisatoshi: 35 wins of 64 sat, each paid once (on a regtest lab, our own nodes).
-
Nothing held between wins
The buyer's channel was looked at every 20 ms during those downloads. Nothing was pending in 47% of the looks. There were never more than 3 payments pending, and every one of them was a win on its way. When the downloads were over nothing was pending, and nothing was held on the seller's node (on a regtest lab, our own nodes).
-
Many sellers at once
20 sellers, and then 100, were paid at once from one 30-slot channel with no failed payment (on a regtest lab, our own nodes). Many sellers at once has the figures.
-
A buyer that does not pay
A buyer that sent no halves of its own was served 8 pieces, then cut off. A buyer that rolled and never paid a win got 1.4 wins' worth before it was stopped, as above; with dearer pieces, a quarter of a win each, it got 3.9 wins' worth (on a regtest lab, our own nodes).
-
A seller that lies
A seller that claimed a win for a roll that had lost, that sent an invoice paying another node or asking for one sat more, or that sent two invoices for every win, was paid nothing for it. The wallet's own working of the roll, and the checks it makes of every invoice, refused them (on a regtest lab, our own nodes).
-
A crash
The wallet, the gateway, the buyer's node and the seller's node were each killed between two calls, and again in the middle of a download while wins were being paid. In all eight cases no win was paid twice, the wallet's books matched what its node had paid, and a later call was served (on a regtest lab, our own nodes).
-
-

Building it changed the design, and running it found faults that the tests had not. The plainest: the wallet's limit of 8 payments at a time first let a win go as soon as it was sent, as is right for a ticket. With 100 sellers, 24 wins were then pending at once on the 30-slot channel, and 47 of 313 payments failed. A win now stays inside the limit until it has been paid. The tree's docs/TICKETS.md, section 9, lists what building it changed and what the lab found.

-

A file cut short with 100 sellers. A later fault showed only when the machine was busy. The gateway bears two unpaid wins from a buyer. At a third, the answer it is sending stands still for the payment, for 10 s at the most, and is then cut short. A file of 64 pieces at one win expected draws three or more wins 8 times in 100, and its answer then stands still at the third until the first is paid. The wallet paid wins strictly in the order it found them, all sellers together, so the first of those three waited its turn behind the other sellers' wins: about 7 s when the machine did nothing else (100 wins at 14 a second), which is inside the 10 s, and more than 10 s when it was busy. The seller then cut the file, and every one of its wins was paid a moment later. With 16 busy loops beside the lab, on its 16 cores, a file was cut in 12 of 15 runs of the 100-seller check; on an idle machine, 13 runs cut none. The fault was not new: it was also there in the tree the lottery was first merged in. The wallet now pays first the wins a seller's answer stands still for. It knows which they are by its own count against the seller's terms, and takes no seller's word for it. Under the same load, every file was whole in 5 runs of 5, and the whole lottery script then passed ten runs out of ten. It is a change of order only: which payments are made, the limit of 8 at a time and every check of an invoice are as before. These are the numbers of one lab on one day (regtest, one machine, our own nodes, one routing node), and the load measures nothing but itself. What the two waits bound beyond that is reasoned from the lab's rate and was not run past 100 sellers: a win no answer waits for would reach the seller's 30 s of grace with about 420 wins waiting, and some 140 wins of the urgent kind at once would use up the 10 s. A slower machine or a slower route lowers the rate, and those numbers shrink with it.

-

What the second form is built from. None of its parts is ours. The roll uses oblivious transfer, in which a receiver takes one of two values and the sender does not learn which: the prototype uses the protocol of Chou and Orlandi [46], whose proof has since been questioned [47], extended to many transfers by the method of Ishai, Kilian, Nissim and Petrank [48]. That extension is safe only against a seller that follows the rules, so a real build needs a hardened one [49][50]. The transfers are combined by Gilboa's multiplication [51], the same step that threshold signing uses [52][53]. The proof that ties a lock to its rolls is a Groth16 proof [54] over the curve BLS12-381 [55] with the key on Jubjub [56], made with the arkworks libraries [57]; who may run its setup is the question studied in [58][59]. Only the way these are put together is ours, and that is the part nobody has reviewed.

-

In the design's lab a roll of the first form cost about two millionths of a second for both sides together. As built, a win was paid 221 ms after its payment began (median of 35 payments through one routing node), and each win paid that node 1 sat, which is 1.6% of a 64 sat win. A page bought by a roll took the wallet 3.0 ms a call, against 1.5 ms for a free page: a roll is one more request (on a regtest lab, our own nodes). A roll of the second form cost 16 millionths of a second for each side and 200 to 600 bytes; in 20 runs out of 20 the seller collected its win alone, and the buyer's node showed the payment complete 13 ms after the win. Numbers has the rest.

- -

6How it comes together

-

This is one session from the first request to the last, with a seller the buyer stays with and pieces smaller than a ticket, in the form where a win pays itself. That form is the design, and it is not built. In the form that is built, where the buyer pays after a win, two of the steps fall away: nothing is set aside and nothing is topped up, and a win is paid by an ordinary payment as soon as the wallet has found it.

-
-
Terms
A node runner puts a gateway in front of a service it already runs and sets a price for a piece. The gateway answers a first request with its terms: the price of a piece, the size of a win, and so the odds.
-
Limits
The wallet checks those terms against the owner's limits: the largest win, the highest odds, what any one seller may be paid, and the budget for the task. Terms outside the limits are refused before anything is paid.
-
Set aside
The wallet locks one payment with the seller over Lightning, of at least 546 sat as every held ticket is. Nothing has been spent. It is money set aside.
-
Roll
Each request carries the buyer's half of a roll. The roll rides on the request, so the service does not wait for it.
-
Win
When a roll wins, the seller collects the payment that was set aside. The wallet sees the money move on its own node, and books what its node paid, never a number the seller sends.
-
Top up
The wallet sets the next payment aside in the background, and the session goes on.
-
Stop
When the buyer stops, the seller cancels the payment that was set aside, and what was not won comes back, as an unused ticket does.
-
-

Which way of paying is used follows from the size of a piece and from how long the buyer stays with a seller. This is the rule the wallet has today.

+

Neither side can steer the roll. Each roll is made from two halves. The seller fixes its half of every roll before the session and shows only a fingerprint of them, so it cannot change one later. The buyer adds its half only after the piece has arrived. The two are hashed together and the result decides, and both sides can work it out for themselves. The argument treats SHA-256 as a fair source of randomness, and it is our own. Chris Guida's second review read it and the code and found no way for either side to steer a roll; that was one person's reading, not a proof and not an audit.

+

Exact on average, uneven in one run. A miner knows the feeling: no block for a while, then one, and over a year the income matches the work. What one buyer pays one seller is a whole number of wins, so it evens out only over many wins between the same two parties: to be within 20% of the price nine times in ten takes about 68 wins (computed). Below that it is luck. So the wallet keeps a call that expects fewer than 4 wins off the lottery where the seller also offers prepaid tickets, and pays it with a ticket instead.

+

The form that is built: the buyer pays after a win. Nothing is locked ahead. When a roll wins, the seller sends an ordinary Lightning invoice, and the wallet, which has worked out the roll itself, pays it at once, and pays only a win it found. Its weakness is plain: a buyer can see a win and not pay. In our lab such a buyer was served about 1.4 wins' worth on average before the seller stopped it. That is a small, bounded loss to each cheat, not enforcement. Because nothing is held, neither slots nor dust stand in the way, which makes this form the way to pay many sellers at once.

+

The form that is not built: a win that pays itself. The buyer sets a ticket aside, and each roll gives the seller a small, hidden chance of drawing its key, so the buyer cannot refuse to pay a win. The aim was first set out and built by Paul Gerhart, Jay Taylor and Sri Aravinda Krishnan Thyagarajan in May 2026 [44]; our way of reaching it differs from theirs, rests on an argument of our own, and will not be built before a cryptographer has reviewed it. The lottery in detail has both forms.

+ +

5Many sellers, and how a buyer chooses

+

Nothing in a ticket ties a buyer to one seller: each ticket is its own Lightning payment. But the slots a held ticket takes are shared along its whole route. From one channel of 30 slots, keeping to half of them, a buyer can hold tickets with 7 sellers at two each, or 15 at one each. So held tickets are for one seller or a few, and a swarm is paid after a win in the lottery, which holds nothing. On a regtest, through one routing node on channels of 30 slots, the built wallet and gateway paid 100 sellers at once with no payment failed; the 100 sellers were 100 gateways beside one seller node.

+

The wallet chooses for each call, by the size of a piece and how long the buyer stays:

- - - - - + +
CaseHow it is paid
A piece worth a ticket or moreIt releases a ticket.
A call that expects fewer than 4 wins, from a seller that also offers prepaid ticketsA ticket: held, where the owner named the seller and one fits; a prepaid one first, where it did not.
A seller the buyer stays with: the call may spend four tickets' worth or more there, and a ticket can be heldTickets. With a seller the owner has not named, one prepaid ticket first, then held tickets one at a time.
Anything smaller, and any seller no ticket can be held with, as most sellers in a swarm areA roll, paid after a win, with nothing set aside, where the seller offers the lottery for that piece (a quarter of a win or less). The win is sized so that the session expects about sixteen wins, and it is never so small that the routing fee takes most of it: at least 64 sat through a routing node.
Rolls were chosen and no size of win fits the owner's limitsTickets, and a prepaid ticket where none can be held.
A piece worth a ticket or more, or a seller the buyer stays withTickets. With a seller the owner has not named, one prepaid ticket first, then held tickets one at a time.
Anything smaller, and any seller no ticket can be held with, as most sellers in a swarm areThe lottery, paid after a win.
A single call from a buyer with no sessionOne ordinary Lightning payment.
-

If the win that pays itself is built one day, it would take the place of rolls with a seller the buyer stays with. Its win is a held ticket, so it would never be below 546 sat, and a seller that earns less than that from a buyer would still be paid after a win.

+

The full rule, with its edge cases, is under How it comes together.

-

7Many sellers at once

-

Nothing in a ticket ties a buyer to one seller: each ticket is its own Lightning payment. But each held ticket takes a slot on every channel of its route, and the number that binds is the smallest over the whole route, shared by every buyer who uses it. From one channel of 30 slots, keeping to half of them, a buyer holds tickets with 7 sellers at two tickets each, or with 15 at one each. At 15 sellers with two each the channel is full and nothing else can pass through it. So on today's network held tickets are for one seller or a few.

-

Earlier drafts gave a much larger number of sellers that one channel could hold tickets with at once. That number is withdrawn. What the five-node lab behind it showed (a buyer, one routing node and three seller nodes, all Lightning Fork, every channel with 483 slots) is narrower: a Lightning Fork node accepts 483 pending payments on one channel, the most the protocol allows, and its router kept 400 tickets in flight at once, two each to 200 seller sessions spread over three nodes, locked in 11 seconds. It did not show a route that carries that many. A channel with a Core Lightning node at either end carries 30 at its default, as does eclair, and LDK carries 50, as commonly documented. The same lab showed that a seller that had just appeared could be paid a quarter of a second later through one routing node, and a tenth of a second later over a direct channel.

-

Many sellers at once are paid after a win in the lottery, which holds nothing. In the five-node lab, 200 seller sessions that all won in the same instant had all been paid 4.6 s later, with nothing held for any of them beforehand. On a 30-slot channel the wallet has to pace such payments: 200 payments of 64 sat all went through in 7.1 s when sent 8 at a time, and 139 of the 200 failed when sent 64 at a time.

-

Those were the design's measurements, made by scripts. The wallet and the gateway that are now built have done it too, on a regtest lab, our own nodes, through one routing node on channels of 30 slots. With 20 sellers paid at once, three small files from each: 3,840 rolls, 68 wins where 60 were expected, every file whole, no payment failed, 4.8 s. With 100 sellers: 19,200 rolls, 288 wins where 300 were expected, every file whole, no payment failed, 20 s, which is 14 wins a second. There were never more than 8 wins on the channel at once, and an ordinary payment of 5,000 sat that somebody else sent over the same channel meanwhile went through in half a second. One caution: the 100 sellers were 100 gateways beside one seller node. The channels carried what 100 sellers' wins would, and the seller's side was one node's worth of work. A second caution: those figures are from an idle machine. On a busy one the same check at first had a seller cut a file short, and the wallet's order of paying was changed for it; see A file cut short with 100 sellers.

-

Three limits remain, and each has an answer.

-
-
A ticket cannot be re-aimed
Once a Lightning payment is locked, its route and its receiver are sealed. Money cannot be locked first and pointed at a seller later, and a locked ticket cannot be moved to another seller. What can be done is to lock a new one, which is the quarter second above. The answer is not to wait for it: for content the buyer can check, the seller serves the first piece while the ticket locks, and paying after a win needs no lock at all. Serving a stranger one piece before it has paid is BitTorrent's "optimistic unchoke" [30], borrowed here.
-
Tickets are too coarse for small sellers
Through a routing node each collected payment costs about 1 sat, so paying one seller less than about 100 sat wastes more than 1%, below 1 sat nothing can be paid, and no ticket under 546 sat is held. In a swarm most sellers earn far less than that. The answer is the lottery.
-
Held tickets are a shared, limited resource
A channel carries between 30 and 483 held payments in each direction, for all sellers and every other user together, and the wallet takes at most half: 15 on a 30-slot channel. A seller that leaves without cancelling keeps its tickets locked for hours, and in a swarm sellers leave all the time. The answer is to hold little: two tickets with a seller the buyer stays with, one with a seller the owner has not named, one each when there are a few, one where a win pays itself, and none where the buyer pays after a win, which is how a swarm is paid.
-
-

An owner cannot list sellers it has never heard of. In place of a list of names it approves a kind of spending: a budget for the task, and a small cap on what any one unknown seller can be paid. The wallet has that part of the policy, for tickets and for wins. A seller the owner has not named is paid wins of 250 sat at the most, and no more than 32 wins in a task's window; with tickets, it is paid one prepaid ticket first and then held with one ticket at a time (A seller the owner has not named).

+

6Over HTTP, for agents

+

A seller puts a gateway in front of any web service it already runs, beside its Lightning node. The gateway answers a first request with 402 Payment Required and its terms, in the shape the x402 standard gives that status [22], and every answer after that comes with a receipt the seller signs. The ticket and lottery entries are our own, so only Lightning Stream clients can pay with them.

+

On the buyer's side is a wallet for AI agents. An agent should be able to spend but never to hold a key, because a model can be tricked by what it reads. So the agent asks the wallet to pay, over the Model Context Protocol [26], and the wallet decides: it holds the keys and the ticket secrets, keeps to a policy the owner signs (budgets, caps for each seller, and a small cap for sellers the owner has never heard of), and books what its node paid, never a number a seller sends. Mainnet is refused on both sides unless the owner asks for it in so many words. Uses has the wire, the wallet and what they are for.

-

8The costs, stated plainly

-

The spreads below are simulations, except where a line says it was measured. "Nine days in ten" means the middle nine tenths of the days simulated.

+

7What it costs

-
Uneven income for a seller
A seller that earns about 4,000 sat a day in pieces of a tenth of a sat, with wins of 64 sat, is paid between 80% and 120% of what it earned nine days in ten, and between 96% and 104% over a month. A seller that earns 1,000 sat a day sees 58% to 141% on a day and 92% to 108% over a month. A seller that earns 100 sat a day gets no win at all one day in five. The rule behind these figures is the horizon above: about 68 wins for 20%, about 1,080 for 5% (How far "on average" reaches).
-
The seller chooses the trade
A smaller win means steadier income and a larger share lost to routing fees, because each win costs about 1 sat for each routing node it passes: 6.25% of a 16 sat win, 1.6% of 64, 0.4% of 250, 0.1% of 1,000. A node that runs several services gets steadier income for nothing, because all their wins land on one node: twenty services that each earn 1,000 sat a day bring that node within 9% of its earnings on a day.
-
Uneven cost for a buyer
A download priced at 1,638 sat (4 GiB at a tenth of a sat a piece, wins of 64 sat) cost between 1,152 and 2,176 sat nine times in ten. For it not to stall on an unlucky run more than once in a thousand, the owner must allow 2,795 sat, fees included. The budget is a ceiling. The average stays at the price. Measured on a regtest lab, our own nodes: a file priced at 381.5 sat, bought five times, cost 520, 780, 390, 260 and 325 sat with routing fees. The wallet stops asking for more pieces when the wins of one call run far above its price (for a call of 1,000 sat on wins of 64 sat, at 1,848 sat), and the budget the owner gave the task holds whatever the rolls do.
-
The seller goes first when the buyer pays after a win
By about one win's worth for each new buyer, and by everything where a seller earns less than one win from a buyer. Measured on a regtest lab, our own nodes: a buyer that never paid was served 1.4 wins' worth on average with pieces of a quarter of a sat, and 3.9 wins' worth with pieces of a quarter of a win, because the gateway bears two unpaid wins and serves 8 pieces ahead. A buyer that sends no halves at all, or voids every piece, gets the window of 8 pieces a session, which is 2 wins' worth at most, since no piece dearer than a quarter of a win is drawn for. Behind a reverse proxy the gateway's cap on sessions from one address counts only if the runner names the proxy and the header it reports a buyer's address in; otherwise every buyer has the proxy's address. Nothing on today's Lightning can force a buyer to pay a seller it touched only briefly.
-
What routing nodes carry
Tickets are held payments, and a win that pays itself needs one held for each seller. Each takes a slot on every channel of its route for as long as it is held. A routing node is paid nothing for one that is cancelled. If a seller vanishes with tickets locked, the routing node that opened the channel to it bears a forced close: with 100 tickets of 1,000 sat locked that cost about 29,000 sat in all at 1 sat/vB, which is 29% of the tickets' value, and with 3 tickets 1,530 sat (measured on regtest, anchor channels); scaled to 10 sat/vB the first is about 290,000 sat (Fee rates). A locked payment below a channel's dust limit, 354 sat on a Lightning Fork node and 546 sat on a Core Lightning node, cannot be claimed on the chain at all, which is why no ticket under 546 sat is held. Paying after a win holds nothing, and pays the routing node for every payment it carries.
-
A win that pays itself cannot be small
Its win is a held ticket, so it is at least 546 sat. Larger wins mean lumpier income: over a month, a seller that earns about 4,000 sat a day is paid between 85% and 115% of it with wins of 1,000 sat, against 96% to 104% with wins of 64 sat (simulated). A small seller is better paid after a win, where a win can be any size.
-
Pooling does not work here
Miners even out their income in pools, and Meni Rosenfeld's analysis of how pools pay [45] is where we took the comparison from. Pooling does not carry over, because a mining share is proof of work that anyone can check, and a piece served proves nothing to anyone who was not there: a seller and a friendly buyer could invent pieces and draw on the pool for free.
-
The deeper help is in Lightning itself
Changes to Lightning would do more than anything we can add on top of it. Point locks [14][15] first: with them the self-paying win would no longer need its proof. Then a fee for held payments [11][12], which would pay routing nodes for what tickets ask of them. Both are proposals made by others for Lightning as a whole. Neither exists on the XBT Lightning forks. They are other people's software. We can ask for them, and we cannot promise them.
+
Money tied up
Unused tickets are locked until the seller cancels them or they expire, for hours if the seller vanishes.
+
A Lightning node on each side
A seller needs an lnd-family node with inbound capacity, online while tickets are locked. A buyer needs a Lightning node with a channel.
+
Load on routing nodes
Held tickets take slots and capacity on every channel of their route, and a routing node is paid nothing for a ticket that is cancelled. On a large network that is the behaviour that defences against channel jamming [10] are meant to stop, which is why tickets stay few, small and short-lived.
+
A routing fee per ticket
At the forks' default policy a hop takes about 1 sat for each collected ticket: 0.1% of a 1,000 sat ticket. What nodes on mainnet charge is not known to us.
+
Real fee rates
Every on-chain figure was measured at regtest's 1 sat/vB, on channels of the anchor type. At mainnet's rates, on a channel without anchors, a 1,000 sat ticket can have no output on the chain at all, which is why the floor for held tickets rises with the fee rate.
+
An uneven lottery
Paid by lottery, income and cost are uneven in the short run, and the seller goes first by about one win's worth for each new buyer.
+
What others see
No transaction on the chain ties a buyer to a seller, but the nodes along a route see a run of equal payments to one seller.
+

The costs, stated plainly has the figures, and Fee rates the table at 1, 10 and 50 sat/vB.

-

9Paying over HTTP

-

The web has kept a status code for this since 1997: 402 Payment Required, reserved for future use then and still [21]. The x402 standard, which Coinbase created and the x402 Foundation now keeps [22], gives it a shape: the server answers with a price and terms, and the client retries with a payment in a header. Lightning Stream uses that shape. The wire and the receipts were first built for the earlier channel, which is no longer in the tree. For tickets the seller's 402 has an entry of its own in its list of accepted payments, and every request of a session carries a signature over the request with the session's key; a ticket's secret travels in a release of its own. Both sides of that entry are built and run on a regtest: the gateway offers ticket terms in its 402, and the wallet's pay tool reads them and pays. The lottery has an entry of its own beside it. Its terms carry the size of a win and the price of a piece, which together fix the odds, and the buyer's half of each roll travels in a small request of its own after the piece has arrived. The tree's docs/TICKETS.md writes both down as a draft. Upstream x402 clients do not know either entry, so only Lightning Stream clients can pay with tickets or by rolls.

- -
- - One paid call with tickets: request, 402 with terms, two tickets locked, then a release carries one secret, and requests paid from the balance get data and a signed receipt. - - - Buyer (an agent) - - Seller (an API) - - - - GET /forecast - - 402 · price · seller's node · ticket terms - - first: 2 hashes sent, 2 hold invoices paid over Lightning - - release: the secret of one ticket - then GET /forecast, paid from the balance - - hash the secret, find its - ticket, collect, serve - - 200 OK · data · receipt signed by seller - -
Figure 4. The 402 step happens once, and two tickets are locked before the first paid request. After that the wallet releases the next secret whenever the balance runs out, requests are paid from the balance, and the wallet locks the next ticket in the background. This flow now runs on a regtest between the wallet and the gateway; for what was measured see Numbers.
-
- -

Each receipt is signed by the seller and bound to the hash of the request it paid for. With tickets the receipt matters more than before, because it is the only proof of payment the buyer can show: the secret proves nothing. A client that does not check its receipts has no such proof. An answer lost on the way is paid for from the balance. A refusal of a request the seller could authenticate is signed too; two answers cannot be (a request out of order, and a session the seller has forgotten), and the wallet releases nothing on their word.

-

For a single call from a buyer with no session, an ordinary Lightning payment is the right tool, and a seller's 402 can offer that beside tickets. Two existing forms do this: x402's exact scheme for a Lightning invoice [22] and L402 [23]. The wallet reads such an entry as x402's exact. Upstream x402 has since defined exact on Lightning; its definition has not been checked against ours, no seller in the tree offers the entry, and it was not run in the lab.

-

On the wire this is x402 v2. Since October 2026 the chain is named by its standard name, its CAIP-2 id [24] in the bip122 namespace, with "layer": "lightning" beside it to say that the payment is made over Lightning on that chain. Before, the entries used a name of ours, lightning:, which nobody else defines; the wallet and the gateway still read it for one release and write the new one. Because XBT and the SHA-256 chain share a genesis block, XBT mainnet is keyed to its fork block, 961,640, instead of genesis: bip122:0000000000000050c1e5f69672f45929. The scheme names, ticket and lottery, and the asset name are still ours. XBT is Bitcoin on BLAKE2b proof of work, and up to that block it has the same history as the SHA-256 chain, so its Lightning invoices look alike on both. What marks an XBT Lightning node, invoice or offer is feature bit 512, a convention of the two XBT Lightning forks [61][63] and not of ours. The wallet checks it on everything it pays, and it pays only through channels whose funding it can prove exists on XBT alone.

+

8Prior art

+

Paying by lottery is an old idea, and none of it is ours. David Wheeler proposed "transactions using bets" in 1996 [33] and Ronald Rivest "electronic lottery tickets as micropayments" in 1997 [34], with a bank that honours the winning tickets; Silvio Micali and Rivest removed the back-and-forth in 2002 [35], and Rafael Pass and abhi shelat put an escrow on a chain in the bank's place in 2015 [36]. Orchid [39] and Livepeer [40] run such lotteries with a contract that pays a winner without the payer's help. For Bitcoin the idea was raised by Mike Caldwell in 2012 [41], sketched inside Lightning channels by Tadge Dryja in 2016 [42] and built from specially made keys by Oleksandr Kurbatov in 2025 [43], and a win over Lightning that enforces itself was first built by Gerhart, Taylor and Thyagarajan [44].

+

Where tickets sit. Between a prepaid balance and a payment per piece. A prepaid balance, such as L402 used for a metered service [23], hands the seller the money before the service, and the buyer can lose all of it. A payment per piece, such as the keysend streaming of podcast apps [8][9], hands it over piece by piece and makes each piece wait for its payment. A ticket commits the money before the service and hands it over a ticket at a time. Cashu ecash pays per request instantly and privately, but a mint holds the money [27]; a locked ticket is held by nobody. Nostr Wallet Connect gives each app a limited connection to a wallet [25], the idea the agent wallet applies with an owner-signed policy.

+

How Stream differs. Nothing in a ticket is a new mechanism: it is the hold invoice [5], used to the end "stuckless payments" were proposed for [6], and bound to HTTP 402 and to an agent's spending policy. The lottery as built adds nothing to the older work but that same binding. Lightning has neither a bank nor a contract to honour a win, which is why, in the form where the buyer pays after a win, the seller is exposed by about one win. Prior art, on the design page, has the full discussion.

-

10Paying only for what checks out

-

Paying per piece only helps if a bad piece can be caught. For content that exists before it is sold, such as a file, a dataset or a recorded stream, the seller first signs a manifest: the Merkle root [32] of every chunk it promises to send. Then the stream begins.

+

9Status

+

Built, and run on a regtest only, between our own nodes: tickets on both sides, the ticket book in the wallet and the seller's gateway; the lottery in the form where the buyer pays after a win; a demo in which a film is paid for piece by piece as a player reads it; and packages for Umbrel and StartOS node boxes. On StartOS they cannot start beside Lightning Fork until a change to its package, which its maintainer has agreed to look at for the release after next. Lab scripts in the public tree rerun the tests, and a guide lets anyone outside the project run them.

+

Not run on mainnet. Nothing of Lightning Stream has run on XBT mainnet. The next steps are one rehearsal between two of our own nodes with a small channel, then a small test with people outside the project, by invitation, with amounts that can be lost entirely. Neither has started.

+

Not audited. Chris Guida has reviewed the code and the design twice, and his findings are answered in the code and on these pages; nobody outside the project has reviewed those answers. There has been no independent audit, and the win that pays itself waits for a cryptographer. Treat it all as unaudited software.

+

Progress and status has what is built and not built, and Tests and numbers every measurement and what it does not show.

-
- - Chunks are checked against the signed manifest and a ticket is released for each; a chunk that fails its proof is not paid and the stream stops. - - Signed manifest - root = H(chunk 1…8) - - Each chunk arrives with a proof. Check it, then release a ticket for it. - - - - - - - - - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - verified · ticket released - bad proof - never paid - The seller risks one chunk. A chunk that fails its proof is not paid for. - -
Figure 5. Streamed fair exchange, as designed for tickets. A seller that tampers with chunk 5 is paid for chunks 1 to 4, which it delivered, and nothing after. This ran on the earlier channel; on tickets it is not built.
-
- -

This is where the order of a ticket turns round: the buyer checks a chunk first and releases its ticket second. The last chunk can be sold the opposite way, as an ordinary Lightning payment to a hash the seller chose, so that its key arrives only with the payment; selling a key through a hash lock goes back to Gregory Maxwell's contingent payment of 2011 [31]. Fair exchange was built and tested on the earlier channel, and it left the tree with the channel (The earlier design): chunks proved against a signed manifest, with a hash-locked last one, can no longer be bought with this code. On tickets it is designed, and simpler than it was, and the draft wire has a setting for it, but it is not built: the wallet does not buy content that way. The lottery has a first piece of it: where the wallet is given the hash of a piece, it sends its half of the roll only for a piece that matched. An agent cannot pass those hashes through the pay tool yet.

-

This only works for fixed content. Nobody can commit to the Merkle root of a model's answer before the answer exists. For generated output, paying per piece still limits what the buyer can lose to one ticket, but it cannot prove that a piece is any good.

- -

11A wallet for agents

-

An AI model should be able to spend, but never to hold a key: a model can be tricked by what it reads. So the agent never signs. It asks a wallet to pay, and the wallet decides.

- -
- - The agent asks the policy wallet to pay over MCP; the wallet holds the keys, enforces the owner's signed policy and pays through the owner's Lightning node. - - - AI agent - asks; cannot sign - - MCP - - Policy wallet - holds the keys and the ticket secrets - daily budget · per-seller caps - allowed sellers only - human approval, single payments only - tamper-evident log of what it released - - Owner - signs the policy - - - Owner's Lightning node - invoices · offers · tickets - - -
Figure 6. The model sees tools such as quote, pay and balance. The wallet is built so that an agent held to those tools, even a prompt-injected one, can spend only what the policy allows, with the exceptions listed below.
-
- -

The wallet speaks MCP, the Model Context Protocol that Anthropic published in 2024 [26] and that AI agents already use for tools, so any agent that can call a tool can pay. It pays through the owner's own Lightning node: XBT Lightning invoices (BOLT 11) and offers (BOLT 12) [4], and, on a regtest, stream tickets and wins in the lottery through the same pay tool. A single payment the agent asks for by itself, a Lightning invoice or a payment on the chain, waits for the owner's signature from another device when it is above the owner's threshold. A paid call to a seller does not ask a person: ticket and lottery payments are bounded by the budget of the task and by the caps, and never wait for a human. The flow in which a paid call waited for the owner's approval belonged to the earlier channel and went with it (The earlier design). The policy itself is signed by the owner, so the agent cannot rewrite it.

-

For tickets the wallet has a ticket book. The secrets are made inside the wallet's signer, and the agent never sees one before it is spent. Each ticket is counted twice: against a cap on what may be locked when it is locked, and against the budgets when its secret leaves. A released secret is written down before it leaves the signer, so a crash cannot under-count what was spent. Routing fees are counted as spending. The ticket book is built, in the wallet's signer, and runs on a regtest against Lightning Fork nodes. It is tied to the agent's pay tool, so an agent buys a service with tickets there in one call. It holds 2 tickets with a seller the owner named and 1 with one it did not, the latter only after a prepaid ticket (A seller the owner has not named), and checks a channel's slots, its dust limit and the floor of Fee rates before a lock.

-

Mainnet only when asked for, and only to public sellers over https. The outside review found that "test networks only" was a sentence in the documents and not a guard in the code. Now it is a guard on both sides. A gateway config that names no chain is a regtest config, and the example shipped is one. Mainnet takes two settings, the chain and an acknowledgement typed word for word ("real funds, software that has run on regtest only"), and a gateway that starts there prints a short list of what is known to be open, at every start. On mainnet the wallet pays no ticket and no win unless its owner gives the same sentence, and then with lower caps than elsewhere unless the owner sets others: 4 tickets and 4,000 sat locked at once, 4 sellers at once, 120 ticket payments an hour. The packages' setup pages write low caps too (Packages). This guards against using mainnet by omission and does no more: the acknowledgement makes no part of the software fit for mainnet. Separately, the wallet sends nothing to a seller the owner has not named unless its address is https and every address its host has is on the public internet, so not a private, loopback or reserved one. The check is made before the first, unpaid request leaves; until 17 October 2026 that request went out first. A host whose address changes between the check and the connection (DNS rebinding) is not caught by it. The gateway, for its part, will not listen on any address but loopback unless its public address is https, which is the runner's word that a TLS proxy stands in front of it.

-

For the lottery the same signer does the rolling. It makes the buyer's half of each roll from its own random source, checks the seller's half against what the seller fixed before the session, and works out every roll itself. It pays only a win it found, only by an invoice that names the seller's node and the agreed size of a win, and only once. The payment is written down as spent before it leaves, and what is booked is what the owner's node paid, with its routing fee. The owner's policy sets the largest win, how often a piece may win, and how many wins a seller the owner has not named may be paid.

-

The scope of the wallet's claim is narrow. It covers an agent whose only way to the wallet is the MCP tools. Software that can open the wallet's signer socket directly is outside it, so the socket must stay out of the agent's reach. The policy binds only what goes through the wallet: anyone who holds a broader credential for the Lightning node can spend past it. The policy also limits how much an allowed seller can be paid, not what else that seller does. And the outside review found faults in this very part, the wallet's budget accounting; see Status for where that stands. One rule that came out of those fixes carries over to tickets unchanged: the wallet books what it released, never a number the seller sends.

- -

12A demo: a film paid for as it plays

-

This paper opens with one buyer and one seller and a streamed film. That case now runs, as a demo, on a regtest. A node runner's media server, Jellyfin as it comes, stands behind the seller's gateway, and a film is bought from it piece by piece through the wallet while a player reads it. Nothing is installed into Jellyfin and none of its settings change. The same file is then bought in pieces from 20 gateways at once, paid by the lottery. A script in the public tree, scripts/demo_film.sh, runs all of it, and the tree's docs/DEMO.md is the guide for a node runner, with the seller's whole setup.

-

The conditions. Every figure in this section is from one run on 13 October 2026: on a regtest, on one machine, on loopback, between our own Lightning Fork nodes, with channels that carry 30 pending payments. Nothing ran on mainnet or between two people. On one machine everything is a loopback away, so the times say what the software adds and nothing about a real network. Jellyfin was version 10.11.0. The film is Big Buck Bunny, (c) 2008 Blender Foundation, www.bigbuckbunny.org, licensed under Creative Commons Attribution 3.0: 276 MB, 10:34 long, 1080p, 3.5 Mbit/s. It was priced at 100 sat a MiB and paid in tickets of 1,000 sat. That price is a number chosen so that a ticket lasts about half a minute of this film. It is not a market price. The rules of tickets and of the lottery were the shipped ones, but the demo's driver changes some other settings: the owner names every seller, so nothing in the demo is paid as a stranger; caps on rates and sessions are raised for a lab where every buyer comes from one address; and the rule that keeps small calls off the lottery is turned off for the 20 sellers, so that their rolls can be shown. docs/DEMO.md lists each change, and says where the script gives no reason for one.

-

On the buyer's side stood the wallet and a small paying proxy, a demonstration script that a player reads from in place of the seller. Each request the player makes becomes one call of the wallet's pay tool, so the wallet pays as the film plays and stops when the player stops asking. The proxy holds no key and no ticket secret. The film was played as HLS, in segments of about six seconds, and priced by the byte.

-
- - - - - - - - - - - -
WhatThrough one routing nodeThrough two
First frame in ffmpeg, from a wallet with no session open: the terms, 2 tickets locked along the route, the playlist, the first segment0.46 s (median of 3)0.55 s
The same with a session open0.17 s0.12 s
Played in real time, the player keeping 12 s of film ahead90 s with no stall; 4 tickets released, 2 held45 s with no stall
What it cost2,213 sat a minute of film (22.1 MiB a minute)The same.
The whole film, fetched as fast as it came106 segments, 274.7 MiB, 27,466 sat by the price; 28 tickets paid, 28,000 satThe same 28 tickets.
Routing fees for the whole film28 sat (1.001 sat a ticket)56 sat (2.002 sat a ticket)
Held ahead while it played2 tickets (2,000 sat), and never more pending on the buyer's channel2 tickets
-
-
- - - - - - - - - - -
What happens whenMeasured, through one routing node
The player is pausedIt stops asking once its 12 s are ahead. In the 20 s after that nothing was paid and no ticket was released. The 2 held tickets stayed held and were not spent.
The viewer seeks to 5:00Playing from the new place after 0.03 s. Jellyfin had those segments ready.
The connection drops in the middle of a segmentOne request failed. The player asked again and had the segment whole 0.5 s later, and the film did not stall. The 0.28 MiB that had arrived were paid for (30 sat) and were bought again.
The seller's gateway is killed and started 8 s laterOne request was refused. The film stood still for 19 s and then went on in the same session, with the balance it had. Why it was 19 s and not 8 was not traced.
The viewer stopsThe seller cancelled the 2 held tickets, and they were back on the buyer's node 0.24 s later. 458 sat, what was left of the last released ticket, stayed with the seller.
An agent's one call that may use 300 sat at the most3.0 MiB, the first bytes of the film's file, in 0.37 s. One ticket was released, and the wallet stopped the answer where 300 sat were used by its own count.
-
-

After every part, what the buyer's node paid, what the sellers' nodes received and what the wallet's ledger held agreed to the millisatoshi.

-

The same file from 20 sellers. The film's file, 263.3 MiB, was cut into 1,054 pieces of 256 KiB at 1 sat a piece and bought from 20 gateways at once. A piece costs far less than a ticket, and 20 sellers are more than tickets can be held with from one 30-slot channel, so the wallet paid by rolls: one roll in 64 wins, and a win is an ordinary payment of 64 sat. There were 1,054 rolls and 14 wins, where 16.5 were expected. The buyer paid 896 sat for pieces priced at 1,053 sat; the run before it paid 576 sat. Nine of the 20 sellers were paid nothing: each had sold about 52 sat of pieces, which is less than one win. Routing fees were 14 sat. Never more than 4 payments were on the buyer's channel at once, nothing was held between wins, and no payment failed. Every piece was checked against its hash, and the file was whole in 3 s. That is the lottery as it is: exact on average and uneven in one run, for the buyer and for each seller. The 20 gateways stood beside one seller node (on a regtest, one machine, our own nodes, one routing node).

-

What the demo does not show

-
-
A person watching
Nobody watched this film on a screen. The players of the run were ffmpeg, for the first frame, and a script that asks for segments as an HLS player does: it keeps 12 s ahead, pauses and seeks. mpv, VLC and a browser were not tried.
-
A stock Jellyfin app paying
It cannot yet. The player here is handed the film's address. Jellyfin's own web and TV apps also log in, browse and report progress, with headers the gateway does not pass on by default, and they play the file directly with range requests, which the wallet's pay tool cannot send yet. A paying proxy that carries those is not built.
-
An AI model as the agent
The agent of the demo is a script that speaks MCP with the wallet's tools.
-
Real coins, or two people
It is a regtest, on one machine, between our own nodes. Letting people stream from a seller needs a shared test network or mainnet, a gateway reachable from outside behind TLS, and somebody's decision to expose a home server.
-
Seeking inside what was paid for
A viewer who seeks back pays for those segments again.
-
What the limits already say
A seller that takes a ticket and serves nothing keeps at most one ticket, what is left of the last ticket stays with the seller, and a buyer that never pays a win was served about one win's worth.
-
-

For a seller: what a buyer can reach is decided by the gateway's routes, one film each, so the service's own port must never be published, only the gateway's. In the demo a second film on the same server, and the server's own pages, answered 404 through the gateway.

- -

13Packages for node boxes

-

Most people who run a Lightning node run it on a home box, under umbrelOS or StartOS. There are now packages for both: a wallet app, which buys, and a gateway app, which sells a service of the owner's. Both use the box's own Lightning Fork node. Neither holds the node's admin credential: the owner pastes narrow ones, and the wallet's tool server for agents cannot read the one that pays. The images they run are published on GitHub's container registry, for three kinds of processor, and the packages name each image by its digest, so a box gets exactly the image that was checked. Whether a rebuild gives the same digest has not been checked. Nothing is submitted to either platform's store; a tester installs from a store of our own.

-
-
Where they have run
On regtest only. In simulations of each platform's install, on one machine, a packaged wallet bought from a packaged gateway with tickets, also after a restart, and on StartOS after a backup was restored into a new install. On a real umbrelOS 2.0 box, a test machine of our own, both apps installed from a community store, and the wallet bought from the gateway with a ticket, again after a restart and a reboot. That box ran regtest stand-ins for the node apps the packages depend on, with their names, and the images came from a registry of our own, not from GitHub's: no box has yet pulled them from there. The Lightning Fork and node packages themselves were read, not run. Nothing was run on a small computer such as a Raspberry Pi.
-
StartOS is blocked
StartOS mounts a folder of another package, never a single file, and Lightning Fork's StartOS package keeps the certificate the wallet needs at the top of its data, beside its credentials. Mounting that folder would hand the apps the node's admin credential, so neither app starts beside Lightning Fork on StartOS today. The fix is a change to Lightning Fork's StartOS package, the certificate in a folder of its own, which its maintainer has agreed to look at for the release after next. A test with the certificate alone in a folder ran.
-
Umbrel needs the seller's own TLS
umbrelOS gives apps no https of their own, and the wallet pays tickets only over https with a publicly trusted certificate. So a seller on Umbrel points a TLS proxy it runs itself at the gateway. On StartOS the owner adds a public domain to the gateway's interface.
-
No sellers over Tor
Both platforms can give the gateway an onion address, but that is plain http, and the wallet does not pay tickets over plain http. It cannot pay a seller reached over Tor.
-
Mainnet off by default
The gateway's setup page writes a regtest config unless the owner picks mainnet, and then asks for the acknowledgement and writes low caps: 4 sessions, 1 from one address, 4 held tickets of 1,000 sat. The wallet's starter policy on mainnet caps a payment at 2,000 sat and a day at 10,000 sat, and its signer refuses tickets and rolls without the acknowledgement, whatever the page did.
-
-

The tree's packaging/README.md and packaging/DESIGN.md have the details, the sizes and memory measured, and what cannot be done yet.

- -

14Built and not built

-
-
Built
The agent wallet and its policy engine: budgets, per-seller caps, approvals for single payments and the log. The wallet's Lightning payer, which pays BOLT 11 invoices and BOLT 12 offers through the owner's node. The HTTP 402 wire and signed receipts, for tickets and the lottery. Pay with work, where a miner pays with pool shares instead of coins; it is built around OCEAN's DATUM and TIDES [66]. All of it is in the public tree and runs on test networks only.
-
Built, for tickets
Both sides, each on a regtest against Lightning Fork nodes. The ticket book in the wallet's signer makes the secrets, locks tickets through the owner's node, writes each release down as spent before the secret leaves, and keeps to the owner's policy; scripts/ticket_book_regtest.sh in the public tree runs it. The seller's gateway stands beside a seller's Lightning node in front of any HTTP service: it offers ticket terms in a 402, issues hold invoices for a buyer's hashes, collects a ticket when its secret arrives, meters the answer per request, per byte or per second, and signs a receipt; scripts/gateway_regtest.sh runs it with a test buyer. And the two together: the agent's pay tool reads a seller's terms, locks tickets and pays as the answer arrives, with prepaid tickets as the fallback when slots are short; scripts/ticket_e2e_regtest.sh runs it through a routing node.
-
Built, the lottery
The form where the buyer pays after a win, in the wallet and in the gateway, on a regtest against Lightning Fork nodes. The gateway offers it beside tickets and the wallet chooses between them. The wallet's signer works out every roll itself, pays a win at once with an ordinary Lightning payment, and locks nothing with any seller. scripts/lottery_regtest.sh in the public tree runs it on channels of 30 slots: a 100 MB file bought by rolls, 20 and 100 sellers paid at once, a buyer that never pays, a seller that lies about wins, and a kill of each part. The argument that the roll is fair is our own, read by one outside reviewer and proved by nobody.
-
Built, a demo
A stock media server behind the gateway, and a film bought piece by piece through the wallet while a player reads it; then the same file from 20 gateways at once, paid by rolls. scripts/demo_film.sh in the public tree runs it, on a regtest, on one machine. The players were ffmpeg and a script, not a person at a screen; see A demo.
-
Built, packages
A wallet app and a gateway app for Umbrel and StartOS, over the box's Lightning Fork node, with their images published and pinned by digest. Run on regtest only: in simulations of both platforms, and on a real umbrelOS box with stand-ins for the node apps. They do not start on StartOS beside Lightning Fork yet; see Packages.
-
Built, since the last draft
The answers to the second outside review: a seller the owner has not named paid a prepaid ticket first and held with one ticket at a time; hold invoices only for a session that has paid; the floor for held tickets that follows from the fee rate; voids counted against the lottery's window, and the lottery offered only for pieces of a quarter of a win or less; small calls kept off the lottery where prepaid tickets are offered; lottery sessions that outlive a restart of the gateway; mainnet refused unless asked for, on both sides; no request to an unnamed seller at a private address or over plain http; the chain named by its standard name; public CI; and the lab reports in the tree.
-
Removed
The earlier design's hub, and later its on-chain channel, with the light client that watched it, the fair exchange built on its states and the flow in which a paid call waited for a person's approval. The code is in the history; see The earlier design.
-
Next
The packages the last draft listed are built. What comes next: one rehearsal on mainnet between two of our own nodes, with a small channel; then a small, bounded test on mainnet with people outside the project, by invitation, with the packages; and signed service lists, so that a seller can publish what it sells and a buyer can check who published it. None of the mainnet steps has started.
-
The defaults in the code
The ticket book and the gateway now have the defaults of Slots and dust: 2 tickets a session, no held ticket under 546 sat, held tickets within half of a channel's slots, and holding less, then paying another way, after a lock that finds no slot. They were tested on channels opened with 30 slots between Lightning Fork nodes, which stand in for Core Lightning there: such a channel carries 30 one way and 483 the other, and its dust limit is 354 sat, so the test is close and not the same. A policy written before this change that does not set these values now gets the new ones; the tree's docs/LIMITS.md says what that means.
-
Lab-tested
The design itself. The lock, release, cancel and failure cases in Numbers were run by scripts on three Lightning Fork nodes, and the slot and dust cases on six nodes, three of them the Core Lightning fork. Tickets to many sellers at once, and both forms of the lottery before the first was built, were run the same way, by scripts and prototypes on three and five Lightning nodes. The win that pays itself has been run in no other way.
-
Not built
The win that pays itself: it will not be built before a cryptographer has reviewed the argument it rests on. Fair exchange on tickets. A step where a paid call asks a person. A seller's software for a Core Lightning node. Signed service lists. Packages that start on StartOS beside Lightning Fork. A wallet that pays a seller over Tor. A proxy that lets a stock media app pay.
-
Planned
A deeper upgrade: a stream output inside a Lightning channel. Two direct peers would add one output to their channel, and the payer would pay out of it by signing a rising total for each piece, with no Lightning payment round per piece. It would bring back exact settlement per piece, which tickets give up. It needs a new channel type in the Lightning node software, so it can only be done with the maintainers of the XBT Lightning forks, and we mean to raise it with them. As designed it covers two direct peers only; tickets would still carry a payment across a route. For many sellers and for the lottery, the change that would help most is a different one, point locks; see The costs, stated plainly.
-
- -

15The earlier design

-

The first version of Lightning Stream did not carry payments over Lightning. It used its own one-way payment channel on the chain: Jeremy Spilman's channel of 2013 [1], in the CHECKLOCKTIMEVERIFY form that BIP 65 gives as one of its examples [2]. The buyer locked coins once in an output on the chain, signed a slightly larger running total for every piece, and the seller settled once. To reach many sellers with one channel it added a hub, with each forwarded payment locked by an adaptor signature [16][17][18]. A hub that forwards payments it cannot take was not new either: TumbleBit [19] and A2L [20] are its ancestors.

-

Chris Guida's review of the published code (October 2026) found the hub the weakest part. One-way channels with no revocation give a hub nothing to fall back on when a channel closes or is replaced while a payment is in flight, and that is the problem Lightning's commitment protocol [3] was built to solve. The review advised using Lightning for what a network is good at, reaching many sellers, and keeping the direct channel as a fast path. We went further and moved the whole payment path onto Lightning.

-
-
The hub is retired
Its code, tests and packages have been removed from the tree, and they remain in its history, last at commit 0911cc0. Lightning's own routing replaces it. The 59 stated limits that belonged to the hub, to the hub beside a Lightning node and to the routed client go with it.
-
The on-chain channel is removed
It was frozen on 11 October 2026, when the payment path moved onto Lightning, and nothing new was built on it after that. Once tickets ran end to end and the lottery was built, it was taken out of the tree, later in October 2026: tickets and the lottery do its job on Lightning, and the channel carried the open defects that were left. With it went its provider and its client, the wallet's channel rail, the light client that watched the chain for it, the fair exchange built on its states (Paying only for what checks out), the flow in which a paid call waited for the owner's approval (A wallet for agents), and their tests, vectors and scripts. The code stays in the history, last at commit 1ad0c48. The two Python reference repositories still hold the channel.
-
What the removal leaves behind
Three things. A wallet that was upgraded with channels on record cannot close or refund them with this version: it leaves their records and sealed keys untouched and says which revision settles them. The wallet pays sellers over Lightning only; its Umbrel and StartOS packages have since been redone to use the box's Lightning node (Packages). And the channel's one remaining case, a seller who cannot run a Lightning node, is given up: such a seller has no rail here, and pay with work is the other way in. Nobody has reviewed the removal.
-
What the channel did that tickets do not
It settled each piece exactly, it left nothing in flight when a buyer stopped, and its seller needed no Lightning node. Tickets give those three up, as What it gives and what it costs says. What they bring is Lightning's routing in place of a hub, and no transaction on the chain for each buyer and seller.
-
-

An earlier draft of this paper had a section, "Beside Lightning", which argued that Lightning could not hold a buyer's coins under a lock for the length of a session. Hold invoices do that, for a ticket at a time. That section no longer describes Lightning Stream.

- -

16Prior art

-

Nothing in a ticket is a new mechanism. It is the hold invoice Lightning nodes already have [5], used to the end that "stuckless payments" were proposed for in 2019 [6], and bound to HTTP 402 and to an agent's spending policy. The numbers in square brackets point to References. The policy wallet is the part we think is most useful.

-
-
L402
Lightning Labs' HTTP 402 binding [23]: a macaroon plus a Lightning invoice. Used for metered services it becomes a prepaid balance at the seller. A seller that collects each ticket on arrival, before it is used, is running exactly that in ticket-sized units, and a seller whose node has no hold invoices can do so.
-
Keysend streaming
Podcast apps stream sats for each minute listened, usually as one spontaneous Lightning payment a minute [8][9]. That is a payment per piece: it suits a service where a wait of a tenth of a second or more per piece does not matter. AMP [7] is the other spontaneous payment Lightning has; in neither does the payer hold anything back, so neither is a ticket.
-
x402
The HTTP payment standard whose shape Lightning Stream uses [22]. Its batch-settlement scheme, where the client commits at request time and value settles later, is the name the earlier channel was carried under before it was removed. The ticket and lottery entries are our own, and the upstream clients do not speak them.
-
Nostr Wallet Connect
NIP-47 [25] gives each app its own connection to a wallet, which the owner can limit or revoke, and wallets that speak it put spending budgets on those connections. The policy wallet applies the same idea to agents, with an owner-signed policy.
-
Routstr and Cashu
Inference paid for request by request with Cashu ecash [27][28]. Payments are instant and private, but the mint holds the money. A locked ticket is held by nobody: it sits in Lightning channels until the buyer releases it or it returns.
-
Ark
One operator serving many recipients off chain [29], the shape the retired hub had. Users can exit on chain alone at any time before their coins expire, and must come back before then to refresh them. Lightning Stream now has no operator of its own.
-
-

Paying by lottery

-

Paying small amounts by lottery is an old idea, and none of it is ours. David Wheeler proposed "transactions using bets" in 1996 [33], and Ronald Rivest described "Electronic Lottery Tickets as Micropayments" in 1997 [34], with a bank that honours the winning tickets; Rivest's paper names still earlier forms of the idea. Silvio Micali and Rivest removed the back-and-forth in 2002 [35]. Rafael Pass and abhi shelat put an escrow on a chain in the bank's place in 2015 [36], in one form with no third party and in two with a third party whose conduct anyone can check. Orchid [39] and Livepeer [40] run such lotteries with a contract that holds the payer's deposit and pays a winner without the payer's help. Chiesa and others added privacy and defined a transfer that succeeds with a set probability [37], which Mitani and Otsuka built for payment hubs [38]. For Bitcoin itself the idea was raised by Mike Caldwell in 2012 [41], sketched inside Lightning channels by Tadge Dryja in 2016 [42], and built from specially made keys by Oleksandr Kurbatov in 2025 [43]. Lightning has neither a bank nor such a contract, and that is why the plain form here leaves the seller exposed by about one win. The plain form adds nothing to these but the binding to a request and to an owner's policy.

-

In May 2026 Paul Gerhart, Jay Taylor and Sri Aravinda Krishnan Thyagarajan published "Probabilistic Atomic Swaps for Bitcoin and Friends" (arXiv:2605.04975) [44], which builds an exchange that completes with a set probability and enforces itself, runs it between two test networks, and shows it over Lightning with a prototype of two nodes. The aim of a win that enforces itself off the chain is theirs first, and so is the proof that ties a hash lock to a key, which we measured after them. As we read their paper, each of their rolls is a small paid exchange of its own, where ours keeps one payment locked and lets the roll ride on a request the buyer sends anyway; theirs is built from adaptor signatures and an oblivious pseudorandom function, where ours uses oblivious transfer; and theirs comes with a formal treatment, where the check ours depends on is our own argument and has not been reviewed. Where the two differ, theirs is the one that has been set down properly.

-

Where tickets sit

-

Tickets sit between a prepaid balance and a payment per piece. A prepaid balance hands the seller the money before the service. A payment per piece hands it over piece by piece and makes each piece wait. A ticket commits the money before the service and hands it over a ticket at a time, inside the request.

-
- - - - - - - - - - -
Prepaid balance (L402 with credit)Stream ticketsA Lightning payment per piece
Wait per requestNone once the balance is paid.None waits for a Lightning payment: a released ticket's balance pays the requests. The seller's check of a secret took 0.93 ms.110 ms on a direct channel, 210 ms through one routing node (median).
The buyer can loseThe whole balance.One ticket.One piece.
Money tied upThe balance, which is already the seller's.The unused tickets, until cancelled or expired.None.
Routing fee, one hop, default policyOne fee per top-up.1 sat per collected ticket: 0.1% at 1,000 sat.1 sat per piece: more than 1% for a piece under 100 sat.
Load on routing nodesAn ordinary payment.Held payments, a slot each, unpaid if cancelled.Many ordinary payments.
The seller's node needsAny Lightning node.Hold invoices: an lnd-family node today.Any Lightning node.
-
-

The timings and fees in this table were measured on a three-node regtest lab, one hop. A seller's 402 can list more than one of the three.

- -

17Numbers

-

The first table was measured on a three-node regtest lab, one hop: a buyer, one routing node and a seller, all running Lightning Fork v0.21.3-beta-blake2b.17 [61] with default settings, in the regtest lab its author publishes (lightning-fork-lab at commit a5cadc5, on a Bitcoin Knots 29.4.1 BLAKE2b regtest [60]), on one machine, with two channels of 5,000,000 sat. The nodes were driven by scripts, not by the wallet, and all traffic was on loopback, so no figure includes real network latency. A script in the public tree, scripts/ln_ticket_regtest.sh, now reruns these cases on four nodes. Its figures differ a little from the ones below and are in the tree's docs/TICKETS.md.

-
- - - - - - - - - - - - - - - - - -
QuestionMeasured on a three-node regtest lab, one hop
Does a stock Lightning Fork node accept tickets through a routing node?Yes, with no change to it. Collecting a ticket returned the buyer's own secret as the payment's proof.
Per request, on the sellerHash the secret and look up the ticket: 0.93 ms median. Collect: 3.5 ms. The buyer's node showed the payment complete 11 ms after the request arrived.
Time to lock tickets of 1,000 sat1 ticket: 0.27 s. 10: 0.59 s. 100: 3.0 s. About 45 tickets a second after the first quarter second.
Smallest payment, and smallest held ticketThe smallest payment a node carried was 1 sat; a smaller one found no route. The smallest ticket the design holds is 546 sat, by the dust rule in the next table.
Routing fee1 sat plus one part per million for each collected ticket, per hop, at the default policy. Nothing for a cancelled ticket: with 10 locked and 5 collected the buyer paid 5,005 sat and the seller received 5,000.
How many at once, between Lightning Fork nodes483 in one channel, the most the protocol allows and Lightning Fork's default. Of 520 offered at once, 483 were accepted and 37 failed cleanly on the buyer's node. A channel with a Core Lightning node at either end carries 30; see the next table.
Cost of many tickets in a channelEach ticket above the dust limit (354 sat on these Lightning Fork nodes) adds an output to the channel's commitment transaction. The fee its opener would pay on a force close rose from 285 sat with no tickets to 21,304 sat with 483, at 1 sat/vB.
How long a ticket can be heldA ticket's life must be more than 24 blocks: 20 was refused and 30 accepted. The seller's Lightning Fork node cancels a held ticket 18 blocks before its expiry. With a life of 40: locked at height 159, expiry at 202, cancelled at 184.
A restart with 4 tickets lockedSeller, routing node and buyer in turn: each was back in 1 to 1.5 s with its tickets still locked. Two were then collected and two cancelled, correctly.
A routing node that is downThe seller's collect returned in 4 ms and its invoice read settled. The buyer's node showed the payment complete as soon as the routing node was back.
A seller that neither collects nor cancelsIts node cancelled the tickets 25 blocks after the lock (40-block tickets). Every channel stayed open.
A seller that goes offline with tickets lockedThe routing node force-closed its channel to the seller 43 blocks after the lock. The buyer's money came back 8 blocks later, 51 blocks in all. The buyer's own channel stayed open.
For comparison: one Lightning payment per pieceDirect channel: 110 ms median. Through the routing node: 210 ms median, with a fee of 1,001 msat on 1,000 sat.
-
-

Not measured: more than one hop; real network latency; the fees and routes of mainnet; tickets on a direct channel with no routing node; a force close with hundreds of tickets in the channel (in this lab it was run with 3); and a seller claiming a ticket on the chain because the routing node stayed down. The four-node script has since run a force close with 100 tickets, which is the figure in the table below. The demo has since paid tickets through two routing nodes.

- -

With Core Lightning: slots and dust

-

These come from a later run, on 12 October 2026, on regtest, on one machine, in the same lab: three Lightning Fork nodes of the version above and three nodes of the Core Lightning fork [63] at its release v26.06.9-blake2b.7, the released binaries. Two of the Core Lightning nodes were started with the values that binary has by default on mainnet (30 slots among them), because on regtest the same binary defaults to 483; the third kept 483, for the dust cap. The channels were of 5,000,000 sat, one of 2,000,000, all of the anchor type. A Core Lightning seller held tickets through a small plugin of our own. The driver of this run is not in the public tree, so treat the figures as our own claim; the tree's docs/TICKETS.md, section 11, has them too.

-
- - - - - - - - - - - - - - - - - -
QuestionResult
40 tickets of 1,000 sat to a Core Lightning seller on one channel30 locked and 10 failed. The buyer's node reported its balance as short, though its side of the channel had 3,998,056 sat.
An ordinary payment of 5,000 sat over that channel while the 30 were heldFailed the same way. Left free to choose a route, it went round through another node for a fee of 1,005 msat.
40 more tickets, the buyer free to choose a routeAll 40 locked, over two more of the seller's channels. The seller then held 70 tickets on three channels, two of them full.
40 tickets through a Core Lightning routing node30 locked and 10 failed.
Two buyers through one Core Lightning routing node to one sellerThe first held 20. The second offered 20: 10 locked and 10 found no route.
A Core Lightning node as the buyer's nodeIt paid a Lightning Fork seller's ticket through one routing node for a fee of 1,001 msat, and the proof it got back was its own secret. At its own limit its node names the cause: "Too many HTLCs".
Time to lock 1, 8 and 30 tickets through one routing node, invoices made firstTo a Lightning Fork seller: 0.21 s, 0.28 to 0.29 s, 0.56 to 0.64 s. To a Core Lightning seller: 0.22 s, 0.25 to 0.31 s, 0.54 to 0.57 s.
Which held tickets have an output on the chainOn a Lightning Fork node, those of 354 sat and above. With tickets of 400, 600 and 1,000 sat held, a Core Lightning node's own force close had outputs for 600 and 1,000 only: its limit is 546 sat.
Core Lightning's cap on dust in one channel, on a channel it opened with 483 slotsTickets of 500 sat: 100 locked (50,000 sat) and 30 failed. Tickets of 546 sat: 130 of 130 locked.
The next ticket to that seller after a refusal at the capA 1,000 sat ticket found no route: the buyer's node had stopped trying that seller.
Lightning Fork's cap on dustNot reached: 483 tickets of 300 sat locked, 144,900 sat below the dust limit.
200 payments of 64 sat on a 30-slot channel, nothing heldSent 64 at a time: 61 succeeded and 139 failed, in 3.0 s. Sent 8 at a time: all 200 succeeded in 7.1 s, 28 a second.
A Core Lightning seller that neither collects nor cancels (40-block tickets, direct channel)Nothing cancelled the tickets. At their expiry height the buyer's node began to force-close its own channel to the seller, and the close was in the chain 3 blocks later.
-
-

Not measured here: what XBT's nodes on mainnet are set to (an operator can raise Core Lightning's 30 or lower Lightning Fork's 483), the channel types in use there and the fee rates; channels without anchors, where the dust limit also rises with the fee rate (computed under Fee rates, not run); two or more Core Lightning routing nodes in a row; and the two published hold plugins beyond a first try of one and a reading of the other. Who bears the loss of a ticket below the dust limit in a force close is reasoned from the protocol's rule, not run.

- -

The lottery as built

-

These come from a run on 13 October 2026 of scripts/lottery_regtest.sh, which is in the public tree and makes 30 checks. It ran on a regtest lab, our own nodes: the wallet's signer, its tool server and the gateway as the tree builds them, an ordinary file server, and three Lightning Fork nodes of the version above (a buyer, one routing node, a seller) on one machine, on loopback. The buyer's channel and the seller's inbound channel were opened with 30 slots. There was no Core Lightning node. The settings were the ones the wallet and the gateway ship with, with pieces of 64 KiB. These are one run's figures, and a roll is random, so the wins differ from run to run.

-
- - - - - - - - - - - - - - - - - - - - -
QuestionMeasured on a regtest lab, our own nodes
A 100 MB file at a quarter of a sat a piece (1,526 pieces, 381.5 sat), bought five times by an agent's one call to the walletWhole each time, in 1.2 to 2.3 s. 8, 12, 6, 4 and 5 wins, where 6 were expected each time: 520, 780, 390, 260 and 325 sat paid, fees included.
What the buyer's node paid, what the seller's node received, and what the wallet booked2,240,000 msat on both nodes: 35 wins of 64,000 msat, each paid once. The wallet's ledger: 2,275 sat, each win and its fee of 1 sat.
A win, from the start of its payment to its end, one at a time221 ms median, 267 ms at the longest (35 payments, one routing node).
What was pending on the buyer's channel during the downloads, looked at every 20 msNothing in 47% of the looks, never more than 3 payments, and every one of them a win on its way. Nothing when the downloads were over, and nothing held on the seller's node.
A page priced at 2.5 sat a request, bought 200 timesOne roll each, 7 wins where 7.8 were expected. 3.0 ms a call, against 1.5 ms for a free page through the same wallet (medians).
20 sellers paid at once, three files of 64 one-sat pieces from each3,840 rolls, 68 wins where 60 were expected, every file whole, no payment failed, 4.8 s. At most 8 wins on the channel at once. An ordinary payment of 5,000 sat from someone else over the same channel went through meanwhile in 0.5 s.
100 sellers paid at once, the same19,200 rolls, 288 wins where 300 were expected, every file whole, no payment failed, 20 s: 14 wins a second. At most 8 wins on the channel at once; the ordinary payment went through in 0.5 s. A win was on its way for 0.44 s at the median and 1.2 s at the longest.
100 sellers paid at once on a busy machine: 16 busy loops beside the lab, on its 16 cores (other runs of the same day)With wins paid strictly in the order found, a seller cut a file short in 12 of 15 runs, each time with every win paid afterwards; on an idle machine, in none of 13. With the wallet paying first the wins a seller's answer stands still for: every file whole in 5 runs of 5.
A buyer that sends no halves of its ownServed 8 pieces. Then its answer was cut and its next request refused.
A buyer that rolls and never pays, pieces of a quarter of a satServed 1.4 wins' worth on average before it was stopped (ten sessions; 1.2 at the median, 3.3 at the most; 0.8 to 1.4 on average over four runs).
The same, pieces of a quarter of a win3.9 wins' worth on average (ten sessions; 3.9 to 4.9 over four runs): the gateway bears two unpaid wins and serves 8 pieces ahead of the buyer.
A second program for the roll, written separately, playing that buyerThe wins it worked out were exactly the seller's, in every session.
A seller that claims a win for a roll that lost, with a real invoiceRefused by the wallet's own working of the roll. Nothing paid, and the session ended.
A seller that sends, for a real win, an invoice that pays another node, or one for 1 sat moreRefused by the checks every invoice passes. Nothing paid, and the session ended after the third such invoice.
A seller that sends two invoices for every win64 wins, each paid once. None of the 64 second invoices was paid.
The wallet's signer, the gateway, the buyer's node and the seller's node, each killed between two calls and again in the middle of a downloadIn all eight cases: no win paid twice, nothing in the ledger that the node did not pay, nothing paid that is not in the ledger, and a later call was served.
-
-

Not measured for the built lottery: sellers on separate machines and nodes (the 100 sellers were 100 gateways beside one seller node); more than 100 sellers; more than one hop, and a direct channel with no routing node; real network latency and mainnet fees; a Core Lightning node; and anything on a small computer. When the buyer's node was killed in the middle of a download, one to three of its payments stayed marked as in flight on that node for good: the wallet keeps those wins booked as spent and does not pay them again, so the seller is not paid for them. The tree's docs/LIMITS.md states this and the other limits under "The lottery".

- -

The design's measurements: the lottery and many sellers

-

These are older than the table above, and were made before anything of the lottery was built. They come from three runs, all on regtest, on one machine, on loopback, with Lightning Fork nodes of the same version in the same lab. Tickets to many sellers and the pay-after-win lottery ran on five nodes: a buyer, one routing node and three seller nodes. Up to 200 seller sessions were spread over those three nodes, and a request and its answer were calls inside one program; every invoice, payment, lock, collect and cancel was a real call on a node. The win that pays itself ran on three nodes, with its roll in a prototype of our own. The scripts for these runs are not in the public tree, so treat the figures as our own claim. Rows marked simulated involved no node.

-
- - - - - - - - - - - - - - - - - -
QuestionResult
Tickets in flight from one channel, every channel with 483 slots400 tickets, 2 each to 200 seller sessions on three nodes, locked in 11.0 s. Offered 600 over two channels: all 600 locked, 483 on one and 117 on the other, in 9.2 s. This is what one Lightning Fork channel and its router accept, not a number of sellers a route carries. Within half of a 30-slot channel the figures are 7 sellers at 2 tickets each, or 15 at 1.
A new seller appears: until it holds a ticket248 ms median through one routing node (30 runs); 0.11 s over a direct channel.
One request that pays many sellersEvery seller's collect had returned after 28 ms for 10 sellers, 149 ms for 50 and 809 ms for 200. The buyer's node showed every payment complete after 0.2 s, 0.8 s and 2.9 s.
A force close with 100 tickets of 1,000 satThe routing node paid 4,635 sat in fee for the closing transaction and about 29,000 sat in all to get its funds back, at 1 sat/vB. With 3 tickets: 1,530 sat.
One roll, pay after a win2.3 millionths of a second for both sides together, in Python.
A win, until the seller is paid (pay after a win, one routing node)With 24 sellers at 400 pieces a second, odds of 1 in 640 and wins of 64 sat: 218 ms median, 255 ms at the longest, 30 wins. With 96 sellers and odds of 1 in 32: 284 ms median, 509 ms at the longest, 520 wins. Every payment succeeded.
Many sellers win in the same instantAll paid after 0.76 s for 24 sellers, 2.3 s for 100 and 4.6 s for 200.
Routing fee for a win1 sat for each routing node: 1.56% of a 64 sat win.
A buyer that never pays (simulated)It is served 1.00 win's worth before its first win on average, 2.98 one time in twenty.
One roll, a win that pays itself16 to 19 millionths of a second for each side and 197 to 581 bytes, for odds from 1 in 16 to 1 in 65,536 (a prototype in Rust, one processor core).
A buyer that offers rolls with no key in themCaught on 49.9%, 50.0% and 50.2% of 200,000 rolls at odds of 1 in 16, 64 and 1,024. No win got through.
A win that pays itself, on three nodesA 64 sat ticket locked through one routing node (209 ms), rolls at 1 in 64 until the seller won: the seller collected in 20 runs out of 20. This run was made before the dust rule; as designed now, that ticket is at least 546 sat. Its collect call took 2.4 ms and the buyer's node showed the payment complete 13 ms after the win. Paying the same win afterwards with an ordinary payment took 217 ms.
The proof that ties a ticket's lock to its rolls254 ms to make on one processor core, 1.35 ms to check, 192 bytes (a Groth16 proof [54] made with arkworks [57]).
+ -

Not measured in these design runs: sellers that are really separate machines; more than one hop; real network latency and mainnet fees; requests over HTTP, and a buyer that does not pay on real nodes (both are in the table of the built lottery above); anything on a small computer; the hardened form of one building block that the self-paying win needs, where the prototype uses the simple form; and a proof that needs no trusted setup.

-

18Status and limits

-
-
Works
On XBT's regtest: the agent wallet pays Lightning invoices and offers through a Lightning Fork node under the owner's policy. For tickets, also on regtest and against Lightning Fork nodes: the wallet's ticket book locks, releases and books tickets, and the seller's gateway sells an HTTP service to a test buyer for tickets. And the two together: the agent's pay tool buys a page and a 100 MB file from a stock web server behind the gateway, through a routing node, paying as the file arrives (scripts/ticket_e2e_regtest.sh). The lottery, in the form where the buyer pays after a win: the same pay tool buys the 100 MB file by rolls, and pays 100 sellers at once from one 30-slot channel (scripts/lottery_regtest.sh). The demo: a film behind the gateway, paid for piece by piece as a player reads it, through one routing node and through two (scripts/demo_film.sh; see A demo). The packages: a packaged wallet buying from a packaged gateway with tickets, in simulations of both platforms and on a real umbrelOS box with stand-ins for the node apps (Packages). Everything in this entry ran on regtest, between our own nodes, and all but the umbrelOS box on one machine.
-
Evidence anyone can check
The outside review pointed out that the measurements could not be checked by anyone outside the project. Three things have changed. Public CI builds the tree with its locked dependencies and runs its unit and integration tests on every push and pull request, on GitHub; those tests need no Lightning node, and the lab scripts are not part of it. It passed at the commit this draft describes, aaad6da. The reports the lab scripts wrote on their latest runs, on 14 October 2026, are in the tree's reports/ folder, as they were written: every check with what it saw. One of them has a failed check, published with it: in the wallet's end-to-end script the part that kills each process in turn timed out before it reached the seller's node. They are our own runs on one machine, and the figures on this page were mostly written from earlier runs of the same scripts, so a time or a lottery's wins differ between the two. And the tree has a guide for an outside tester, docs/TESTING.md, written from a first run from a fresh clone on a clean Ubuntu 24.04 machine, made as a stranger to the project would make it: the workspace's 707 tests passed, and so did every check of the three lab scripts the guide asks for (the wallet paying a gateway with tickets, 35 of 35; the lottery, 30 of 30; the film demo, 22 of 22). The Lightning lab scripts need Docker and python3 and fetch the rest themselves, so anyone can run them; the scripts for pay with work still need parts that are not published.
-
Lab-tested
The design of stream tickets, by scripts on three Lightning Fork nodes, and its slot and dust limits on six nodes, three of them the Core Lightning fork; see Numbers. Tickets to many sellers, and the win that pays itself, which ran as scripts and a prototype on three and five nodes. Nothing of tickets or of the lottery is in a release.
-
Reviewed
There has been no independent audit. Our internal review found three critical and five high-severity issues; we changed the code for each and added tests. A first outside review of the published code by Chris Guida (October 2026) then found more serious issues: in the agent wallet's budget accounting, the hub, the pay-with-work audit and the HTTP layer. Six rounds of fixes are in the public tree. Four follow-up audits of our own checked them: the first found 14 items (3 high), the second 20 (6 high), the third 23 (none high, 11 medium), the fourth 18 (none high, 9 medium). After the sixth round every finding is fixed or ends as a stated limit, and two items were open; a later run of the failure cases through the release binaries added three, of which the one an agent could be steered by is fixed. That left four open. Three were on the on-chain channel's path and left the tree with its code; the Python references, which keep the channel, still have one of them. One remains open, and it is not in this tree's code: it is on a rail of the Python reference wallet that is off by default. The channel was what most of the review's findings were about, and the findings on it and its stated limits left the tree with it. Neither removal, the hub's or the channel's, has been reviewed by anyone. The source tree's docs/LIMITS.md lists every limit, the open items and what nobody has reviewed. A Lightning developer who read the design pointed out both limits that the defaults are built around, the 30 slots and the dust limits; that was a reading of the design, not an audit of the code. Chris Guida then made a second review, in October 2026, of the ticket design, the lottery and the tree as they stood on 13 October: a static reading, in which nothing was built or run. He found the ticket mechanism and the lottery's roll sound as specified and as coded, and that much of what was said around them did not hold: "no change to the node" was true of lnd only; the losses were stated at regtest's fee rate and on anchor channels; held tickets are jamming by design, and a stranger could fill a seller's held places for free; the spec said two things about where a secret travels; the lottery's void path and its "exact price" needed bounds and a horizon; "regtest only" was a sentence, not a guard; and the evidence could not be checked from outside. This draft and the code answer each of those, as the sections above say. Nobody outside the project has reviewed those answers. Nobody has reviewed the argument that the win that pays itself rests on, and that form will not be built before a cryptographer has. Two reviews are still wanted, an audit of the code and a cryptographer's reading of that argument; neither has been arranged. Treat it all as unaudited software.
-
Retired and removed
The hub was retired on 11 October 2026 and its code removed. The on-chain channel was frozen that day and removed later in October 2026, with the light client that watched it, the fair exchange built on its states and the flow in which a paid call waited for a person's approval. The code is in the history, last at commit 1ad0c48. What ran on that channel is history too: on regtest it opened, paid, streamed, closed and refunded, and a Claude agent given only the wallet's tools bought an analytics API over it and refused a tampered chunk. None of that can be run with the tree as it is. See The earlier design.
-
Next
Mainnet, in small steps. The project's owner has decided on a small test on mainnet with amounts that can be lost entirely, once the software is ready for it: first one rehearsal between two of our own nodes with a small channel, then people outside the project, by invitation, with the packages. What a tester could lose is the balance of the channel the wallet pays from. It has not started: nothing of Lightning Stream has run on mainnet. Then signed service lists; see Built and not built.
-
Not yet
The win that pays itself. Fair exchange on tickets. A Core Lightning node as a seller: it needs a hold plugin that keeps the secret off the node, carries XBT's feature bit and cancels a ticket before it expires, and no published one does. A step where a paid call asks a person: ticket and lottery payments are bounded by the task's budget and do not ask one. XBT mainnet: regtest only so far, and the mainnet test above has not started. An independent audit. A published specification. Packages that start beside Lightning Fork on StartOS, and a wallet that pays sellers over Tor (Packages). A stock media app that pays, and a person watching a paid film on a screen; see A demo.
-
Trade-offs
Money moves a ticket at a time, and the buyer can lose one ticket. Unused tickets are locked until cancelled or expired. A held ticket takes a slot on every channel of its route, a channel has as few as 30 for everyone, and a held ticket is never under 546 sat: so held tickets suit one seller or a few, and many sellers are paid by lottery. At mainnet's fee rates, on channels without anchors, a 1,000 sat ticket can have no output at all, so on mainnet at the defaults nothing is held through a routing node. The seller needs an lnd-family Lightning node with inbound capacity, online while tickets are locked; a Core Lightning node cannot hold tickets today; a seller that cannot run one has no rail here but pay with work. Routing nodes hold tickets without a fee when they are cancelled. Paid by lottery, income and cost are uneven in the short run, and where the buyer pays after a win the seller goes first by about one win. The Lightning nodes on both sides hold hot keys for their channels. XBT's Lightning network is young and small, so a route may not exist.
-
- -

19References

-

Each of these was opened and read against what this paper says of it on 12 October 2026. Where we could only read an archived copy, or only part of a source, the entry says so.

-

Payment channels and Lightning

-
    -
  1. J. Spilman. "Anti DoS for tx replacement". bitcoin-development mailing list, 20 April 2013. archived copy.
  2. -
  3. P. Todd. "BIP 65: OP_CHECKLOCKTIMEVERIFY". 2014. Its section "Payment Channels" describes "Jeremy Spilman style payment channels". bip-0065.
  4. -
  5. J. Poon, T. Dryja. "The Bitcoin Lightning Network: Scalable Off-Chain Instant Payments". Draft 0.5.9.2, 14 January 2016. lightning.network.
  6. -
  7. Lightning Network developers. "BOLT: Basis of Lightning Technology". BOLT 2 (the peer protocol: the most pending payments a node may accept in a channel, 483, and the cap a node may put on dust), BOLT 3 (which pending payments get an output in a channel's transaction), BOLT 11 (invoices), BOLT 12 (offers; R. Russell, merged 2024). lightning/bolts.
  8. -
  9. J. Jager. "htlcswitch: hodl invoice". lnd pull request 2022, merged March 2019; released in lnd v0.6-beta, April 2019. The calls are AddHoldInvoice, SettleInvoice and CancelInvoice of lnd's invoices service. pull request, Optech: hold invoices.
  10. -
  11. H. Gondo. "Proposal for Stuckless Payment". lightning-dev mailing list, 25 June 2019. archived copy.
  12. -
  13. O. Osuntokun, with C. Fromknecht. "AMP: Atomic Multi-Path Payments over Lightning". lightning-dev mailing list, 6 February 2018. archived copy.
  14. -
  15. V. Wallace. "bLIP 3: Keysend". 2021. blip-0003.
  16. -
  17. Satoshis Stream. "bLIP 10: Podcasting 2.0 Streaming payments, Boosts and Boostagrams". 2022. blip-0010.
  18. -
  19. Bitcoin Optech. "Channel jamming attacks". Topic page. bitcoinops.org.
  20. -
  21. C. Shikhelman, S. Tikhomirov. "Unjamming Lightning: A Systematic Approach". Cryptology ePrint Archive 2022/1454, 2022. ePrint 2022/1454.
  22. -
  23. J. Jager. "Hold fee rates as DoS protection (channel spamming and jamming)". lightning-dev mailing list, 11 February 2021. archived copy.
  24. -
  25. C. Kirk-Cohen. "bLIP 4: Experimental Endorsement Signaling". 2024. blip-0004, Optech: HTLC endorsement.
  26. -
  27. Bitcoin Optech. "Point Time Locked Contracts (PTLCs)". Topic page. See also "Multi-Hop Locks from Scriptless Scripts", Blockstream Research. bitcoinops.org, multi-hop locks.
  28. -
  29. G. Malavolta, P. Moreno-Sanchez, C. Schneidewind, A. Kate, M. Maffei. "Anonymous Multi-Hop Locks for Blockchain Scalability and Interoperability". NDSS 2019. ePrint 2018/472.
  30. -
  31. A. Poelstra. "Scriptless Scripts". Slides, MIT Bitcoin Expo, 4 March 2017. slides.
  32. -
  33. L. Aumayr, O. Ersoy, A. Erwig, S. Faust, K. Hostakova, M. Maffei, P. Moreno-Sanchez, S. Riahi. "Generalized Channels from Limited Blockchain Scripts and Adaptor Signatures". Asiacrypt 2021. ePrint 2020/476.
  34. -
  35. Blockstream Research. libsecp256k1-zkp, module ecdsa_adaptor, which follows L. Fournier, "One-Time Verifiably Encrypted Signatures A.K.A. Adaptor Signatures". secp256k1-zkp. We read the module's header, which names Fournier's paper; we did not read the paper itself.
  36. -
  37. E. Heilman, L. AlShenibr, F. Baldimtsi, A. Scafuro, S. Goldberg. "TumbleBit: An Untrusted Bitcoin-Compatible Anonymous Payment Hub". NDSS 2017. ePrint 2016/575.
  38. -
  39. E. Tairi, P. Moreno-Sanchez, M. Maffei. "A2L: Anonymous Atomic Locks for Scalability in Payment Channel Hubs". IEEE Symposium on Security and Privacy 2021. ePrint 2019/589.
  40. -
-

HTTP, agents and other payment systems

-
    -
  1. R. Fielding and others. "Hypertext Transfer Protocol: HTTP/1.1". RFC 2068, January 1997, section 10.4.3: "402 Payment Required. This code is reserved for future use." It is still reserved in RFC 9110 (2022), section 15.5.3. RFC 2068, RFC 9110.
  2. -
  3. x402 Foundation. "x402", protocol version 2, with its schemes exact (and exact on Lightning, 2026), upto and batch-settlement. Created by Coinbase; since April 2026 kept by the x402 Foundation under the Linux Foundation. Apache-2.0. x402-foundation/x402, announcement.
  4. -
  5. Lightning Labs. "L402 Protocol Specification". lightninglabs/L402.
  6. -
  7. S. Warta, ligi, P. Gomes, A. Herzog. "CAIP-2: Blockchain ID Specification". 2019. With the bip122 namespace (Warta, ligi, Gomes), which follows M. Pontello, "BIP 122: URI scheme for Blockchain references / exploration". CAIP-2, bip122 namespace.
  8. -
  9. Nostr contributors. "NIP-47: Nostr Wallet Connect". 2023. NIP-47.
  10. -
  11. Anthropic. "Introducing the Model Context Protocol". 25 November 2024. Since December 2025 the protocol is kept by the Agentic AI Foundation, under the Linux Foundation. announcement, modelcontextprotocol.io.
  12. -
  13. Cashu contributors (calle and others). "Cashu NUTs", the Cashu protocol specifications; "NUT-24: HTTP 402 Payment Required". cashubtc/nuts, NUT-24.
  14. -
  15. Routstr. "routstr-core". Routstr/routstr-core.
  16. -
  17. Burak. "Ark: An Alternative Privacy-preserving Second Layer Solution". bitcoin-dev mailing list, 22 May 2023. For expiry and refresh as built: Second, "VTXO lifetime". archived copy, second.tech.
  18. -
  19. B. Cohen. "Incentives Build Robustness in BitTorrent". 22 May 2003. Section 3.3, "Optimistic Unchoking". bittorrent.org.
  20. -
  21. G. Maxwell. "Zero Knowledge Contingent Payment". Bitcoin Wiki, page created 28 November 2011. Bitcoin Wiki. The page names no author in its text; the author and date are from its history.
  22. -
  23. R. C. Merkle. "A Digital Signature Based on a Conventional Encryption Function". Crypto '87, Springer, 1988. doi:10.1007/3-540-48184-2_32.
  24. -
-

Paying by lottery

-
    -
  1. D. Wheeler. "Transactions Using Bets". Security Protocols, LNCS 1189, Springer, 1996. doi:10.1007/3-540-62494-5_7. We read its record and what Rivest and later authors say of it, not the paper itself.
  2. -
  3. R. L. Rivest. "Electronic Lottery Tickets as Micropayments". Financial Cryptography 1997. author's copy.
  4. -
  5. S. Micali, R. L. Rivest. "Micropayments Revisited". CT-RSA 2002. author's copy.
  6. -
  7. R. Pass, a. shelat. "Micropayments for Decentralized Currencies". ACM CCS 2015. ePrint 2016/332.
  8. -
  9. A. Chiesa, M. Green, J. Liu, P. Miao, I. Miers, P. Mishra. "Decentralized Anonymous Micropayments". Eurocrypt 2017. ePrint 2016/1033.
  10. -
  11. T. Mitani, A. Otsuka. "Anonymous probabilistic payment in payment hub". Cryptology ePrint Archive 2020/748, 2020 (a preprint). ePrint 2020/748.
  12. -
  13. J. S. Cannell, J. Sheek, J. Freeman, G. Hazel, J. Rodriguez-Mueller, E. Hou, B. J. Fox, S. Waterhouse. "Orchid: A Decentralized Network Routing Market". Version 2.0, 2019. whitepaper.
  14. -
  15. D. Petkanics, Y. Fu. "Livepeer Streamflow Paper". 2018. The contract is TicketBroker in the Livepeer protocol. Streamflow, contract.
  16. -
  17. M. Caldwell (casascius). "Sustainable nanopayment idea: Probabilistic Payments". Bitcoin Forum, 4 February 2012. bitcointalk.org.
  18. -
  19. T. Dryja. "LN as a Directed Graph: Single-Funded Channel Topology". Slides, 11 April 2016. slides.
  20. -
  21. O. Kurbatov. "Emulating OP_RAND in Bitcoin". arXiv:2501.16451, January 2025, and the Delving Bitcoin thread "Emulating OP_RAND". arXiv:2501.16451, thread, Optech: probabilistic payments.
  22. -
  23. P. Gerhart, J. Taylor, S. A. K. Thyagarajan. "Probabilistic Atomic Swaps for Bitcoin and Friends". arXiv:2605.04975, 6 May 2026. arXiv:2605.04975.
  24. -
  25. M. Rosenfeld. "Analysis of Bitcoin Pooled Mining Reward Systems". arXiv:1112.4980, 2011. arXiv:1112.4980.
  26. -
-

Building blocks of the sealed draw

-
    -
  1. T. Chou, C. Orlandi. "The Simplest Protocol for Oblivious Transfer". Latincrypt 2015. ePrint 2015/267.
  2. -
  3. Z. A. Genç, V. Iovino, A. Rial. "'The Simplest Protocol for Oblivious Transfer' Revisited". Information Processing Letters, 2020. It finds a flaw in the security proof of the protocol above. ePrint 2017/370.
  4. -
  5. Y. Ishai, J. Kilian, K. Nissim, E. Petrank. "Extending Oblivious Transfers Efficiently". Crypto 2003. doi:10.1007/978-3-540-45146-4_9.
  6. -
  7. M. Keller, E. Orsini, P. Scholl. "Actively Secure OT Extension with Optimal Overhead". Crypto 2015, revised 2022. The authors' 2022 note says the original proof does not hold and gives a repair that uses Roy's technique. ePrint 2015/546.
  8. -
  9. L. Roy. "SoftSpokenOT: Quieter OT Extension From Small-Field Silent VOLE in the Minicrypt Model". Crypto 2022. ePrint 2022/192.
  10. -
  11. N. Gilboa. "Two Party RSA Key Generation". Crypto '99. doi:10.1007/3-540-48405-1_8.
  12. -
  13. J. Doerner, Y. Kondi, E. Lee, a. shelat. "Secure Two-party Threshold ECDSA from ECDSA Assumptions". IEEE Symposium on Security and Privacy 2018. ePrint 2018/499.
  14. -
  15. J. Doerner, Y. Kondi, E. Lee, a. shelat. "Threshold ECDSA in Three Rounds". IEEE Symposium on Security and Privacy 2024. ePrint 2023/765.
  16. -
  17. J. Groth. "On the Size of Pairing-based Non-interactive Arguments". Eurocrypt 2016. ePrint 2016/260.
  18. -
  19. Electric Coin Company. "BLS12-381: New zk-SNARK Elliptic Curve Construction". 11 March 2017. blog post.
  20. -
  21. D.-E. Hopwood, S. Bowe, T. Hornby, N. Wilcox. "Zcash Protocol Specification". Section 5.4.9.3, "Jubjub". zips.z.cash. Read from an archived copy of 21 September 2026; the address given did not answer us.
  22. -
  23. arkworks contributors. ark-groth16, ark-bls12-381 and ark-ed-on-bls12-381, Rust libraries. MIT or Apache-2.0. arkworks-rs.
  24. -
  25. M. Campanelli, R. Gennaro, S. Goldfeder, L. Nizzardo. "Zero-Knowledge Contingent Payments Revisited: Attacks and Payments for Services". ACM CCS 2017. ePrint 2017/566.
  26. -
  27. G. Fuchsbauer. "Subversion-zero-knowledge SNARKs". PKC 2018. ePrint 2017/587.
  28. -
-

Software this work runs on

-
    -
  1. Bitcoin Knots, maintained by Luke Dashjr. Release 29.4.1 (September 2026) carries the BLAKE2b proof of work (L. Dashjr) and the unified opt-in signature hash (K. Santiago; specified in the tree's doc/unified-sighash.md), activated at block 961,640 together with the reduced-data rules of BIP 110 (D. Ohm). MIT. bitcoinknots/bitcoin, unified-sighash.md.
  2. -
  3. Lightning Fork, by Paul Lamb: lnd for the BLAKE2b chain. Measured here at tag v0.21.3-beta-blake2b.17 (commit cebc10fe), in the regtest lab of the same author, lightning-fork-lab, at commit a5cadc5. Lightning Fork is MIT; the lab carries no licence file. paulscode/lightning-fork, paulscode/lightning-fork-lab.
  4. -
  5. lnd, the Lightning Network Daemon, by Lightning Labs and the Lightning Network developers. MIT. lightningnetwork/lnd.
  6. -
  7. The Core Lightning fork for the BLAKE2b chain, by PrivKey, built on Core Lightning (R. Russell, Blockstream, and contributors). Measured here at release v26.06.9-blake2b.7 (commit 482c8c52), from the released binaries, as buyer, routing node and seller. Its documentation at that tag (doc/lightningd-config.5.md) gives the default of 30 pending payments in each direction of a channel. privkeyio/lightning, release, ElementsProject/lightning.
  8. -
  9. electrs, by Roman Zeyde. MIT. romanz/electrs.
  10. -
  11. libsecp256k1, by Pieter Wuille and the Bitcoin Core developers. MIT. bitcoin-core/secp256k1.
  12. -
  13. OCEAN. DATUM Gateway (Bitcoin Ocean, LLC, Jason Hughes and contributors; MIT), and J. Hughes, "TIDES: Transparent Index of Distinct Extended Shares", 2024. OCEAN-xyz/datum_gateway, TIDES.
  14. -
  15. Core Lightning documentation. "htlc_accepted", the plugin hook through which a plugin can fail an incoming payment, let it continue, or settle it with a secret. docs.corelightning.org.
  16. -
  17. Boltz. "hold", a hold invoice plugin for Core Lightning. MIT. Tried at v0.3.3. BoltzExchange/hold. We loaded it on the fork and asked it for one invoice, which lacked the XBT feature bit, so a Lightning Fork node refused to pay it; we tried nothing more.
  18. -
  19. daywalker90. "holdinvoice", a hold invoice plugin for Core Lightning. MIT. Read at v4.0.0. daywalker90/holdinvoice. Not run by us. By its README it settles an invoice by its hash, so the secret is the seller's; the repository is archived and points to the plugin above.
  20. +

    10References

    +

    The works cited on this page, numbered as in the full list, which also says how each was read.

    +
      +
    1. J. Poon, T. Dryja. "The Bitcoin Lightning Network: Scalable Off-Chain Instant Payments". Draft 0.5.9.2, 14 January 2016. lightning.network.
    2. +
    3. J. Jager. "htlcswitch: hodl invoice". lnd pull request 2022, merged March 2019; released in lnd v0.6-beta, April 2019. The calls are AddHoldInvoice, SettleInvoice and CancelInvoice of lnd's invoices service. pull request, Optech: hold invoices.
    4. +
    5. H. Gondo. "Proposal for Stuckless Payment". lightning-dev mailing list, 25 June 2019. archived copy.
    6. +
    7. V. Wallace. "bLIP 3: Keysend". 2021. blip-0003.
    8. +
    9. Satoshis Stream. "bLIP 10: Podcasting 2.0 Streaming payments, Boosts and Boostagrams". 2022. blip-0010.
    10. +
    11. Bitcoin Optech. "Channel jamming attacks". Topic page. bitcoinops.org.
    12. +
    13. x402 Foundation. "x402", protocol version 2, with its schemes exact (and exact on Lightning, 2026), upto and batch-settlement. Created by Coinbase; since April 2026 kept by the x402 Foundation under the Linux Foundation. Apache-2.0. x402-foundation/x402, announcement.
    14. +
    15. Lightning Labs. "L402 Protocol Specification". lightninglabs/L402.
    16. +
    17. Nostr contributors. "NIP-47: Nostr Wallet Connect". 2023. NIP-47.
    18. +
    19. Anthropic. "Introducing the Model Context Protocol". 25 November 2024. Since December 2025 the protocol is kept by the Agentic AI Foundation, under the Linux Foundation. announcement, modelcontextprotocol.io.
    20. +
    21. Cashu contributors (calle and others). "Cashu NUTs", the Cashu protocol specifications; "NUT-24: HTTP 402 Payment Required". cashubtc/nuts, NUT-24.
    22. +
    23. D. Wheeler. "Transactions Using Bets". Security Protocols, LNCS 1189, Springer, 1996. doi:10.1007/3-540-62494-5_7. We read its record and what Rivest and later authors say of it, not the paper itself.
    24. +
    25. R. L. Rivest. "Electronic Lottery Tickets as Micropayments". Financial Cryptography 1997. author's copy.
    26. +
    27. S. Micali, R. L. Rivest. "Micropayments Revisited". CT-RSA 2002. author's copy.
    28. +
    29. R. Pass, a. shelat. "Micropayments for Decentralized Currencies". ACM CCS 2015. ePrint 2016/332.
    30. +
    31. J. S. Cannell, J. Sheek, J. Freeman, G. Hazel, J. Rodriguez-Mueller, E. Hou, B. J. Fox, S. Waterhouse. "Orchid: A Decentralized Network Routing Market". Version 2.0, 2019. whitepaper.
    32. +
    33. D. Petkanics, Y. Fu. "Livepeer Streamflow Paper". 2018. The contract is TicketBroker in the Livepeer protocol. Streamflow, contract.
    34. +
    35. M. Caldwell (casascius). "Sustainable nanopayment idea: Probabilistic Payments". Bitcoin Forum, 4 February 2012. bitcointalk.org.
    36. +
    37. T. Dryja. "LN as a Directed Graph: Single-Funded Channel Topology". Slides, 11 April 2016. slides.
    38. +
    39. O. Kurbatov. "Emulating OP_RAND in Bitcoin". arXiv:2501.16451, January 2025, and the Delving Bitcoin thread "Emulating OP_RAND". arXiv:2501.16451, thread, Optech: probabilistic payments.
    40. +
    41. P. Gerhart, J. Taylor, S. A. K. Thyagarajan. "Probabilistic Atomic Swaps for Bitcoin and Friends". arXiv:2605.04975, 6 May 2026. arXiv:2605.04975.
    42. +
    43. Bitcoin Knots, maintained by Luke Dashjr. Release 29.4.1 (September 2026) carries the BLAKE2b proof of work (L. Dashjr) and the unified opt-in signature hash (K. Santiago; specified in the tree's doc/unified-sighash.md), activated at block 961,640 together with the reduced-data rules of BIP 110 (D. Ohm). MIT. bitcoinknots/bitcoin, unified-sighash.md.
    44. +
    45. Lightning Fork, by Paul Lamb: lnd for the BLAKE2b chain. Measured here at tag v0.21.3-beta-blake2b.17 (commit cebc10fe), in the regtest lab of the same author, lightning-fork-lab, at commit a5cadc5. Lightning Fork is MIT; the lab carries no licence file. paulscode/lightning-fork, paulscode/lightning-fork-lab.
    46. +
    47. lnd, the Lightning Network Daemon, by Lightning Labs and the Lightning Network developers. MIT. lightningnetwork/lnd.
    48. +
    49. The Core Lightning fork for the BLAKE2b chain, by PrivKey, built on Core Lightning (R. Russell, Blockstream, and contributors). Measured here at release v26.06.9-blake2b.7 (commit 482c8c52), from the released binaries, as buyer, routing node and seller. Its documentation at that tag (doc/lightningd-config.5.md) gives the default of 30 pending payments in each direction of a channel. privkeyio/lightning, release, ElementsProject/lightning.
    50. +
    51. electrs, by Roman Zeyde. MIT. romanz/electrs.
    52. +
    53. libsecp256k1, by Pieter Wuille and the Bitcoin Core developers. MIT. bitcoin-core/secp256k1.
    54. +
    55. OCEAN. DATUM Gateway (Bitcoin Ocean, LLC, Jason Hughes and contributors; MIT), and J. Hughes, "TIDES: Transparent Index of Distinct Extended Shares", 2024. OCEAN-xyz/datum_gateway, TIDES.
    -

    20Acknowledgements

    +

    11Acknowledgements

    Lightning Stream is a small addition to a great deal of other people's work, and the credit for that work is theirs.

    XBT is Bitcoin on BLAKE2b proof of work, and it runs on Bitcoin Knots [60], maintained by Luke Dashjr, who wrote the BLAKE2b proof of work; the unified signature hash that keeps a payment from being replayed on the SHA-256 chain is Kyle Santiago's. Lightning on XBT exists because of Paul Lamb's Lightning Fork [61] and the Core Lightning fork by PrivKey [63], which stand on lnd by Lightning Labs [62] and on Core Lightning. Every measurement in this paper was made in the regtest lab that Lightning Fork's author publishes: most on Lightning Fork nodes alone, and the slot and dust measurements with the released binaries of the Core Lightning fork beside them. The light client of the removed channel talked to electrs by Roman Zeyde [64], all signing runs in libsecp256k1 [65], and pay with work is built around OCEAN's DATUM and TIDES [66]. The demo's media server is Jellyfin, as its project ships it, and its film is Big Buck Bunny, (c) 2008 Blender Foundation, www.bigbuckbunny.org, under Creative Commons Attribution 3.0. The source tree's THIRD_PARTY_NOTICES.md lists every library it links, with its licence.

    The ideas are older than the software. One-way channels are Jeremy Spilman's, Lightning is Joseph Poon's and Tadge Dryja's, hold invoices are Joost Jager's, and a payment the payer releases in a second step is Hiroki Gondo's. Paying by lottery is David Wheeler's and Ronald Rivest's, and a win that enforces itself over Lightning is Paul Gerhart's, Jay Taylor's and Sri Aravinda Krishnan Thyagarajan's. The HTTP shape is x402's, and the agent's tools are spoken in the Model Context Protocol.

    -

    Chris Guida read the earlier design and its code in October 2026 and found what we had missed. Moving onto Lightning follows from his review. He then read the ticket design, the lottery and the tree a second time, and most of what is new in this draft follows from that second review: the narrower claim about which nodes need no change, the costs at real fee rates and the floor that follows, the prepaid first ticket for strangers, the bounds on the lottery and its horizon, the guard against mainnet by omission, and evidence that can be checked from outside. The credit for both is his. The mistakes that remain are ours.

    -

    Kyle Santiago read the design and pointed out both limits that this draft is built around: the 30 pending payments a Core Lightning channel carries, and the dust limits. The defaults changed because of that reading.

    +

    Chris Guida read the earlier design and its code in October 2026 and found what we had missed. Moving onto Lightning follows from his review. He then read the ticket design, the lottery and the tree a second time, and most of what was new in Draft 9 follows from that second review: the narrower claim about which nodes need no change, the costs at real fee rates and the floor that follows, the prepaid first ticket for strangers, the bounds on the lottery and its horizon, the guard against mainnet by omission, and evidence that can be checked from outside. The credit for both is his. The mistakes that remain are ours.

    +

    Kyle Santiago read the design and pointed out both limits that the defaults are built around: the 30 pending payments a Core Lightning channel carries, and the dust limits. The defaults changed because of that reading.

    This page is set in IBM Plex (IBM) and Newsreader (Production Type), both under the SIL Open Font License.

    In one sentence. Lock a few small Lightning payments, release one with every request, take back the rest: a buyer can pay across the Lightning network for anything that arrives over time, and can lose no more than one ticket.

    -
+