Thread

Zero-JS Hypermedia Browser

Relays: 5
Replies: 27
Generated: 20:12:26
I've been thinking of 'Cashu Channels', as they might be useful in nostr:npub1zzt0d0s2f4lsanpd7nkjep5r79p7ljq7aw37eek64hf0ef6v0mxqgwljrv to be very efficient in transferring tiny amounts of cashu at an extremely high volume. We want the device and the router to be able to update their mutual balance - without trust - and without needing any communication with the mint. The mint is involved in setting up the Cashu Channel and in closing the channel a few hours later; but the mint is not needed during the millions of tiny cashu-balance-updates in between. In Lighting, after two parties have set up a channel and their funding transaction is confirmed in the blockchain, the two parties can move balance over and back in their channel with zero communication with any third party; they simply sign updated commitment transactions and revocations. In nostr:npub1zzt0d0s2f4lsanpd7nkjep5r79p7ljq7aw37eek64hf0ef6v0mxqgwljrv , this could be useful as the device needs to send tiny amounts to the router at very high volume. In our Tollgate use case, we may want to support billions of such transactions and we want zero communication with the mint during this time. This isn't possible in Cashu today, but I feel like it could be supported with the right NUTs. Let's simplify by having all transfers in one direction, from A (my phone) to B (the Tollgate router). Initially, with the cooperation of the mint, A "locks up" some of their cashu in a special 2-of-2 multisig token that can be spent with the cooperation of A and B, and which reverts to A after a suitable delay (a few days?). Now the 'Cashu channel' is active and they don't need to talk to the mint any more. Each time A wants to transfer a tiny amount of Bitcoin to B, A signs a updated 'commitment' transaction: "Of the original 50,000 sats in the 2-of-2 multisig, A agrees that 2,315 of those sats can be redeemed unilaterally by B. Signed, A" Instead of immediately redeeming though, B just continues providing service to A and A continually updates the balance and signs the updated commitment transaction, adding a few (milli)sats each time. Finally, to 'close the channel', B can take the latest signed 'commitment transaction' and get a few sats from the mint, and A is seperately able to approach the mint for the remainder of the sats. I've been trying to squeeze this into the exiting Cashu protocol, where a Cashu 'proof' could be sent over and back an arbitrary amount of times with something like Lightning's revocations, but I can't see how to make it work trustlessly.
2025-10-13 22:04:04 from 1 relay(s) 5 replies ↓
Login to reply

Replies (27)

