Skip to content

Instantly share code, notes, and snippets.

@thunderbiscuit
Last active February 18, 2024 18:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thunderbiscuit/08ee8638fe66412ce0494646903f0b0b to your computer and use it in GitHub Desktop.
Save thunderbiscuit/08ee8638fe66412ce0494646903f0b0b to your computer and use it in GitHub Desktop.
Cashu

I've been looking into the fountain codes and UR spec for Cashu token transmission over QR codes. I wanted to get a feel for how big in bytes was likely to be a typical payment, and I decided to run some statistics on the number of proofs you need for given payments. The results are interesting so I'm sharing them here.

Here is the distribution of the number of proofs you'll need for a random sample of 10,000 payment amounts between 1 and 1,000,000 satoshis (a payment of 0 to $500 at today's prices).

number-of-proofs

I was surprised at how a lot of payments can be done with less than 10 proofs, even on pretty big amounts (this makes sense when you think about it but for some reason I had expected a lot more proofs required). Moreover, since the number of proofs required is so nicely distributed, it occurred to me that a simple search "around" a given payment amount that required too many proofs would likely find an amount that requires less proofs.

Here is the distribution of the number of proofs you'll need for 10,000 random payment amounts if, every time you have a payment amount that requires 11 or more proofs you instead search for a local minimum by overpaying your amount by up to 16 satoshis (basically a rounding error).

max10

This is interesting: just over 92% of payments can be made with 10 proofs or less if you are willing to overpay by 16 satoshis. If you're willing to overpay by more, it quickly becomes almost all payments that can be done with 10 or less proofs. This can inform how we attempt to optimize for QR code transmission (or at least tell us what we're dealing with).

On Token Size

Tokens V3 are mostly comprised of proofs with a bit of metadata (mint url, unit, memo). A single proof is a data structure a little over 81 bytes long (amount (8 bytes), id (8 bytes), secret (32 bytes), C (33 bytes) plus the fields' names). Using CBOR encoding, we can fit proofs into a little under 100 bytes, and together with the metadata, we can think of a 5-proof token as being 500 bytes.

Note that the above is only if we encode the tokens using CBOR, which is much smaller than the base64 we have in the spec; the tokens grow about 50% in size if you use our normal base64 encoding.

On QR Codes

QR codes come in 40 Versions (densities), each carrying more data but harder to parse for the QR code reader, depending on the quality of the camera capturing the code as well as lightning conditions and how long the QR code is shown for if you do fountain codes, as well as other factors. I have not done a ton of practical tests on this so I don't know how complex you can make the codes and still get fountain codes to be read reliably. But here are some rough ideas:

For standard bitcoin addresses, you can easily fit them into Version 7 QR codes. Here is a slightly denser Version 10 (57x57 "modules"—dots—which can carry just about 100 bytes of data depending on the encoding) QR code:

image

Not bad, and probably easy to read quickly for most modern hardware. Here is a Version 20 (97x97):

image

This is getting harder to read (I think? just from rough testing), and my fairly high quality phone is not always picking it up super quickly depending on the size of the screen displaying it. I'm not sure there is value in even considering bigger QR codes. Easy to produce, but probably very unreliable to read (quickly) on standard hardware (maybe not? Need to test more). The above means that if we think of most payments as 5-10 proofs payments, and each proof is about 100 bytes, and each Version 10 QR code can carry 100 bytes, we should be able to make just about any payment under $500 with 10 QR codes' worth of data depending on the error correction level one might aim for. Using Fountain Codes, you can expect this to be transmitted in 10-16 codes, somewhere around 1-3 seconds depending on the delay between QR codes.

Things that might impact this is scanning bigger displays, which could make scanning Versions say 15-20 QR codes practical, in which case you might only need 2-3 QR codes and where the scan will be very much sub-second.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment