cashubtc / nuts Goto Github PK
View Code? Open in Web Editor NEWCashu protocol specifications
License: MIT License
Cashu protocol specifications
License: MIT License
NUT-05: Specify the error returned by the mint to the wallet if the Lightning payment fails.
I am working on a Java implementation of the protocol (wallet and mint), and have the following question:
When swapping proof P1 for proofs P2 and P3, is it acceptable to delete P1 from the wallet database after a successful swap, similar to the process during the melting operation?
NUT-03 does not provide guidance on this matter, and it seems that cashu-ts
will not delete, but always check the spendable status of a proof with the mint before selecting it... (?)
https://github.com/cashubtc/cashu-ts/blob/4bb76a432f0b01589f95fa370ec5e0d78d0e70ae/src/CashuWallet.ts#L84
Deleting locally "feels" safe, but I thought I should ask first...
Thoughts?
Thank you.
NUT-11 says:
The recipient who owns the private key of the public key
Secret.data
can spend this proof by providing a signature on the serializedProof.secret
string that is then added toProof.witness.signatures
We use
libsecp256k1
's serialized 64 byte Schnorr signatures on the SHA256 hash of the message to sign.
However, in the examples, the pubkey specified in the Secret.data
field is a 33-byte compressed key. The schnorr signature verification function of libsecp256k1
, as with any BIP340 implementation in general, requires a 32-byte x-only public key.
I suggest either:
P2PK
Secret.data
field02
byte)I would like to add a token spent state check using Y
(BlindedMessage
) instead of the secret
. That way, someone other than the owner of a token can check the state of a token (if they know Y
) without being able to spend it directly.
This could be added as an additional optional field in PostCheckStateRequest
to the /v1checkstate
endpoint or as a new endpoint altogether. I tend towards the former option but I'm open for other preferences.
In the former case, PostCheckStateRequest
would become
{
"secrets": [
<secret_str>,
...
],
"Ys": [
<Y_hex_str>,
...
]
}
In that case, there would have to be a rule that states that either "secrets" OR "Ys" has to be populated for the request.
In such a case sent proofs will get spent by mint without the wallet receiving change + new proofs.
This is a generalization of the issue minibits-cash/minibits_wallet#28 that is worth discussion what could be a recovery path and if the protocol can plan for that. This situation will reappear in production because of network / device sudden unavailability during split operation.
Mint should announce https / Tor addresses in the info response at which it is reachable from.
The spec should include test vectors for generating a keyset and deriving the keyset ID. A small MAX_ORDER
would be fine to illustrate the concept.
The exact structure of secrets is currently left to the wallets to implement and there is no default value recommended in any NUT. Because not all client libraries build their secrets the same way, a mint can, in theory, eventually learn to fingerprint given libraries that produce certain tokens, lowering the anonymity set for those users.
It might make sense to either:
a. recommend in one of the NUTs that client libraries use a common secret structure
b. enforce a secret size in the protocol for "simple/raw" secrets (not the secrets defined in NUT 10)
Opening this issue for discussion on these ideas.
Right now when a wallet requests keys, the mint returns keys for denominations of satoshis. I'd like to be able to have a mint that can issue both satoshi tokens and, for example, "USD cent" tokens.
One way to do this would be to have different mints for each token kind, and wallets would just have to keep track of which mint issues which kind of token. But there are some use cases when you might want many different kinds of tokens (for example, if you want the mint to back up some kind of trading market).
There may be a way to do this with the bitcoin scripting functionality, but since it is not documented, I'm not sure.
Today I published a first-draft of an idea for discreet log contract integration for Chaumian Ecash mints.
https://conduition.io/cryptography/ecash-dlc/ [Pull request link]
Before I go to the trouble of writing up a NUT submission, is this even the right place for such an idea? Or would DLCs be outside the scope of Cashu?
Naturally I don't think DLC support should be mandatory for any cashu implementation. But DLCs could be a highly desirable feature for ECash... something which might incentivize non ecash users to take the plunge. DLCs could offer a sort of programmable functionality on top of Ecash, outside of simple unconditional payments, without adding much complexity to the mint itself.
For /melt
, P2PK only checks the inputs but does not require a signature on the outputs of the transaction (which is the quote to be paid and possibly the change outputs). This could be achieved by requiring a signature on the quote ID.
H/t @supertestnet
Tried clicking on LNbits and looks like it leads to an empty page
{
"proofs": Proofs,
"outputs": BlindedMessages,
"amount": int //deprecate
}
the amount field is not necessary, since it introduces unwanted constraints.
The client has to manage split amounts (send, return) , but the mint does not need to. The mint only needs to perform split according to the clients request.
I believe that there should be a gpg encryption scheme added to the cashu/nuts protocol to always ensure that
NUT-05/NUT-06: Split tokens: Melting tokens go to the correct person.
Here's how a MITA would play out:
This is highly theoretical, but if the melt request is an unencrypted channel, then it's possible.
I would add a GPP encryption step before sending it off to the server, and then a decryption step upon receiving the request by the server before processing.
Encryption ensures no one can perform this attack as it would require the GPG keys of the server
This is only upon melting/splitting (since they are similar), anything sent by the server doesn't require extra encryption due to the blinded signature scheme used
After speaking with @ngutech21 over a dev call last week, I decided to open an issue to discuss the value of the links to the libraries that implement the NUTs in the README.
My thinking is the following: links to individual libraries that implement the cashu protocol are important, but belong elsewhere than the spec (main website? awesome list? other places?). Here are a few reasons why I think over time it gets harder and harder to keep those in sync, and how they somehow complicate the commit history of the spec repo without reason.
Now I think the readme should point to locations where developers would be able to find that sort of information, but that could be just a new section with some meta links, or maybe just a sentence like You can find a list of libraries that implement the various NUTs in this spec at [this link] and [this link].
Anyway just a thought as the spec matures.
NUT 00 references NUT 01:
"unit is the currency unit of the token keysets (see Keysets for supported units)"
But, there is nothing in NUT 01 that I see that mentions supported units.
We need to have standard units along with standard token denominations so that wallets can transmit the correct amount of value.
I propose adding the following to NUT 01:
The following shows supported units and their corresponding token values.
Unit | Token Value |
---|---|
'sat' | 1 sat |
'usd' | 0.001 cents |
Mints wind down and it would be great to provide for this in the most orderly way possible. I therefore suggest to add an expiration timestamp to tokens which would force wallets to rotate tokens from time to time at which the mint can reject issuing new tokens, informing the user of the need to swap funds out.
Running but more so shutting down a mint is probably a legal nightmare. At which point may the operator legally use remaining unclaimed funds? With expiration at the protocol level this could be made very explicit.
I used to tip waiters with paper wallets but always printed on these paper wallets that I reserve the right to reclaim these coins after a year as I didn't want to get sued many years later about those lost riches. Similarly I would set my mint to put a one-year expiry on those tokens to be able to wind it down within one year. Wallets could auto-rotate tokens every month or three.
I am having trouble with the proof serialization in NUT-11, I do not think the example proof JSON in the NUT is valid. The '
should be replaced with a "
and the witness field is missing {}
.
{
"amount":8,
"secret":"[\"P2PK\", {\"nonce\": \"5d11913ee0f92fefdc82a6764fd2457a\", \"data\": \"026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198\",}]",
"C":"02250a37a56b78e66674f7f063e6abd3d9345f8761fb90cac0293108910a8c27a3",
"id":"1cCNIAZ2X/w1",
"witness":[
{
"signatures":[
"c43d0090be59340a6364dc1340876211f2173d6a21c391115adf097adb6ea0a3ddbe7fd81b4677281decc77be09c0359faa77416025130e487f8b9169eb0c609"
]
}
]
}
Lines 31 to 45 in aefec2e
How can I send tokens in smaller units, like 1.234 sats?
When I input a float amount, the website https://wallet.cashu.me/ shows a 500 error. Does Cashu support float numbers?
Or support millisatoshi
After some preliminary discussion on the Telegram channel, I wanted to open the discussion here and formally propose the cashu_wallet_spec
file be removed from the repository. I see a few reasons for this:
35:
Alice
generatesN
random secret stringsx
by generating128
random bits and encoding thembase64
for each requested token.
78:secret
is the secret message (no encoding standard)
I think that there isn't anything in that file that is not already in the NUTs, and it can therefore be safely removed, but careful review should be done before removing it in case it adds something that current implementations abide by but that is not defined in any given NUT.
There might also still be interesting/meaningful clarifications in that file that the NUTs could use. It's probably a good idea to make sure that the information gets integrated in the NUTs if need be rather than simply removed from the repo.
After reading all the spec files, I see a few sections that emerge from all NUTs and could make them easier to parse if used more consistently.
Initially, I thought of them roughly like so: Motivation, Overview, Specification, and Examples.
But after a few days I thought of taking a look a the BIPs to see if any patterns emerged. It turns out a lot of the BIPs (at least a lot of the good ones) over the past 5+ years have used a fairly standard pattern (if it's defined anywhere I don't know where, and it appears people have just agreed to use a common pattern? In any case it works great). Edit: it's defined here. The pattern in question roughly has the following, almost mandatory sections:
With the following, more optional sections:
In general, I assume being flexible with the structure is a good approach, because there might be many reasons why a certain spec might not fit the standard structure. But providing some sort of baseline looks to me like a good next step in the development of the Cashu specification.
I see a few reasons why standardizing the structure might help the Cashu project:
Is there a way to check which bitcoin/asset network the mint is running on before trying to mint/melt? The info isn't contained in the ecash token so for a wallet running multiple mint connections it'd be nice to be able determine which network it's on so when I'm melting an ecash token I know what network to get the invoice on.
Currently when i try on most mints I just get a failure method back with an error message for wrong network then I have to parse that out and retry from a different wallet, but I'd like to be able to hit mint info to determine this before generating the invoice at all:
Currently, calling POST /melt
is blocking until either the Lightning invoice succeeds or fails. This is not necessary anymore because we now have a new pending
state in the POST /check
response (see here: #21).
POST /melt
should have an option to immediately return. I'm unsure what the best way would be to spec this out.
Input is very much appreciated.
Options:
POST /melt?blocking=false
with a URL paramPostMeltRequest
with optional blocking: false
field in jsonPOST /melt/async
respond-async
I notice that the default mint for the Python cashu implementation currently returns the following keyset:
{"1":"03ba786a2c0745f8c30e490288acd7a72dd53d65afd292ddefa326a4a3fa14c566","2":"03361cd8bd1329fea797a6add1cf1990ffcf2270ceb9fc81eeee0e8e9c1bd0cdf5","4":"036e378bcf78738ddf68859293c69778035740e41138ab183c94f8fee7572214c7","8":"03909d73beaf28edfb283dbeb8da321afd40651e8902fcf5454ecc7d69788626c0","16":"028a36f0e6638ea7466665fe174d958212723019ec08f9ce6898d897f88e68aa5d","32":"03a97a40e146adee2687ac60c2ba2586a90f970de92a9d0e6cae5a4b9965f54612","64":"03ce86f0c197aab181ddba0cfc5c5576e11dfd5164d9f3d4a3fc3ffbbf2e069664","128":"0284f2c06d938a6f78794814c687560a0aabab19fe5e6f30ede38e113b132a3cb9","256":"03b99f475b68e5b4c0ba809cdecaae64eade2d9787aa123206f91cd61f76c01459","512":"03d4db82ea19a44d35274de51f78af0a710925fe7d9e03620b84e3e9976e3ac2eb","1024":"031fbd4ba801870871d46cf62228a1b748905ebc07d3b210daf48de229e683f2dc","2048":"0276cedb9a3b160db6a158ad4e468d2437f021293204b3cd4bf6247970d8aff54b","4096":"02fc6b89b403ee9eb8a7ed457cd3973638080d6e04ca8af7307c965c166b555ea2","8192":"0320265583e916d3a305f0d2687fcf2cd4e3cd03a16ea8261fda309c3ec5721e21","16384":"036e41de58fdff3cb1d8d713f48c63bc61fa3b3e1631495a444d178363c0d2ed50","32768":"0365438f613f19696264300b069d1dad93f0c60a37536b72a8ab7c7366a5ee6c04","65536":"02408426cfb6fc86341bac79624ba8708a4376b2d92debdf4134813f866eb57a8d","131072":"031063e9f11c94dc778c473e968966eac0e70b7145213fbaff5f7a007e71c65f41","262144":"02f2a3e808f9cd168ec71b7f328258d0c1dda250659c1aced14c7f5cf05aab4328","524288":"038ac10de9f1ff9395903bb73077e94dbf91e9ef98fd77d9a2debc5f74c575bc86","1048576":"0203eaee4db749b0fc7c49870d082024b2c31d889f9bc3b32473d4f1dfa3625788","2097152":"033cdb9d36e1e82ae652b7b6a08e0204569ec7ff9ebf85d80a02786dc7fe00b04c","4194304":"02c8b73f4e3a470ae05e5f2fe39984d41e9f6ae7be9f3b09c9ac31292e403ac512","8388608":"025bbe0cfce8a1f4fbd7f3a0d4a09cb6badd73ef61829dc827aa8a98c270bc25b0","16777216":"037eec3d1651a30a90182d9287a5c51386fe35d4a96839cf7969c6e2a03db1fc21","33554432":"03280576b81a04e6abd7197f305506476f5751356b7643988495ca5c3e14e5c262","67108864":"03268bfb05be1dbb33ab6e7e00e438373ca2c9b9abc018fdb452d0e1a0935e10d3","134217728":"02573b68784ceba9617bbcc7c9487836d296aa7c628c3199173a841e7a19798020","268435456":"0234076b6e70f7fbf755d2227ecc8d8169d662518ee3a1401f729e2a12ccb2b276","536870912":"03015bd88961e2a466a2163bd4248d1d2b42c7c58a157e594785e7eb34d880efc9","1073741824":"02c9b076d08f9020ebee49ac8ba2610b404d4e553a4f800150ceb539e9421aaeee","2147483648":"034d592f4c366afddc919a509600af81b489a03caf4f7517c2b3f4f2b558f9a41a","4294967296":"037c09ecb66da082981e4cbdb1ac65c0eb631fc75d85bed13efb2c6364148879b5","8589934592":"02b4ebb0dda3b9ad83b39e2e31024b777cc0ac205a96b9a6cfab3edea2912ed1b3","17179869184":"026cc4dacdced45e63f6e4f62edbc5779ccd802e7fabb82d5123db879b636176e9","34359738368":"02b2cee01b7d8e90180254459b8f09bbea9aad34c3a2fd98c85517ecfc9805af75","68719476736":"037a0c0d564540fc574b8bfa0253cca987b75466e44b295ed59f6f8bd41aace754","137438953472":"021df6585cae9b9ca431318a713fd73dbb76b3ef5667957e8633bca8aaa7214fb6","274877906944":"02b8f53dde126f8c85fa5bb6061c0be5aca90984ce9b902966941caf963648d53a","549755813888":"029cc8af2840d59f1d8761779b2496623c82c64be8e15f9ab577c657c6dd453785","1099511627776":"03e446fdb84fad492ff3a25fc1046fb9a93a5b262ebcd0151caa442ea28959a38a","2199023255552":"02d6b25bd4ab599dd0818c55f75702fde603c93f259222001246569018842d3258","4398046511104":"03397b522bb4e156ec3952d3f048e5a986c20a00718e5e52cd5718466bf494156a","8796093022208":"02d1fb9e78262b5d7d74028073075b80bb5ab281edcfc3191061962c1346340f1e","17592186044416":"030d3f2ad7a4ca115712ff7f140434f802b19a4c9b2dd1c76f3e8e80c05c6a9310","35184372088832":"03e325b691f292e1dfb151c3fb7cad440b225795583c32e24e10635a80e4221c06","70368744177664":"03bee8f64d88de3dee21d61f89efa32933da51152ddbd67466bef815e9f93f8fd1","140737488355328":"0327244c9019a4892e1f04ba3bf95fe43b327479e2d57c25979446cc508cd379ed","281474976710656":"02fb58522cd662f2f8b042f8161caae6e45de98283f74d4e99f19b0ea85e08a56d","562949953421312":"02adde4b466a9d7e59386b6a701a39717c53f30c4810613c1b55e6b6da43b7bc9a","1125899906842624":"038eeda11f78ce05c774f30e393cda075192b890d68590813ff46362548528dca9","2251799813685248":"02ec13e0058b196db80f7079d329333b330dc30c000dbdd7397cbbc5a37a664c4f","4503599627370496":"02d2d162db63675bd04f7d56df04508840f41e2ad87312a3c93041b494efe80a73","9007199254740992":"0356969d6aef2bb40121dbd07c68b6102339f4ea8e674a9008bb69506795998f49","18014398509481984":"02f4e667567ebb9f4e6e180a4113bb071c48855f657766bb5e9c776a880335d1d6","36028797018963968":"0385b4fe35e41703d7a657d957c67bb536629de57b7e6ee6fe2130728ef0fc90b0","72057594037927936":"02b2bc1968a6fddbcc78fb9903940524824b5f5bed329c6ad48a19b56068c144fd","144115188075855872":"02e0dbb24f1d288a693e8a49bc14264d1276be16972131520cf9e055ae92fba19a","288230376151711744":"03efe75c106f931a525dc2d653ebedddc413a2c7d8cb9da410893ae7d2fa7d19cc","576460752303423488":"02c7ec2bd9508a7fc03f73c7565dc600b30fd86f3d305f8f139c45c404a52d958a","1152921504606846976":"035a6679c6b25e68ff4e29d1c7ef87f21e0a8fc574f6a08c1aa45ff352c1d59f06","2305843009213693952":"033cdc225962c052d485f7cfbf55a5b2367d200fe1fe4373a347deb4cc99e9a099","4611686018427387904":"024a4b806cf413d14b294719090a9da36ba75209c7657135ad09bc65328fba9e6f","9223372036854775808":"0377a6fe114e291a8d8e991627c38001c8305b23b9e98b1c7b1893f5cd0dda6cad"}
The last 13 keys in that keyset are for amounts that are more than there can ever be satoshis (210000000000000000
):
2100000000000000
2251799813685248
4503599627370496
9007199254740992
18014398509481984
36028797018963968
72057594037927936
144115188075855872
288230376151711744
576460752303423488
1152921504606846976
2305843009213693952
4611686018427387904
9223372036854775808
At the same time, the spec does not put a hard cap on the amounts that mints can support. I'm wondering if this is a design choice. If so, I have not seen it explained (would be good to add it somewhere maybe?). If not, I wonder if there might be value in "capping" the highest amounts in the spec, in order to provide certainty for typed languages in the range of possible numbers a wallet/library can expect to see (for example the keyset shown here cannot fit into a Long
/i64
, and requires an unsigned long ULong
/u64
. But that doesn't really ensure a library will never encounter a mint that has a keyset that goes higher, and therefore libraries have to preemptively account for that uncertainty.
I see NUT-02 addresses this in part by stating:
MAX_ORDER
refers to the order of the maximum token value that the mint supports, i.e.,2^MAX_ORDER
. Typically,MAX_ORDER = 64
.
Is there a reason to have it go any higher? If not, might I suggest the spec state that here, MAX_ORDER
cannot go higher than 64?
Hi, first let me thank all the folks working on Cashu. The more I think and dig into it, the more inspirational it looks.
I recently started working on a mobile wallet with the aim of exploring the design space to make eCash work in a more comprehensible way for the average user accustomed to their bank's mobile app. The goal is to enable seamless payments and receipt of funds without the need to copy tokens, add payment request formats, deep links, or QR codes, etc. I'm close to having an MVP wallet ready and would appreciate some explanations/opinions on a few Cashu-related concepts:
Is there a strong need for the current token format that supports encoding tokens issued by multiple mints at once?
Reasoning: At first glance, it's not an intuitive concept and it makes reasoning, design, and implementation of sensitive code more complex. As far as I'm aware, current wallets only send single mint tokens. However, to comply with the specification, the wallet needs to be ready to accept tokens from multiple mints. It's similar to a payment funded from multiple banks/accounts at once, which is easily solved by a sequence of transactions. If there is a longer-term strategy underlying this, please explain.
The above issue manifests itself in the Cashu-ts library where there's a situation where a single CashuWallet class instance is constructed with a single mint URL but then implements the receive function from multiple mints. If anyone knows of any plans on how this implementation will conceptually evolve, I would gladly structure my code in that direction.
Naming conventions: I understand that the protocol is new and not finished, but I've been confused many times about how many different things are called a "token" in the specification, documentation, and the code itself. It ranges from encoded serialized tokens to proof collections indexed by mints and the proofs themselves. Would it be possible to propose concise naming conventions? The TypeScript types in Cashu-ts are perhaps the clearest ones.
I understand that it is very difficult to change widely implemented protocols later, even in networks without proof of work. However, every time I dig through those V3 token hierarchies (Token, Token.token, TokenEntry, Proof), the idea comes to my mind to add the damn mintUrl to the proof, attach a memo to the list of proofs to be sent, and forget about them once and for all. All critical code would then work on a simple array of flat objects. :)
The last conceptual point is a fundamental naming convention - how should Cashu tokens be represented in the wallet? The current standard is to represent them as "sats" (as they are hopefully backed by real sats within the mint). However, this raises two questions: Is it not misleading? Would it be more transparent to adopt a convention similar to stablecoins that transparently communicate they are not the same as what they are backed with? As a follow-up question, should we not consider making the protocol ready to issue tokens backed by something else that is digitally transferable (ideally, but not necessarily only through Lightning)? Stablecoins might be a good candidate.
Thanks to everybody reading this and for all your opinions.
MV
The standard Base64 encoding of the keyset ID makes no mention of URL safety. This is already an issue for basic requests back to the server for a specific keyset, with the API endpoint of the form /keys/{id}
.
The Feni server is already doing implicit conversions of received IDs:
keysetId = strings.ReplaceAll(strings.ReplaceAll(keysetId, "_", "/"), "-", "+")
GET https://8333.space:3338/keysets
{"keysets":["L3zxxRB/I8uE","I2yN+iRYfkzT"]}
Naive request URL assembly:
GET https://8333.space:3338/keys/L3zxxRB/I8uE
{"detail":"Not Found"}
URL-safe Base64 encoding (with knowledge of the server substitution code above):
GET https://8333.space:3338/keys/L3zxxRB_I8uE
{"code":0,"error":"keyset does not exist"}
Standard URL encoding:
GET https://8333.space:3338/keys/L3zxxRB%2FI8uE
{"detail":"Not Found"}
The least disruptive solution would be to specify the URL Safe encoding from RFC 3548, which is the implicit behavior of the Feni server already.
The two previous IDs from the example above would change to
{"keysets":["L3zxxRB_I8uE","I2yN-iRYfkzT"]}
Right now, this is undocumented and unspecified. See cashubtc/nutshell#52
I'm opening this question/issue with its corresponding answer for discoverability, in case others come across this aspect of the implementation and wonder why it works.
While looking at the hash_to_curve()
function and its corresponding tests, I noticed that the function will keep searching for a point until it finds one that has an even y-coordinate (that is, the compressed form of the public key will always start with a 0x02
byte). Intuitively this felt like cutting in half the number of possible chosen points on the curve, effectively cutting the security of the curve in half. I was puzzled.
In turns out Chat-GPT4 had a great answer for this, and I just thought I'd post it here for others to find/refer to in case I'm not the only one who was puzzled by this.
If I grabbed random points on the secp256k1 curve by using random x-coordinates but in the end only always picked points with "even" y-coordinates and an attacker knew this, doesn't that effectively reduce the security of the curve in half because this attacker would know I always pick only from the one half of the pool of points on this curve?
In the context of secp256k1, as used in Bitcoin, the "even" or "odd" distinction of the y-coordinate is actually not where the cryptographic security comes from. Instead, the security comes from the private key, which is a randomly selected number from a large range (specifically, between 1 and slightly less than 2^256). The public key is then computed by multiplying this private key by the "generator point" of the secp256k1 curve.
The resulting public key is a point on the curve. If we're using compressed form for the public key, the y-coordinate is only represented as its parity (even or odd) along with the full x-coordinate. This is simply a way to reduce the amount of data that needs to be stored or transmitted.
Even though it may seem that choosing the "even" y-coordinate every time would reduce the number of possible public keys in half, it doesn't reduce the security of the private key. The private key is still a secret random number, and the best known attacks involve guessing or otherwise obtaining this private key. Even if an attacker knows that your public key y-coordinate is always even, they still can't compute your private key from your public key without solving the elliptic curve discrete logarithm problem (ECDLP), which is considered computationally infeasible with current technology.
So, to answer your question, while choosing always the "even" y-coordinate does reduce the number of possible public keys, it doesn't reduce the security of the system, which is based on the infeasibility of deriving the private key from the public key.
In order for users to be sure that their local clock agrees with the mint's clock, the mint should publish its current time in the info response.
Formula for determining number of blank outputs necessary to imprint fee reserves.
Problem: n_blank_outputs = ceil(log2(fee_reserve))
can be 0
if fee_reserve==1 sat
.
Solution: Should be max(ceil(log2(fee_reserve)), 1)
or ceil(log2(fee_reserve)) || 1
.
There have been multiple requests to be able to control the memo
of an invoice. The availability of this option could depend on the backend used.
NUT-04 should have an optional memo
field that a mint can can choose to honor (if their Lightning backend supports setting it).
If I paid the invoice and mint some token, but Bob refuses to pay or does not respond to the request, is there a mechanism I can get my BTC back?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.