nostr:nprofile1qqsdmup6e2z6mcpeue6z6kl08he49hcen5xnrc3tnpvw0mdgtjemh0spr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5qy28wumn8ghj7un9d3shjtnwdaehgu3wvfnszyrhwden5te0dehhxarj9ekxzmnymrwrzm, this reminds me of your idea with the proofs that are locked to a recipient with an expiry so that they can be recovered if un-used. What would it take to make a minimal demo of this?
2025-10-14 06:35:17 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
I don't think you need a channel just locked tokens to the tollgate public key, along side your public key for recovery and a timeout. you keep the tokens in your reserve and send them as you need. What ever tokens you don't send just need to wait for the timeout for you yo take them back. you can also do that with HTLCs but I think that is over complicating it in this case.
2025-10-14 07:35:19 from 1 relay(s) ↑ Parent 3 replies ↓ Reply
I'd like to avoid a scenario where the mint is required to create a large number (millions?) of small (millisat) tokens or proofs That's why I'm curious to learn about other approaches, which will likely need to be a bit more complex, to make this work with just a small number of proofs I think we need the ability for the device to say something like "the router can have the tokens worth 32 sat, 8 sat, 1 sat, and 32 millisat", but where the router can delay the redemption until the device disconnects a few minutes/hours later And we might need some sort of revocation login, where the device can "unlock" a different - likely overlapping - set of proofs while the router revokes its right to the first set
2025-10-14 07:41:26 from 1 relay(s) ↑ Parent Reply
True the word channel can be misleading. I think nostr:nprofile1qqsp9msr6ytgfgf9mkrmapuu9qvsg9d78ua3ajntfmt580t5llvgpesppemhxue69uhkummn9ekx7mp0qyghwumn8ghj7mn0wd68ytnvv9hxgtcpr4mhxue69uhkummnw3ezucnfw33k76twv4ezuum0vd5kzmp0efx0jg had something along the lines of what you described in mind (no HTLCs)...
2025-10-14 08:12:30 from 1 relay(s) ↑ Parent Reply
I like that the tokens stay on the client side until they are spent in what you described here. this way the client doesn't need to race the vendor to redeem un-spent proofs. I think earlier versions of this idea involved over-payment with time locks and trust-less recovery of un-spent proofs, but those solutions were more focused on cash back rather than reducing traffic to the mint...
2025-10-14 08:17:59 from 1 relay(s) ↑ Parent Reply
I don't want a situation where the mint needs to create millions of milli-sat tokens in advance. I'd prefer to build a smaller set of tokens (1 millisat, 2 millisats, 4 millisats, 8 millisats, ... 1024 millisats ) in order that millions of different combinations are possible with only a small number of tokens. At one moment in time, three of those tokens (1+2+4 = 7 millisats) "belong" to the router. Next, to move the balance up to 8, we need a way to send the 8 millisat token to the router, *where the router somehow revokes its access to the 1,2,4 -millisat tokens*. That's the challenge; the device gives access to a subset of the tokens, where the router can later 'revoke' its access (like in Lightning) in return for an updated - more valuable - set of accesses
2025-10-14 08:31:27 from 1 relay(s) ↑ Parent Reply
very cool idea, haven't seen anyone think about this yet. generally, unidirectional channels make everything a lot easier. here is how it might work with the current protocol: - user A wants to open a channel to tollgate B with 1000 sats capacity - user A obtains B's public key - user A mints a 1000 sat coin with 2-of-2 multisig and SIG_ALL signature flag that requires signatures from and B also on the outputs - outputs are the BlindedMessage's that are created when this coin (input) is swapped with the mint - thus, the outputs determine the channel state (distribution of funds), so to make payments, we need to update the outputs and sign them again - to open the channel, the initial state is A=1000 and B=0 (sats), A signs both, the input (the coin itself) and two outputs (the enforced distribution) and sends all this to B. - B signs the input+outputs as well. now B could close the channel. - to make a 10 sat payment, A creates new outputs A=990 and B=10 and signs them, sends them over to B. now B can enforce the new state. - when they're both done with the channel, B can close the channel with the latest state (the one where she gets most). some notes: - after closing the channel, B should be nice enough send A her remaining channel balance after /v1/swap'ing them and receiving new BlindSignature's. B can't use these BlindSignature, only A can unblind them. if she isn't nice, A would have to /v1/restore the BlindSignature's. - B should never send back her signatures to A, otherwise A might close the channel with an earlier state. - to allow A to close the channel uncooperatively (in case B stops operating for example), the initial coin can have a second "refund" spend path with a time lock which also determine the channel's maximum lifetime. I just sketched this out after reading your post, so there might issues or better ways of doing this. you can checkout spillman channels, they are much simpler than the lightning channels we're using today. but I think the idea above here is pretty close to how they work.
2025-10-14 08:57:44 from 1 relay(s) ↑ Parent 3 replies ↓ Reply
Why not just omit the mints and try something like this: A Lightning-inspired multisig pool protocol allowing N participants to collaborate in a pooled channel, locking funds in an N-of-N multisig. Each participant deposits a standardized amount (or variable, with careful balance tracking). Off-chain transfers use collective signing of updated pool balances, enforced by Bitcoin script and advanced cryptographic privacy (e.g., blinded signatures or zero-knowledge proofs to unlink payers and recipients). Withdrawals trigger on-chain collaborative signatures, preserving privacy and enabling flexible outputs. Dispute resolution leverages timeout or penalty transactions, similar to Lightning, but extended for multi-party exit. This model offers native privacy, pooled liquidity, and pure P2P scaling without gatekeepers and custodians, advancing the Lightning and CoinJoin concepts into a native Bitcoin P2P pool.
2025-10-14 09:50:00 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
> locking funds in an N-of-N multisig you mean an on-chain multisig? I'm not against that exactly, but it's getting further away from Cashu Also, your proposal kinda sounds like the Ark Protocol to me, although I don't know as much about about Ark as I would like. It seems to be generating a lot of interest and I want to know much more. I feel like the general idea of Cashu is to trust the mint for "settlement", instead of using the blockchain, partly because it's much faster than the chain.
2025-10-14 09:58:39 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
Sounds very elegant. Would love to have this happen under the hood in our cashu dependencies, so that we don't get rate-limited by the mints as much. Earlier spam mitigation strategies involved mints in the local network that are backed by global mints and don't keep their keysets as long as the global mints do. However, the "channel" based solution would vastly reduce the complexity for us if it just works..
2025-10-14 10:12:11 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
I'm only just this morning properly reading NUT-11 (P2PK). I didn't realise that it's possible to make a signature only to a specific combination of proofs; basically I kinda knew about SIG_INPUT in Cashu but not SIG_ALL. But I think I see now, also thanks to calle's message just above. (As I'm new to this, I'm just obsessing about the ideas that [I think] I understand, and therefore I'm likely misunderstanding a lot of what others have said in this thread) I might have another idea, which might be possible in current Cashu. Just thinking out loud: A and the mint prepare a set (a few dozen) of BlindSignatures with P2PK for a variety of denominations - large denominations (many sats) and small denominations (millisats). At any time, A can take a subset of those (e.g. 32 sat + 8 sat + 1 millisat) and sign the collection of those and give the signature to the router, giving the router unilateral exit to take the value in that set of proofs Later, A can update the balance by taking a set which has a larger total value (e.g. 32 sat + 16 sat + 1 millisat) and giving the updated signature to Bob It's important here that the new set has some overlap with the older set, in this case the 32 sat and the 1 millisat are in both the new transaction and the old one. This overlap ensures that the router can't exit with *both* sets; the mint will notice that the second signature is for a particular Proof that has already been spent Every time A creates a new set of proofs and signs that collection, A must ensure that this set has an overlap with every one of the previous sets that A has signed. This ensures that B can only redeem via one of the many signatures B has got from A. To satisfy the overlap constraint, maybe we could simply have a single 1-millisat proof that A includes in every set https://github.com/cashubtc/nuts/blob/main/11.md
2025-10-14 10:49:25 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
> you mean an on-chain multisig? I'm not against that exactly, but it's getting further away from Cashu Funds stay inside an on-chain N-of-N multisig pool and you get instant, Lightning-like balance updates among participants with a final on-chain exit. No single custodian; disputes resolve via multi-party mechanisms. This preserves Bitcoin-native security but requires sophisticated exit, dispute, and privacy design. > I feel like the general idea of Cashu is to trust the mint for "settlement", instead of using the blockchain, partly because it's much faster than the chain. in my limited understanding, adopting a Cashu mint-based settlement layer the off-chain settlement is accelerated by trusted mint attestations, but at the cost of introducing trust in the mint and potential liquidity constraints. In a Cashu-like arrangement, per-user liquidity is bound by the mint’s token liquidity and the ability to redeem; Lightning liquidity becomes a practical constraint because token minting/redemption must be backed by lightning liquidity so someone has to open the channels on chain anyhow. This can cap the effective throughput and affect routing of payments within the pool.
2025-10-14 11:01:13 from 1 relay(s) ↑ Parent Reply
Thanks for this detailed explanation. The double spend section helped me to understand how sig-all and the re-used proof work. It's beautifully simple 😀
2025-10-14 12:20:35 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
nostr:nprofile1qqsdxpfv503a2ga3ajqxw843hws9z7302ghpj4mcmjpa6qagmp9pwrspzamhxue69uhhyetvv9ujuurjd9kkzmpwdejhgtcg47gk0 I want my bitaxe to spend Spiel e-hash on internet access..
2025-10-14 13:30:28 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
Maybe this can be made bi-directional. To do so, we need a way to make older transactions revocable, just like in Lightning. In Lightning, a transaction is revoked by revealing a preimage, such that the preimage allows the honest party to take all the balance (I might be slightly oversimplifying there) The mint has functionality to check which tokens have been spent *and with which secret*, and that might be the mechanism we can use to ensure that the honest party sees what the dishonest person has done and that the honest party has sufficient data needed to get their money back
2025-10-14 14:30:51 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
I’m new to Cashu. But I feel like this could be much simpler. Here the mint is the rule enforcer, isn’t he? Could this work: A = user. B = service provider. 1. Say A locks 1000 sats with the mint for B using B’s pubkey as a 2/2 multisig (enforced by the mint). Let’s give a unique identifier for this lock. lock_21 2. The mint gives a receipt to A signed with their pubkey. This receipt contains the lock id, amount, B’s pubkey, timestamp and a future timestamp (valid until). 3. Now A sends this receipt to B when they first interact with each other. B can verify that the mint signed this receipt. And start providing services. 4. Everytime A wants to do a micro payment, A signs a message with lock id (lock_21), nonce and amount then sends it to B. 5. After many many txns, B goes to the mint, submits all the messages and claims the amount they’re supposed to receive from the locked tokens. A can then withdraw the remaining funds from the mint with B’s closure signature (happy ending) or after the locked funds expire. 6. B cannot be malicious here at all. A cannot be malicious here either as they cannot withdraw funds before the expiry of locked funds. Mints can offer this service for a fee maybe. Pls correct if this has some major loopholes 😅
2025-10-14 15:07:07 from 1 relay(s) ↑ Parent 2 replies ↓ Reply
Your idea looks like it will work, yes. But I think it would require support from the mints to add the necessary functionality. The other methods proposed here can work with existing mints (as long as they support P2PK) It might be possible, or even easy, to get mints to support your idea, so go for it!
2025-10-14 15:43:58 from 1 relay(s) ↑ Parent Reply
Sounds like it could work but the mint would know that a channel is being setup and it would have to track all that state as well (which should incur fees for the service). Our modus operandi is that the mint should know as little as possible about what's happening between users and that most complexity should be offloaded to clients to keep the mint simple and easy to run. It also decreased the anon set if the mint can differentiate the different usage patterns of users. My sketch above has only two interactions with the mint: open the channel (the mint doesn't know that this is a channel yet because it's blind-signing) and close it (at which point the mint knows it was a multisig coin with second spend path which is a timelock).
2025-10-14 17:45:50 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
Okay i didn’t realise your sketch didn’t require changes to the mint software. I was thinking about it more like UTXOs where each spend is a UTXO and the service provider can redeem these UTXOs. But it’s similar to what you guys have proposed. This would be great for Routstr by the way. We will be able to perform 100s of requests without being rate limited by the mints. One advantage the UTXO design would have is that the service provider wouldn’t need to interact with the mint to verify that the channel is opened (cuz mint’s pubkey signs the message) but i guess we can do this by adding it to the spec you guys have proposed.
2025-10-15 04:48:17 from 1 relay(s) ↑ Parent 1 replies ↓ Reply
you don't need to talk to the mint in my example either, just need to check the DLEQ proof to verify the coin
2025-10-15 08:40:46 from 1 relay(s) ↑ Parent Reply