Mark “Murch” Erhardt, Gustavo Flores Echaiz, and Mike Schmidt are joined by Rob Hamilton, PortlandHODL, Chandra Pratap, and fabohax to discuss Newsletter #416.

The Bitcoin Optech Podcast and transcription content is licensed Creative Commons CC BY-SA 2.0

Action items

  • Move funds secured by COLDCARD-generated keys (1:07)

News

  • Wallets generated by COLDCARD at risk of theft (2:18)

  • Disclosure of two DoS vulnerabilities in Core Lightning (36:26)

  • Proof of concept for a zero-knowledge proof of reserves (49:54)

Selected Q&A from Bitcoin Stack Exchange

  • What is Bitcoin's objective definition of transaction neutrality? (1:03:07)

  • Why does BIP110's decentralization benefit not outweigh its impact on transaction neutrality? (1:05:17)

  • Why does BIP110 require a 55% signaling threshold if its nodes reject non-signaling blocks? (1:09:46)

  • Why use ElligatorSwift encoding in BIP324? (1:17:12)

  • Was the OP_SUCCESSx reservation in BIP342 designed with specific opcode families in mind? (1:25:36)

  • What is the difference between the long-term feerate and the discard feerate? (1:29:14)

  • What is the quickest method for migrating a legacy wallet to a descriptor wallet on a pruned node? (1:32:40)

  • Is there historical data on orphan/stale block rates during high-fee periods? (1:36:09)

Releases and release candidates

Notable code and documentation changes

Transcription

Mike Schmidt: Welcome, everyone, to Bitcoin Optech Newsletter #416 Recap. Today, we’ve got a heavy week. We’re going to talk about the action item from the newsletter around COLDCARD; we also have a News item on that, so we’ll just combine those two into one. We’re also going to be talking about some vulnerabilities in Core Lightning (CLN) that have been disclosed; and then, we have a zero-knowledge proof-of-reserves concept idea that we’ll discuss. We also have some questions from our Stack Exchange segment that we do monthly, and Notable code and documentation changes, and one Release. This week, Murch, Gustavo and I are joined by a few guests. We’ll have them introduce themselves. Rob?

Rob Hamilton: Hello. Thank you for having me.

Mike Schmidt: Portland?

PortlandHODL: Thank you for having me.

Mike Schmidt: Chand?

Mark Erhardt: Just to be clear, usually you would say who you are and what you do so people that don’t know who’s on our show know who they’re talking to!

Move funds secured by COLDCARD-generated keys

Rob Hamilton: Murch, I’m sorry, I’m a bit nervous as a long-time listener, first-time caller. I’m a bit starstruck and nervous, and I wish I was able to come on under better circumstances. But my name is Rob Hamilton, I’m the Co-founder and CEO of AnchorWatch. We offer Bitcoin custody and insurance, and recently have been focusing a lot on the fallout of the issues that we are seeing with the COLDCARD. I’m going to start with a public service announcement, that if you have bitcoin on a COLDCARD, you need to immediately work on getting the bitcoin off, especially if it is a single-signature wallet. I just want to start there. And then, in the fallout of that, I have been doing a lot of work in doing cybersecurity research within the Bitcoin open-source ecosystem.

Mark Erhardt: Splendid, thank you. Portland, let’s do you again, too!

PortlandHODL: Thank you. Sorry, same exact reasoning there. Yeah, former MARA, currently working for Rob at AnchorWatch, general Bitcoin contributor and educator on X, or formerly Twitter.

Mike Schmidt: Hax, do you want to introduce yourself?

fabohax: Yeah, hi. I’m from Brazil, working on researching BTC since late 2018, and developing currently a bunch of research on many things.

Wallets generated by COLDCARD at risk of theft

Mike Schmidt: Thank you all for joining. We’re going to jump into the Action and first News item, which are both around COLDCARD. When we published the newsletter, this was sort of a developing thing. I guess it’s still developing, but two folks who have been sort of in the middle of it and sort of helping educate people in the community have been both Rob and Portland. So maybe, Rob, how would you summarize what has happened since, I believe, Thursday?

Rob Hamilton: Certainly. There were initial speculations, I think it may have been Wednesday night, of people saying that their COLDCARD wallets that were single-signatures that had never touched the internet were having funds move. Immediately, when there were multiple credible, concerned allegations around this happening, immediately a bunch of Bitcoin security engineers across this ecosystem started immediately using the latest and greatest AI models to go exactly into the random number generation that was used within the instantiation of keys within the COLDCARD firmware. And it was immediately found that there was a one-line bug which did not invoke the actual RNG (Random Number Generator) generation that was intended, and it was using an insecure subspace of only 232 bits. And because of that, we are in a race against time right now where you have to assume that if you used a COLDCARD and you did not either roll dice to add entropy, did not add a passphrase, or did not create the seed somewhere else and put it into the COLDCARD, that your funds are currently compromised, and you need to make immediate plans to move.

Mike Schmidt: I think when we originally reported, we said, “Hey, the Mk3 is definitely vulnerable”. It looks like there’s signs that other models are also. Can you describe the nuance between them?

Rob Hamilton: I will say that that would actually be a really great thing for Portland, because he has been going deep on the issues, the differences between those firmwares and the additional entropy. There is additional entropy that is being contributed to for the Mk4, Mk5, and the Q models. And, Portland, do you want to take that?

PortlandHODL: Yeah. So basically, the entropy should have come from the True Random Number Generator (TRNG) on the STM32 in all cases. The fallback on the Mk3 devices did not have any additional reseeding, aka adding any randomness to the seed. And as such, that basically, I think, initial number is like 240. I think, Rob, you said 232. But then, you also had the Mk4, 5, and Q. Those had a slightly different path when generating the PRNG (Pseudorandom Number Generator), where it would get reseeded essentially. Same PRNG algorithm, but you’d add a little bit of randomness, 32 bits. And that did come from a TRNG. So, 232 times harder, essentially.

Rob Hamilton: Yeah. I believe from the initial COLDCARD advisory, they said that it may be 72 bits of entropy, but there’s been a lot of analysis done in the fallout of that, that actually that reseeding is not using the full entropy space. And because of that, it could be as low as 40 to 50 bits of entropy. Is that right?

PortlandHODL: Basically, and then also, the PRNG values it pulls from a couple of parts in the chip that are not as random as initially hoped. They’re different timers. It’s pretty easy to guess some of these values or ranges, the different UID, etc. As the attack continues, the attackers can optimize based on the wallets they’ve scanned and found to go like, “Okay, this is my range, it’ll keep getting more and more compressed that I need to search through”. But yeah, essentially Rob is correct that Mk3s are like, it’s gotta happen, like now or yesterday, and Mk4s, it’s still like, get your funds off of those devices to a new seed generated by not the COLDCARD with that current firmware.

Rob Hamilton: Yeah. As just an observation, someone yesterday, this would be about 18 hours ago, reached out to me saying that they had Bitcoin left on an Mk4 that had no dice rolls, no additional entropy, and they were able to recover their funds. So, there is a window right now where hackers have not brute-forced the entire search space. So, the urgency is now. There are multiple credible reports at this point that low-entropy passphrases, one or two words, are already being cracked, which means that they are quickly expanding the entire search set of all plausible entropy that’s built on top of. Just since this is Bitcoin Optech, the COLDCARD used the BIP39 standard, which allowed you to provide an additional, what was commonly called a 25th word. So, you could have your 24 words and you could add a passphrase of alphanumeric special characters to be able to add additional entropy on top of that base phrase. That additional entropy at the moment from a passphrase is what is protecting your money. The hackers know your original 12, 24 seed words. And because of that, your entire security now is relying on whatever your passphrase was. And most people may not be aware of how passphrases interplay with entropy, but it takes a lot more than you think to be able to have a truly secure passphrase.

Mike Schmidt: I’ve seen a lot of reports that people are treating that as a PIN, right, or I’ve seen a bunch of four-digit PINs as the passphrase, right? Sorry, Portland.

Mark Erhardt: Yeah. I mean, putting it in manually in order to use the wallet probably limits, in practice, how long these passphrases are, because nobody wants to sit there and type for ten minutes and then do it three times to get it right. So, yes, right now, your wallet, if you have an Mk3 with the non-dice roll version, it’s just protected by a password that is trivial to crack probably.

Rob Hamilton: One quick thought. The COLDCARD had two different ways of using dice rolls. You either could entirely derive dice rolls from genesis with a clean slate of entropy that you would be able to cross-verify if you wished. And they also had a method where you were able to get an original, what we now know as an insecure seed phrase, and then you would be able to roll dice to specifically add entropy on top of that. I want to go to Portland. I know, at this point at least, the Block engineering team, James O’Beirne and Portland now, have all done extensive reviews of that firmware to verify that if you did the dice rolls, it’s correct. But what I want to caution people, as I’ve talked to multiple at this point, a lot of people are sure they’ve rolled dice when they ended up not having, and people who maybe did not realize, “Oh, I actually did roll dice, I just forgot about it”.

So, unless you have very clear, explicit memory that you did roll dice – and 50 dice rolls is 128 bits of entropy, 100 is 256 approximate bits of entropy – if you did less than that, you are insecure and you need to treat as if your funds will inevitably be stolen, you need to act with urgency. Portland, did you want to go into any of your analysis with the dice roll?

PortlandHODL: Yeah, so basically I did a complete trace of the most recent, and a couple of other COLDCARD firmwares, through a harness and their simulator. So essentially, what you do is you put these things, these firmwares, in a box after verifying that the deterministic build matches the same firmware that was distributed by Coinkite that would have been installed in these devices. And then, you basically trace the function calls. And I did the traces as such. The inputs were shown, so the arguments were shown and the results. And the dice-roll functionality does exactly what’s expected. It keeps filling up this digest, keeps moving through step-by-step, essentially concatenating every dice roll 1, 2, 6, 5, 4, etc, until you are done, and you’ll get the resultant hash of that string. So, if you did 100 dice rolls, you will have 256 bits of effective entropy. So, that was kind of my statement is that, yeah, the people that are affected by this would have been individuals without a passphrase, without additional dice rolls, or without using the complete dice-roll method that relied purely on the RNG of the COLDCARD. That’s when essentially, you click ‘new seed’ and it just gives you the seed. Those are the ones affected.

Mike Schmidt: Was there an opportunity, through any of the hardware and software or firmware versions, that you could add some dice rolls, but not all 50 or 99/100?

PortlandHODL: Yes. This was an identified issue with previous COLDCARD firmware that’s not related to the current issue, where in theory you could roll a single die and create a seed phrase. Those funds have been swept years ago. It provides warning flags now if you were to use less than sufficient entropy, I believe 50. It will yell at you to say that you can do this, but you should not keep money on it. I believe that’s the case, I haven’t done that recently.

Rob Hamilton: Yeah, it will yell at you. And if you use a number more than a specific number of times, I think it’s like 30 times, it will let you know, like, “Hey, you’ve used the number ‘1’ 30 times out of 100. It’s probably not random”. And then another note is they never capped the amount of dice rolls. So, you could keep rolling essentially forever.

PortlandHODL: But what Rob’s talking about is essentially, if you used low-entropy wallets, like you rolled three dice and went, “Okay, I’m done, that’s going to be my seed”, at that point, those wallets were already known, the addresses predetermined to scan and take the money from those. So, you would have known within seconds if this had happened to you. So, it’s not like it’s probably a latent thing where it’s like, “Oh, yeah, I just happen to have this wallet and now it’s going to get attacked”.

Mike Schmidt: If someone is affected in some way by one of these models and combinations with firmware, and they just have the COLDCARD, what is your personal recommendation of what they do? Is it to use the COLDCARD latest firmware? Like, obviously, you don’t want to tell everybody what to do, but what is the current thinking around people in that scenario?

PortlandHODL: I’m going to defer responsibility hugely on this one as everybody’s situation is different. In the current state, I’ve noticed multiple COLDCARDs during the firmware update process ‘bricking’. As such, I don’t personally think it’s a great idea to be updating the firmware. So, this is in the situation, like you said, you only have a COLDCARD on you and, yeah, if you wanted to essentially move your funds, you would need to get a new seed phrase on that COLDCARD with the dice rolls. So, that is fine, you can do that, or you’re going to have to end up finding a hot wallet, a collaborative custodian, or exchange to get your money off onto. Rob, please correct me on any of my statements if I’m wrong here.

Rob Hamilton: Sorry, I’m multitasking, so I did not hear anything you said.

Mike Schmidt: Maybe one important thing to note, as people are thinking about this, there have been reports and even if they’re not true, you can imagine people are being somewhat panicked about these transfers. They’re transferring it, and as you can imagine, the spammers and scammers are high, you know, fake versions of Wasabi Wallet, fake versions of other wallets are out there. And so, I guess just execute swiftly, but calmly, right, whatever your plan is.

PortlandHODL: The one thing I’ve said is, this is a general term outside of this, but slow is smooth and smooth is fast. While there is immense urgency and you need to act immediately, you need to be able to take a breath and think very calmly. And it may help you to write down a high-level plan of those steps, think about those steps, ask a friend if those steps make sense before you actually do something, because moments of panic like this are when things can go wrong.

Mark Erhardt: Yeah, we’ve had a few reports of people rushing to address this and then, maybe not even having been that insecure before, sending their funds to a scam wallet or otherwise insecure situation and losing funds they might not have lost if they didn’t act.

PortlandHODL: I will say a lot of these scams are claiming to be the official COLDCARD wallet. COLDCARD never maintained a software wallet. There is no COLDCARD software wallet that you use to put in your seed phrase or anything; that does not exist.

Mark Erhardt: Maybe one more option, I don’t think anyone has mentioned it yet. You can also, if you have an old laptop lying around, you can install a software wallet on that old laptop, turn off Wi-Fi, generate a new wallet and keys, and send to those. And software wallets should, well, unless you’re aware of some breach in a software wallet, that should be a good enough short-term solution, especially if it’s air-gapped.

PortlandHODL: We spend a lot of time in Bitcoin talking about self-custody best practices. This is a ‘break glass in case of emergency’ exception to that rule, because someone now has your seed phrase. So, your model is not, “I have a secret and that secret’s there”. You are infinitely safer at the moment with your money on a software wallet and, like, a laptop that you just turn off the Wi-Fi on, than leaving it on the COLDCARD. Just to be very clear, all of the assumptions and the things that we talk about when it relates to best practices are assuming that you’re starting with a secure key. You currently do not have a secure key. So, all of those rules, like those models that we talk about, are out the window.

Mark Erhardt: Can you just be made careful what you download.

PortlandHODL: Yes, be very careful.

Mark Erhardt: Because in many app stores, there is, especially right now, a bunch of people propagating scam wallets. So, check from the project’s website for the download link, if you can verify the signature on the software or at least double check and triple check.

Rob Hamilton: The App Store does not guarantee that a wallet is authentic. That’s where I’m noticing a lot of these are coming from. The Wasabi was a labeled app on the Apple App Store. People just downloaded it thinking it was legitimate completely. They got rugged instantly.

Mike Schmidt: Can we touch briefly on multisig and why that’s maybe a concern, but maybe not a concern, depending on the setup?

Rob Hamilton: Yes. So, I went through a very detailed analysis. it’s my pinned tweet at the moment, if you want to read the entire thing. The high-level summary here is that the attackers at the moment are hitting the low-hanging fruit of the single-signature keys. You have to understand though, if you used only COLDCARDs, a 1-of-2, a 2-of-2, a 2-of-3, 3-of-5, the entire universe of those things, and you did not use entropy on all of them, you are in a position where the attacker inevitably will be able to get your money. If any of those keys had any sort of seed or key that was unrelated to this, or you used entropy or did not come in the COLDCARD, you are able to be safe if, with some asterisks, if you’ve not reused addresses. If you’ve reused addresses, you will be vulnerable to an attacker being able to scan the entire Bitcoin blockchain to be able to see a collision of all of their keys. And just to explain at a high level very quickly, once they have all of your seed phrases that are generated within the universe of this, they will be able to go and get the universe of all of the public keys that are used to call the common derivation paths. And with that, they will be able to scan the entire Bitcoin blockchain and understand the entire universe of any public key that’s ever been tied to a COLDCARD on the network that was generated via this method, and they will be able to understand, once they have single keys and get all the single-signature low hanging fruit, they will be able to start working on the combinatorics of multi signatures.

So, let’s say you have a 2-of-3 and they were all COLDCARDs, they will be able to see, “Oh, wait a second, I see all three of these keys on the blockchain I have the private keys to. That means that this money is moving around and I can pop it”. And what will happen if you’ve reused addresses, they will be able to move that funds without your permission, because they will see all of the public keys to construct the redemption script to be able to move your money off the platform. And if you have not reused addresses, and you are to broadcast, an attacker can hypothetically RBF and steal your money. So, a lot of people have been using MARA Slipstream. I haven’t kept on track on the latest, maybe you have, Portland, on the amount of bitcoin and the number of transactions?

PortlandHODL: It’s approximately 3,500 bitcoin. I don’t know the number of transactions.

Mike Schmidt: Portland, do you want to maybe quickly describe Slipstream for people?

PortlandHODL: Yeah, essentially, Slipstream is a way to get a transaction directly into MARA’s mempool and mined into a block. The effect of this is that the rest of the network will not see your multisig, and there’s some assumptions I’ll go into after, but your multisig will basically appear as if it were just mined into a block. That’s the first time mempool.space will see it. And thus, Rob’s point about the attacker could see like, “Oh, I have these things in my collection. Let’s put them together to RBF the money into my possession”, that becomes, this is my caveat, impossible unless Marathon themselves, or there is a fundamental flaw in Slipstream, that allows somebody to view the transactions in their mempool. But so far, it’s provided one of the best options for people with multisigs, that have not exposed their pubkeys, to basically move their money, I’m going to give a really candid answer, over five hours basically, mine about six, five, six blocks a day. And yeah, in five hours, it just shows up in a block and then your funds are SAFU. So, it’s pretty nice.

Then there are quite a few API or service providers now onchain that are directly now tapping into the API, and offering this as a service to their customers and letting their customers know, “Hey, you haven’t spent from this, this is an option. You can use this”. So, but yeah, avoids a lot of the problems Rob mentioned for multisigs that have not been spent from. If you have spent from it, am I correct, Rob, it just goes in the mempool?

Rob Hamilton: If you reuse the address. That’s the biggest differentiator.

Mark Erhardt: Not just reuse the address. I wanted to restate what Rob said, because I don’t think it hurts to explain it twice. So, please bear with me, even if I’m saying stuff Rob already said.

Rob Hamilton: Don’t worry about it.

Mark Erhardt: So, a multisig setup is derived from three or more keys. And usually, the individual output scripts are composed of the same step in the derivation of the keychain. So, you have maybe three keychains, A, B, and C, and the first output script or address will be the first element in each of those keychains; the second element from each keychain will be composed into the second output script; the third will be composed into the third output script, and so on. So, if an attacker sees any of your addresses being spent, they learn the output script that was hashed and how it is satisfied on the input side. And if they identify any of those keys, they can tell that it is the same derivation chain of what they have in their derived keys, in the compromised keys. And this is how they can recompose your multisig wallet and can take your funds.

So, as Rob said, especially if the wallet is completely composed of COLDCARD keys, they can just combine those, even if you never spent from the wallet, they can just try ABC, ACB, BAC, and for the whole set of keys that they generated. But if you spend onchain, they explicitly are seeing which keys are being combined. And in that case, it’s even enough, if you have a 2-of-3 multisig and two of those keys are COLDCARD keys, because now that they see the public keys, they know what the third public key is, at least for that exact address, but they can’t derive the next public key. So, they can’t take other UTXOs, but they can take UTXOs from reused addresses, even if they only have the quorum. So, if they have two out of the three in a 2-of-3, they can take reused addresses. I just wanted to stress that.

Mike Schmidt: I was going to solicit, on this particular set of COLDCARD issues, if there was anything else you think that the audience should be aware of.

PortlandHODL: I don’t have anything else to add at this time.

Rob Hamilton: I would say just going through the full, I’m looking at my pinned tweet for the hyper, just quick summary. We already went through the different ways you can be mitigated. Just again, for emphasis and repeating, it is either rolling dice, either adding to an existing seed phrase as additional entropy, or by in whole, entirely, doing 100 rolls, totally skip that path of the compromised entropy, so you are mitigated there. But I would emphasize that a lot of people aren’t sure, if these wallets are set over five years ago, they may not exactly remember the exact ritual they did to create these and they need to be very certain. And so, I would still urge caution regardless. If you have a passphrase with sufficient entropy, that is okay. But that’s 12 BIP39 words to have 128 bits of entropy, or 10 English words in the common language, 25 mixed upper and lowercase letters or 20 ASCII characters, right, so that’s 128 bits of entropy. If you’ve done less than that, you are not secure at the moment to varying degrees, and you need to be understanding of that and making plans to upgrade. Just to say, if you used 11 words instead of 12, you’re not getting on a plane this moment to go across the world, but you need to be very sure how everything’s set up and you need to understand, for your own risk measurement, how far off you are of secure and how you need to make your own plans.

Also, if you did external entropy, hypothetically, if you derived a seed phrase that was entirely outside the wallet, including if you use Sparrow on desktop, and then you just loaded it into the COLDCARD, you are not impacted by this issue, right? So, there’s an entire, just as a clarification here, that the COLDCARD and from the initial review that we’ve done for everyone, I think there’ll be more understandings and realizing. But as it relates to this specific catastrophic issue, that is not impacted. The last thing I’m just looking for. If you have a minority, let’s just say hypothetically, let’s say you have a 2-of-3, and let’s say you have one COLDCARD, a ledger, and a Trezor, your one card is now compromised. So, I would treat this as a normal key rotation, so if it were gotten lost or destroyed and you have to do a rotation, you don’t have to do that at this exact moment. But that would be just what I would emphasize, making sure you have a plan to send those funds somewhere, use your friend network, talk to people, don’t urgently do anything that may cause a mistake. And I think that’s a good, just high-level summary of the breaking news we have, Portland.

PortlandHODL: Another note I’ve been dealing with is a lot of people have been asking specifically, like, “Hey, I’ve imported my seed from Mk3 to Mk4. Or just ensure you remember if you’ve done this process, if you’ve used the seed from the Mk3, you’re still compromised, even if you’ve moved that seed to any other device.

Mark Erhardt: Oh, that reminds me also. So, there has been a firmware update issued by COLDCARD. If you just update your COLDCARD, you do not become secure. The matter is what firmware was used to generate the seed. So, just upgrading the firmware does not help. You will need to move your funds, you will need to generate a new seed, and yes, you can probably use the new firmware with your COLDCARD to generate a new seed, but just moving to the new firmware is insufficient.

Mike Schmidt: Maybe one other note, and maybe it’s obvious, but if you have a sort of degrading multisig setup, you may run into eventually situations that have been outlined here as well, especially if you fall back to one of these compromised COLDCARDs as your single key and you broadcast, right?

Mark Erhardt: Only if you’ve used it before. I think that’s probably fairly safe. But yeah, if you use a COLDCARD in your wallet setup in some manner, you should think about whether you need to move. And if you’re not sure, you should move.

PortlandHODL: In terms of the COLDCARD, this is to anybody who has already got rugged, I would not, in my opinion, suggest destroying the device just because you think it’s worthless or throwing it away or whatever. Because of the fact that the random entropy came from the physical chip on the card, so there is, in some potential universe, like, I’m not saying it would happen, but you could use that as potentially added verification to anybody in the chance of recovery. Like, “Hey, I can prove that this COLDCARD would have generated this seed potentially”.

Rob Hamilton: I will say, I have heard of it, I do not know details, but I have heard pretty reliable, confirmed sourcing at this point that there are white-hat hackers right now who are doing this. I’m not going to speak to the ethical implications of that, but for awareness, there is some subset of funds that are plausibly being swept at the moment for those purposes. And that is part of what Portland is saying. I think there’s a longer conversation around the ethics and the practicality of doing that. But in the event, you would be able to have a provable chain of custody, because the UID on the STM32 is seared into the chip, and that is what is the contributory entropy that was used to be able to make your insecure seed phrase. So, there would be a physical, provable chained custody link event to be able to show that provenance, just to explain the full details of what you’re talking about of holding on to your COLDCARD.

Mark Erhardt: Let me say that again. There is a number on your chip that was used to generate your wallet. Keep your wallet, even if you’re not going to use it, probably put a sticker on it, “Don’t use”, or whatever, if you don’t want to use it anymore. But keep it in order to be able to prove that you had the chip that was used to generate your wallet, because it might either, via white hats hacking some remaining wallets and taking the funds, or if law enforcement picks up the hacker early enough and takes the funds, there might be a way to get back some funds. And having the physical COLDCARD device may help you prove that it was your funds.

PortlandHODL: So, there’s another component to this as well that the number of combinations that this hardware ID turned into, there’s like a 1 in roughly 65,535 chance that you would match the same ID as another COLDCARD potentially. So, they’re not completely unique, but they’re much more unique than they all use the same. And the other thing too is the reason why the firmware update becomes a problem is because if the firmware update fails and you break the device, the device itself has been fused off. And what that means is if you break the device, you can’t plug in this little cable to it to pull that UID off for proof any longer. You’ve essentially, at that point, forced yourself into going to like a laboratory to be able to get them to kind of decap the chip potentially, and then get your UID to do any of this proof. So, if you are on a COLDCARD Mk3 or 4 that’s already been rugged, just put it away and just hold on to it as evidence.

Mike Schmidt: There’s one thing that I want to just touch on before we wrap this up, separate but related. And we have Rob here, so I want to have Rob talk about what’s going on. There’s this flurry of activity online right now about vulnerability discovery. Can you explain what’s going on and why it’s maybe related to what happened with the COLDCARD hack, and all that?

Rob Hamilton: Yes. So, this is an ongoing developing situation. So, for the sake of abundance of caution, I will be vague in certain spots, to not over communicate things. But what I’d already shared was that when this vulnerability was happening, a lot of people, including myself, started looking at the firmware exactly where this issue hypothetically would appear. And in my anecdotal experience, if you use the Anthropic, it wouldn’t help, it would actually downgrade you off Fable and put you on Opus, you wouldn’t really be able to do anything. Codex was pretty good, like OpenAI. If you really get the prompt right, maybe it’ll work, but you have to coax it a bit. If you use Kimi K3, it instantly one-shots and finds the problem. So, I don’t think it’s a coincidence that on Monday of last week, the Kimi K3 model went fully open weights, where anyone could run this model anywhere in the world; and then by Wednesday night, this hack was underway. There’s no proof of this. It is just, I think, a very strong suspicion at this point, seeing how this model behaves so differently than anyone I’ve seen before, in being able to just look at an open-source code base. And I could just say, “Give me a list of vulnerabilities”, and it just provides them and says, “Here you go”. And so, there’s been a lot of work being done right now and trying to understand how we could do harm reduction across the rest of the ecosystem and being able to leverage this. I’m not sure if anyone had specific questions around that.

Mike Schmidt: No, I think that’s a great summary. Yes, people are doing this; Rob, you are doing this.

Rob Hamilton: Many people are. Yeah, Portland is doing it. If you want me to, I’ll read Calle’s tweet. We’ve been doing somewhat of a baton relay between where we are in the world, and just one person starts, next person goes. He said, “Red teaming Bitcoin: we’ve written multiple harnesses and we’re launching a huge wave of reviews across many core Bitcoin projects, crypto libraries, wallets, and infrastructure; the situation is extremely bad; we’re averaging in order”, this is Calle’s tweet, “we’re averaging in order of one critical exploit per hour per person; we’ve reported critical vulnerabilities several projects in the past 12 hours; thankfully, this is a very expensive exercise, we’re burning 10,000 tokens a day in doing it; you can donate”. Send Calle a DM if you want to do donations. OpenSats is offering to take up the bill. I have many other people within the Bitcoin ecosystem that are offering to pay for this. For right now, we don’t immediately need the money, but in the fallout and aftermath of this, we’ll handle that and have those conversations. And Calle thanks, Kimi K3 and being able to provide us with the accounts and uncensored intelligence to be able to fight back.

There’s a very sad asymmetry at the moment where white-hat actors are one step behind. And I’m not a policy person, but this is something I’m now directly seeing on the front lines. And what we’re trying to do now is fight fire with fire and start being on even footing.

PortlandHODL: My suggestion would be to anybody that custodies funds through software that they run or are responsible for, is to adversarially prompt Kimi K3 to like, “Hey, how can I break this software? What kind of vulnerabilities exist?” Like, just do it.

Rob Hamilton: Every maintainer of software in the Bitcoin ecosystem right now needs to start aggressively going through their codebase. Reach out to someone you know that can get a hold of myself or Calle to be able to start doing proactive scans. During this call, I’ve been handing off vulnerability disclosures to multiple open-source projects within the Bitcoin ecosystem. We’ve already scanned at least 150. What we’re seeing is that every person is able to apply their subdomain expertise to be able to get more efficiency out of it, to be able to get even more insight. And this is a rapidly evolving situation. And so, everyone right now, if you are maintaining any sort of load-bearing Bitcoin infrastructure, get a hold of someone that can be able to get read in on this. We have multiple people that are peer-reviewing the initial vulnerability reports to get credibility and to refine them more, to make sure that we’re respecting the time of maintainers. But given the circumstance of everything, we’re all acting out of an abundance of caution and proactively flagging and tracking down people to be able to make sure everyone’s able to get a jump start on this and move as fast as possible. Yes, Murch?

Mark Erhardt: Also, just a reminder, tweets are not responsible disclosures. So, if you’re finding an issue, contact the maintainers, don’t post it on Twitter like a moron.

Rob Hamilton: Absolutely. Yeah, we are working on a very tight web of trust at the moment with people that we know and can vouch for, that are handling the entire chain of multiple agent chains. This is an evolving, emerging thing, but it is quite fascinating. I can run a scan on something and get two mediums, and Portland can run a scan on something because he understands the software more and get crits that are confirmed. So, this is a rapidly evolving thing that we’re all trying to kind of massively coordinate all of our different domain expertises, to be able to do the initial scans, cross-verify being able to build proof of concepts that are provable lines of code that you’ll be able to replicate and show and kind of build it. I think there’s going to be a massive, massive amount of learnings from this and a shared knowledge that we’ll be able to use going forward. It’s a little bit too early to know the exact form factor of what that will take.

But right now, just acting with urgency, if you or someone you know maintains critical Bitcoin infrastructure or maintains any Bitcoin software that is either responsible for the management of Bitcoin private keys or the construction of Bitcoin transactions, you need to get a hold of someone and get plugged in to understand what’s going on right now.

Mike Schmidt: Well, we will let both of you get back to that important and timely work. We appreciate your time jumping on. Thanks, Portland; thanks, Rob.

PortlandHODL: Thank you for having us.

Disclosure of two DoS vulnerabilities in Core Lightning

Mike Schmidt: Cheers. We will jump from vulnerability to two more vulnerabilities that we’ll be discussing, “Disclosure of two DoS vulnerabilities in Core Lightning. Chand, you’re back with us again today. You were on with us in #407, I believe. We highlighted your work in Newsletter #407, and I think you came on for Podcast #407. But we want to talk about these two new vulnerabilities that you responsibly disclosed. It looks like they’re both around memory exhaustion, DoS bugs. Why don’t you walk us through the two bugs in your own words?

Chandra Pratap: Right, yeah. First of all, thanks for having me. Just to introduce myself briefly, I’m Chandra, I’m a grad student of mathematics at NIT Surat, India. I am a Summer of Bitcoin 2025 alum where I worked on fuzzing the LN, specifically CLN. And this time around, I’m again participating in Summer of Bitcoin with Smite, which is a snapshot-fuzzing framework for the LN. And these two vulnerabilities were found with my previous stint with CLN, where I was improving the fuzz testing suite for CLN, and I added a fuzz target for the gossip daemon. So, CLN uses a multi-daemon architecture where the master daemon is the Lightning daemon. And it accepts messages from the peers and hands them off to the correct daemon that’s responsible for handing these messages. The opening channel process is handed off to the opening daemon; the gossip messages are handed off to the gossip daemon, connect them, and there’s a bunch of similar daemons. This class of vulnerability, these two vulnerabilities take place in the gossip daemon specifically. Well, one takes place in the connect daemon, which is basically the glue between the Lightning daemon and the gossip daemon. And the second vulnerability takes place in the gossip daemon, the actual daemon responsible for parsing gossip themselves.

The first vulnerability, the one in the connect daemon, it was disclosed quite a bit earlier. And what it is, is basically a memory exhaustion DoS attack, in which the remote attacker can basically reliably crash any publicly-accessible CLN node by sending a certain class of messages. Specifically, it’s the channel_update gossip message in this case. So, what happens is whenever a peer sends you a large number of channel_update messages for a channel with channel announcement message the victim node hasn’t seen yet, what the victim node tries to do is it tries to cache these messages so that it can get up to speed with the channel’s current status when the channel announcement for this said undiscovered channel comes in later. It’s kind of like an optimization process. But what was going wrong was connect daemon actually, while caching these messages, there’s no upper limit. So, any attacker, if they send a flood of gossip messages, keep on sending them, each message takes around, I think it was 48 bytes or so of memory, and the memory consumption keeps piling up. You keep sending these channel_update messages, you don’t need any on chain relationship with the victim node, because gossip messages follow a gossip protocol, you don’t need any type of relationship. So, you can basically send fake short channel IDs. And we can keep sending these messages, the connect daemon is going to keep querying them, and ultimately, your node is going to run off memory.

This class of vulnerability is particularly bad because it affects your system as a whole as a computing system. For me personally, when I was developing the attack program for the verification of this vulnerability, on my 10-GB virtual machine, I was able to get the CLN node that was under attack to consume around 9 GB of memory. At that point, the OS stepped in. I mean, it was a complete system freeze. I had to restart my system to get it to actually start working again. So, that was pretty bad.

Mike Schmidt: So, that first one, it’s an unbounded queue that could be added to by any of your connections on the P2P network. So, the fix is then bounding the queue?

Chandra Pratap: Yes, the fix was pretty simple. I responsibly disclosed it to Rusty, who is the maintainer for CLN. He told me the fix was to cap the queue, which was decided to be half a million, 500,000. At that point, the connect daemon will start dropping gossip messages. That was apparently a workable fix, and that’s the current state of that vulnerability.

The second one is actually particularly sad, because how I discovered this vulnerability was basically I took the attack program from the first vulnerability, I applied the patch, the supposed patch that was supposed to fix this memory exhaustion issue of the first vulnerability, and I just ran the attack program again. I made no changes, no changes to the logic or anything, and it happened to find the second vulnerability. And if anyone from the CLN team would have bothered to actually run the attack program, they would have found it themselves and maybe get it patched earlier. But I had to discover it and disclose it. It’s kind of nice that Rusty was working on a garbage collector for the gossip map where this vulnerability actually takes place, and that fixed the issue. But yeah, it’s a bad look on the security infrastructure of the LN as it stands now.

To talk about the internals of how this vulnerability works, it basically does the same, thing sends a flood of gossip messages, channel_update messages, and the connect daemon now hands off these messages to the gossip daemon, which is actually responsible for processing these gossip messages. And what the gossip daemon does is it maintains an internal map, an integer map of short channel IDs in these channel_update messages. And storing these short channel IDs, they take up some memory. It’s shorter than what the queue thing was from the first vulnerability, but it’s still non-trivial. And you keep sending enough of them, you can get the gossip daemon to balloon up in memory usage and ultimately your node will crash as well. I was able to also verify that this vulnerability also caused a swap death on my system. So, yeah, that was particularly bad. And yeah, I think we’ve talked about the fix already. Rusty was already working on a garbage collector for these internal maps, and that apparently fixed the issue.

Mark Erhardt: So, your first vulnerability was filling up the gossip messages, and the second vulnerability was mapping the channel IDs. And that was also unbounded. And in both cases, just creating a huge amount of gossip messages caused a crash in the node. So, basically, after the first unbounded storage was capped, there was a second one found that could also overflow or not overflow, get you into swapping and crash your node.

Chandra Pratap: Yeah, that’s about it.

Mike Schmidt: Chand, talk a little bit about the fuzzing framework that you mentioned that you’re working on that’s being developed. Is it running now? Talk a little bit about it.

Chandra Pratap: Yeah, so currently I’m working on Smite, which is Matt Morehouse. You’ve mentioned him already. He’s a vulnerability researcher. I think he works with OpenSats now. And he’s been involved with CLN Security for some time now. He’s the maintainer, and we’ve been working on Smite, which is a snapshot-fuzzing framework for the LN. So, the problem with the current state of LN security is that they all manage their independent set of fuzz targets. And while that’s nice, it’s very, I guess, spread and not uniform across the whole LN. So, what we want to do instead now is develop a generalized framework that we can basically hook any Lightning implementation to, and we can basically act as a malicious peer. The fuzzer acts as a malicious peer, sending a sequence of messages to any Lightning implementation, the one that we’re hooking into, and tries to find vulnerabilities in those.

This one, other than the fact that the approach is generalizable and you can hook multiple Lightning implementations into the framework. What’s nice about it is it uses, if you know about Fuzzamoto, that does defines a mini program for Bitcoin messages that you can send over the network. And that’s what we’re trying to replicate with Smite IR, which also defines a mini language in which you can describe a sequence of messages that you can send to a Lightning node. So, we have operations like send channel update, send commitment message, receive commitment message. And the fuzzer, instead of trying to send a message and see if the parser crashes, it goes through the sequence of messages and actively processes these messages to carry out basically a simulation of what an attacker would do if a vulnerability existed for those sequence of messages. And that’s how we’re trying to actually improve upon the idea. It has lots of inspiration from Fuzzamoto and syzkaller, which is the fuzzer for Linux kernel. It draws a lot of inspiration from that in trying to find vulnerabilities. We’ve been successful so far. I think we found quite some vulnerabilities. They’re not disclosed at the moment, we’ve only recently reported them, but we’ve had quite some success with the fuzzer already.

Mike Schmidt: Maybe just to contrast briefly. So, when we were talking with Rob and Portland and some of what they were doing, towards the end of our conversation, about having large language models or AIs reason about a certain codebase and try to figure out if there’s an issue that way, what Chand and what Fuzzamoto and fuzzing is working on is a little bit different. You can kind of give hints to a fuzzer about the structure of certain messages, and then sort of have the fuzzer grind away doing quasi random inputs in different orderings to try to find vulnerabilities that way. So, two approaches to the same goal, which would be to discover vulnerabilities and report them responsibly, as Chand has done here. Chand, anything else for folks? If people are saying, “Hey, it seems important to be doing this kind of work this day and age in Bitcoin, like the Smite thing sounds interesting”, where would you point them to?

Chandra Pratap: If you’re interested in getting involved with security work, Smite is actually a pretty good point. We have a lot of initial work that we need to do. It’s a very open community, you’re always welcome to contribute. And even if you’re not interested in working on LN Security, Fuzzamoto, and there’s a whole lot of fuzzer and security tools developed for the main Bitcoin ecosystem as well. So, I believe personally that fuzzing is actually a pretty good starting point to get into the whole world of Bitcoin and Lightning security. That’s how I was introduced to the community. I’ve been a part of it so far now, and it’s something that anyone can pick up because it’s a really simple concept. You’re basically trying to feed malformed messages to an API and see if it breaks. That’s ultimately all it boils down to. You can build on top of that, there’s various techniques. It’s a very hot area of research. But ultimately, I think it’s a pretty sweet point if you’re trying to get into this type of research. And yeah, there are a bunch of fuzzers for the LN, for a lot of implementations across various languages. So, someone that’s trying to get into security in general, I think fuzzing is a very good starting point.

Mark Erhardt: One follow-up question. So, we’ve talked a lot about the big infrastructure projects, like CLN or Bitcoin Core being fuzzed. We have fuzzing at the internal level, sort of expanding on unit testing, but we also have this fuzzing from the outside, treating the software as a black box and using the external interfaces to put in data. Now I’m wondering, these bigger projects obviously are very important and it’s great that they are being covered. Would this project also be able to be applied to smaller implementations? Would maybe Lightning wallets, mobile wallets, or other interfaces be able to write support to be plugged into Smite and be able to benefit from it that way?

Chandra Pratap: Smite supports Lightning implementations, so it doesn’t matter the size. If it is a full-fledged Lightning implementation, it can definitely be plugged into Smite for wallets and other stuff. We don’t support that as of now. Our core focus is Lightning implementations and as of now, we’re supporting the four major Lightning implementations which is Eclair, which is written in Scala; CLN, which is written in C; LN daemon, which is written in Golang; and LDK, which is written in Rust.

Mark Erhardt: Awesome, thank you.

Mike Schmidt: Chand, thanks for your work on this, responsibly disclosing, and work on Smite, and also joining to describe it all to us today. We appreciate it.

Chandra Pratap: Right, thanks everyone.

Mike Schmidt: Cheers.

Chandra Pratap: Bye.

Proof of concept for a zero-knowledge proof of reserves

Mike Schmidt: In our last News item for this week, “Proof of concept for zero-knowledge proof of reserves”. And hax, you posted about an idea for a proof-of-reserve system using zero-knowledge. Maybe we’ll define proof of reserves really quickly. It’s how an individual or an exchange, for example, could demonstrate that they hold the bitcoin that they claim to. In fact, I think even just the other day, River did their proof of reserves to try to articulate to their users and the broader Bitcoin community that they hold the Bitcoins that they say they hold. Hax, I’m curious as to what are the downsides of that, maybe not that exact approach, but traditional proof of reserves and how would a zero-knowledge proof-of-reserve system work, and have what advantages?

fabohax: Yeah, well, there’s many challenges yet for applying zero-knowledge proofs (ZKPs) into the Bitcoin Network, mostly because we have to prove on the chain what is the relationship between the user and it. And yes, I was struggling with this, but anyways, it’s worth to keep searching. There’s a lot of privacy issues. So, a couple of years I was checking into ZKPs, talking with many other cryptographers also learning about it. Yeah, this is kind of the process.

Mike Schmidt: And so, what can zero-knowledge bring to proof of reserves specifically? I think we’ve had folks on the show talking about other zero-knowledge ideas and how you could apply it, but maybe walk us through what I think you’re calling here ‘proof-of-hodl’.

fabohax: Yeah, I was doing this because we’re doing spaces on X and I was reading a paper about accumulators, batch proofs, etc, about the potential solution of cross-chain swaps between Bitcoin and other chains that could be very like blinded, people could just exchange their bitcoin for other stuff. But what’s interesting is how the ZKPs were into, and thinking how there is no primitive, we have to really prove ownerships. So, I was making this idea, crafting out. So, what is basically a zkPoH (zero-knowledge proof-of-hodl) is a kind of experimental proof of concept. So, for proving you hold bitcoins, you get a snapshot of the specific UTXOs that has the satoshis within the transactions. And with the circuits, with Noir, we have the availability for proving that there was a membership onto that snapshot. But currently, we don’t have a proof that it belongs really to the chain. So, I was, in this day, realizing that we could use a trusted execution environment that can be relayed, it can be audited, and kind of generate proofs for users and have a signature into. And so, we can ensure that the actual proofs were made with a relay process.

Mark Erhardt: I commented on your Delving thread, and maybe I’ll try to summarize a little bit of what I understood and you could correct me. So, this is an early proof of concept for a zero-knowledge proof that proves that someone has access to at least 1 bitcoin, in this case, and you can cover up to 4 UTXOs. The idea is that you can prove that a set of UTXOs amounts to at least 1 bitcoin. The verifier does not learn more than that it is above a certain amount, the verifier doesn’t learn which UTXOs you’re proving for, and this would enable someone to prove that they have at least some certain amount of bitcoin. Future work, I think, currently still includes proving that you can sign for the UTXOs. So, you can lay claim to certain UTXOs, but the initial proof of concept that you have so far does make the prover commit or bind their proof to some specific UTXOs, but doesn’t prove that you can sign for them. Did I get it so far right?

fabohax: Yeah, yeah. Record on the circuit, that’s proof that you did the snapshot. So, everyone can make a snapshot from there. But, anyways, that’s just the current challenge right now.

Mark Erhardt: Right. So, I was curious. You specifically mentioned that you can do it for up to four UTXOs so far. Would it be feasible to scale this up to a larger number of UTXOs?

fabohax: Yeah, sure. It’s kind of a number, but it requires much more computations. ZKPs, that’s another challenge that is a kind of – well, there are other implementations, but, anyways, it’s pretty early, super-early.

Mark Erhardt: Right. So, the idea would be in the future that that would be more scalable, maybe that someone finds more speed ups. And then, you said you could use potentially a trusted execution environment to make sure that the prover can actually sign for the UTXOs that they commit to. So, what are the next steps for you, or what are your calls to action for the audience?

fabohax: Call to action, mostly to keep engaging with the Delving Bitcoin. I found that there is a pretty okay community there. There was already research on the matter. I was surprised too, because I was just generally searching. ZKPs probably are part of the next generation of privacy Bitcoin; it deserves a look at. So, yeah, I think if we have a collective think of it, it will be super-nice.

Mike Schmidt: Murch and hax, maybe a question for either or both of you. It sounds like the value here is that certain UTXOs are not identified, which I think is sort of the privacy angle here. But I’m just thinking, in a fleshed-out version, let’s assume you can do any number of UTXOs performantly and you could prove that you could spend those UTXOs in some way, let’s just assume those are both in place. I guess maybe this is just adversarial thinking, but it would seem like somebody with a large pool of bitcoins could just charge for attestations at certain amounts, right? And so, if I’m in exchange and I’m in big trouble but I want to show a proof-of-reserve number, I go to somebody who has these bitcoins and I pay them maybe a lot of money, but not nearly as much as the money that I don’t have in reserves, and I want to keep my scheme going, I guess that’s the downside just of the privacy element of this, right?

fabohax: Sure, we could search for latency on that, we could ask for a, you know, like a heartbeat you can prove it anytime, right, if you are looking for loans or something like that. I think that there will be further research on that for sure.

Mark Erhardt: Oh, so the proof is tied to a specific height in the blockchain, right? So, if someone wanted to make a convincing proof, you could just anytime hit their API and retrieve a proof, and then it would create a new proof for the current block height. Is that what you’re saying?

fabohax: Yeah, that would be heavy to rely, yeah.

Mark Erhardt: I mean, it would probably come at a later block height because it takes some time to compute, and there might be a limit how often the service offers to do this. So, it sounds like you could maybe implement it in ways that are more convincing concerning the problem that Mike states, where other people can sign that since these UTXOs are unattested to and not revealed, basically if the proof is transitive, you only have a proof that someone has a certain amount of bitcoin. And that, of course, is not quite what we were going for. I also quickly wanted to compare this to two other things that exist. So, there’s BIP322, the generic signed message format, which also has a proof-of-funds scheme in it. In that case, you explicitly sign with some set of UTXOs. You create a transaction that has a fake input, but the other inputs you create actual signatures for. And in that case, you prove that you have a certain set of UTXOs and can spend them. But of course, in either of these cases, nothing prevents you from moving the UTXOs later, and then not holding the UTXOs that you signed with. And in the ZK proof, of course, not only could you move the funds, but you could reuse the same UTXOs to make multiple proofs in parallel.

Then, there is another one, I think it’s BIP46, let me pull it up briefly, which is the Chris Belcher’s proof of funds. The name currently eludes me. Yeah, the timelocked fidelity bonds. It was BIP46. So, in that case, you actually lock up funds for a certain time, and you make a proof that these funds were locked up by you and you can’t spend them for, I don’t know, like a year. And then, you can use them as a proof of funds that you have locked-up funds, and that gives you some sort of credibility. Just sort of as related work, I wanted to mention these two concepts.

fabohax: Yeah, yeah, the current summation. So, I wanted to point out, because there’s another need of proving that you have a latency of ownership, right? We have to make another proof of, like, a timelock. The data would be there, and just another proof. But, anyways, this trusted environment execution will be able to make the proofs for various kinds of. You also have to prove that you have the address or you did a transaction, etc. So, there are many proofs that the environment can generate.

Mike Schmidt: I think we covered that one pretty good. Hax, we appreciate your time and hanging on through the first half of this newsletter to walk us through that.

fabohax: Thanks for having me.

Mike Schmidt: Cheers, yeah, have a good day.

Mark Erhardt: Yeah, and thanks for working on this.

What is Bitcoin’s objective definition of transaction neutrality?

Mike Schmidt: Yeah. We have our monthly Q&A from the Stack Exchange, and we had a flurry of activity this month to cover. “What is Bitcoin’s objective definition of transaction neutrality?” This is obviously a squishy question, Murch, but Ava attempted to answer saying, “It’s whether a change prevents anyone from continuing to use Bitcoin as they already do”. And then, the examples there would be previously spendable scripts unspendable, or breaking a protocol that’s being developed or relied upon. But even that is a bit sketchy, right? Because basically when you’re soft forking, you’re sort of taking some of that out to some degree, if you’re messing with transaction-related items. So, Murch, maybe you could comment on Ava’s thoughts, but do you have a thought on this?

Mark Erhardt: I mean, I don’t know if Bitcoin has an objective definition for transaction neutrality, and especially one that all of the Bitcoin ecosystem aligns, or whatever you want to call it, the community agrees on. But yeah, soft forks always forbid something that was possible before. The question is whether that impacts someone. And if something is being forbidden that wasn’t being used by anyone, Ava argues that this could be called a neutral change. So, changes that do impact people that have been using something would not be considered a neutral change. And just to be clear, there were some discussions in the comments underneath that not all changes to Bitcoin have to be neutral. So, for example, changes could propose a non-neutral change, but then, of course, the discussion would be whether the change is worth it and what we’re trying to achieve and a cost-benefit analysis. Generally, a non-neutral change would probably cause a lot more discussion than a neutral change.

Why does BIP110’s decentralization benefit not outweigh its impact on transaction neutrality?

Mike Schmidt: Next question, totally unrelated, “Why doesn’t BIP110’s decentralization benefit outweigh its impact on transaction neutrality?” This was answered by Pieter Wuille. I guess the crux of Peter’s answer is that even if you invalidated data-carrying transactions or patterns that would match that, it wouldn’t actually reduce node costs. He gives a few different reasons for that, noting the block weight limit is already in place; that actually, the folks that are using data storage are using the cheapest for certain node resource costs; and that even if you did outlaw those patterns of data embedding, that they would be replaced by other styles or other transactions, or they would just be replaced with, I guess, regular Bitcoin monetary transfer transactions. So, Murch, do you have thoughts on this? Obviously, there are a few different node resources that are in question here. And I think large data-embedding transactions take up more space than would probably be otherwise used by monetary-only transactions or normal transactions. But they’re also easier on validation or verification, right? Do you have some thoughts on the nuance here?

Mark Erhardt: Yeah, this is a very common meme that is being espoused by 110 proponents, especially that through the spam wave, the IBD (Initial Block Download) has gotten way slower. So, there is probably some effect by the UTXO set having become bigger, but I think the effect is overstated. There’s also been a ton of improvements to IBD in Bitcoin Core, well, there were improvements in 29, 30 31. There’s a batch more improvements coming in 32 too that I think are going to make IBD again at least 33% faster. Regarding the limit, the blockchain cannot grow more than the block weight limit restricts it to. So, the blockchain is restricted to linear growth. This limit has been the same since segwit activated in 2017. Obviously, these new data-embedding schemes that have been invented since then, with the inscription envelope, are making more use of the witness section to contribute to the data. So, their overall data insertions have a lower weight per byte. But also, as you said, a lot of that data does not have any opcodes. They are completely inert in the sense of transaction activity. They’re very cheap to validate. I think that BitMEX research had an article where they researched whether or not IBD was slower for those blocks specifically that had a lot of data embedding. And they found that actually, these blocks, while bigger in data footprint, are cheaper to validate and faster to validate.

So, yeah, data embedding is, I think, especially in the context of the last week, I feel vindicated with saying that data embedding is not nearly as big of an issue as many other things we could be spending time on. And I think we’re, well, sorry for tooting our own horn, but I think dismissing this as an issue that we want to spend our time on, our very limited time on, is correct and continues to be correct. I think we have way bigger issues, like security, and we should spend more time on that than discussing spam and BIP110.

Why does BIP110 require a 55% signaling threshold if its nodes reject non-signaling blocks?

Mike Schmidt: Well, that I guess leads to the next question and whether the community agrees with your assessment, Murch, which is, “Why does BIP110 require a 55% signaling threshold if its nodes reject nonsignaling blocks anyway”. Vojtěch answered this. He explained the two different phases, one being the 55% threshold applying to the voluntary minor signaling portion or phase, which happens before the mandatory signaling period begins. This is a timely question, of course, because I guess it’s not possible now to hit the 55% threshold for BIP110. And so, to your point earlier, Murch, it does seem like at least the community writ large has discounted the concern that BIP110 is attempting to address for a variety of reasons, and we move from that phase to the minor signaling phase, where essentially it is required by the implementation of the BIP110 software that the blocks would be signaling after that particular mandatory block height is reached.

Mark Erhardt: Right. So, the activation style proposed for the deployment of BIP110 has two phases. One is the minor activated soft fork portion. So, it was using a paradigm that had been used successfully by a number of other soft forks, where if a sufficient number of miners signal readiness to enforce the new rules, there would be a lock-in; and after one difficulty period of lock-in, the new rules would start taking effect. The idea here is that if more than half of the hashrate actually enforces new rules, a soft fork is stable and coalesces on the new rules, because any blocks that do not adhere to the new rules would be rejected by the majority of the hashrate and reorged out eventually. So, there might still be a short chain split where a non-upgraded node would create a block that doesn’t adhere to the rules. But if the majority of the hashrate enforces the new rules, it would eventually be reorged out and the whole network would coalesce on this soft fork.

The percentage that was required for activation in prior soft forks was much higher usually. BIP9 proposed 95% at first. Taproot reduced it to 90% after segwit was struggling so long to get 95% of the hashrate. The other part is the mandatory signaling phase. So, after this phase where for a number of signaling periods or difficulty periods, and a majority of the hashrate could lock in the changes to activate early, the BIP110 deployment additionally has a mandatory signaling. So, it has a flag-day activation essentially, where even if the miners do not support the change with the majority of the hashrate, it will force activation. BIP110 was immediately proposed, as in, “Okay, we can do this the easy way where you agree with us, or we can do it my way where we do it anyway at a specific height”. So, this block height is coming up, currently predicted to fall on Saturday, four days from now. And at that point essentially, the BIP110 nodes are going to start a soft fork by themselves where they only affect the header of blocks.

So, the mandatory signaling can be thought of as a soft fork in the sense that they will start rejecting any blocks that do not signal the bit in the block header and the version field. They do not enforce the rules that they’re trying to enforce with the soft fork yet. So, rules for transactions are not changed yet, only the rules for block headers are changed. And now, BIP110 nodes will require every single block from a specific height to signal for activation. This mandatory signaling then will cause the chain to achieve the 55% activation threshold, and then the lock-in phase would follow, where one difficulty period of blocks would have no encumbrance at all, and then the BIP110 rules would activate. Currently, the hashrate that is signaling support and readiness for activation is under 3%. They’ve really picked up the support in this difficulty period. So, they recently had a total number of 110 blocks that signaled. 110 blocks, if they had all happened in a single difficulty period, would be about 5.5% of that difficulty period. So, I think it is safe to say that at least from hashrate’s side, there is very little to no support for this change, and it’s a pipe dream to expect that suddenly on Saturday, 100% of the hashrate will flip and start signaling for this soft fork, especially with people having their mind on a much more important issue.

So, it’s very timely that today I see that one of the leading BIP110 proponents announced that he is rebasing the PoW-change hard fork that Luke had prepared, I don’t know, over ten years ago; it looks like while also, out of one side of their mouth, claiming that there is no opposition to their soft fork and it has consensus and it’s happening. They’re now working on a PoW-change hard fork to fork away from Bitcoin proper by changing the mining algorithm. So, while the public messaging is claiming that everybody is going along with BIP110, they do apparently understand the technical details well enough that they see the writing on the horizon and are working on a PoW change. So, I think 110 will be a funny but clear respite from the more dire news this week on Saturday, as we see BIP110 proponents sail away on their forked coin.

Why use ElligatorSwift encoding in BIP324?

Mike Schmidt: Interesting development, Murch, I hadn’t seen that. Okay, wow. All right, let’s move along with the Stack Exchange, “Why use ElligatorSwift encoding in BIP324?” BIP324, as a reminder for listeners, is the encrypted transport between nodes, so you’re communicating encrypted as opposed to plain text, which is the previous way that nodes would communicate with one another. And Pieter Wuille actually answered this. Oh, sorry, Murch?

Mark Erhardt: I was just looking at my notes and I had a very funny little fact that I wanted to add. Can I go back to the 55% signaling threshold?

Mike Schmidt: All right, Murch is going to make a joke. Let’s do it. You’re interrupting Pieter Wuille in this very serious engineering work for it!

Mark Erhardt: I was looking at BIP8 yesterday and I realized that BIP8, during the mandatory signaling phase, only requires a threshold of the blocks to signal. So actually, instead of requiring it from all blocks, the old soft fork proposal, that one of the co-authors was Luke, only required the threshold to signal. So, only about half of the blocks would be required and it would only reject some blocks, and it would have been way safer to try to activate that way, because it would have allowed for some stragglers with the upgrading. But for some reason, the people that designed BIP110 did not really look at existing BIPs that solved the same problem previously and did not consider this.

Mike Schmidt: Murch, you mentioned the hard fork thing, and now we’re back on this topic. Now I have a question for you.

Mark Erhardt: All right, sorry.

Mike Schmidt: If BIP110, let’s assume they get zero blocks come Saturday, just for whatever reason, the 2% becomes zero, people are worried that it didn’t hit 100% or whatever, and they stop their mining, and the chain doesn’t advance, the PoW change is put in and deployed to those users, and you have this new chain. I guess that soft fork never activated because it didn’t even get to one block, but it also didn’t get to, I guess, technically the activation phase either. So, all of that together would equal just a hard fork then, right? There actually wouldn’t have been a soft fork and then a hard fork fork; is that right?

Mark Erhardt: Well, currently it would look strange if they didn’t get any blocks at all, but I would expect that the Bitcoin chain tip, or sorry, the non BIP110, the default chain tip would advance about 39 times faster. Yeah, so we would probably see a lot of blocks on the non-signaling chain just charging ahead, and then maybe we would see a couple of blocks on the BIP110 chain. However, miners are paying for their mining and they constantly pay for the electricity. So, if there is a number of blocks that don’t signal, miners very well might reconsider. So, rolling out a hard fork on short notice is going to be quite the adventurous project as well. Obviously, nobody will follow a hard fork unless they upgrade the software. They would, at best, be guessing how many people go along with it. And then, they would additionally require people to first upgrade their software in order to even consider the hard fork change. So, it will be a very strange situation where their chain tip is probably not advancing more than one or two blocks per day, maybe three at most. And then, they’re also trying to rally the supporters of BIP110 to do a much bigger change to actually hard fork away from the main Bitcoin chain and roll out software upgrades.

I was looking at the listening node population recently, and a solid portion of Knots nodes and even BIP110 nodes were still running the old version, and they had a consensus change in one of the upgrades. So, even among the nodes that support BIP110, the listening nodes, not all of them are running the latest version. So, trying to roll out a hard fork in maybe under a week or under two weeks, well, I don’t know, doesn’t sound all that promising to me. And meanwhile, they basically will have block space for under three blocks per day to get all of their transactions in. So, I don’t know, that seems extremely discouraging. So, I would think that many people at that point would say, “Yeah, this is not happening”, even if they were in support before.

Mike Schmidt: Okay, back to ElligatorSwift and BIP324. And Pieter explained that encoding the handshake’s public keys as uniformly random bytes makes the entire v2 transport or BIP324 communication byte stream look pseudorandom. Obviously, there’s benefits to having this encrypted, but there’s also benefits to having it look pseudorandom, one of which I don’t think is being taken advantage of is you can send decoy messages, you can also have this traffic look like it’s behaving like other protocols potentially. Anything else advantageous or notable about ElligatorSwift?

Mark Erhardt: Yeah, so ElligatorSwift is used to make the bytestream look pseudorandom. So, it just is fairly indistinguishable, except by looking pseudorandom. It would make it a lot harder for intermediate nodes to filter this traffic, right? They’re just seeing some pseudorandom bytes flow by, and there isn’t explicit strings to filter for, “Oh, if this message part comes along, there’s a Bitcoin node, and I’m going to drop the traffic”, or anything like that. Being pseudorandom means that it would be much more involved to write a filter for dropping those packages. And yeah, it would make it easier to potentially, in the future, make Bitcoin traffic mimic other protocols, parrot the behavior of other software. So, maybe just to be clear, BIP324, the v2 transport, in the first handshake, very briefly, it is visible what’s happening. But then, after that, even for future key rotations and so forth, all of the traffic is encrypted and looks pseudorandom. And yeah, it is currently easy to man-in-the-middle if an active attacker were trying to do so, because it is encrypted but not authenticated. So, a man-in-the-middle attacker would be able to run a Bitcoin node that speaks the protocol, decode what comes from one side, and re-encode it for the recipient on the other side.

So, this is not a perfect solution for when someone is actually running infrastructure to man-in-the-middle, but it makes it much more expensive to track what’s going on if you’re not actively attacking, but only passively listening. So, passive listeners will now only see bytestream soup and, well, they might see, “Oh, a new Bitcoin block was found, so probably this burst of traffic is a Bitcoin block being announced”, so traffic analysis would still identify that people are running Bitcoin nodes potentially, but it takes a lot more effort for servers along the way or internet nodes to determine what traffic is going on there.

Was the OP_SUCCESSx reservation in BIP342 designed with specific opcode families in mind?

Mike Schmidt: Next question from the Stack Exchange, “Was the OP_SUCCESSx reservation in BIP342 designed with specific opcode families in mind?” So, Murch, you answered this, so maybe you should answer this.

Mark Erhardt: Sure. To my knowledge, people did not have specific opcodes in mind that they wanted to add. If they did, they haven’t told me. But generally, the OP_SUCCESS upgrade path is much more elegant than the one that we had before, which was OP_NOP. OP_NOP stands for ‘no operation’, and no operation means that an opcode is just not doing anything, it’s inert, it doesn’t make any changes, it’s just popped off the stack and nothing happens. So, what we can do with OP_NOPs are upgrades that do not change the stack. So, for example, if there were a new signature validation opcode, we could read the signature from the stack and we could read the message from the stack, or whatever is being signed and the public key, and we could have a result. So, for example, we could fail if the signature is not correct, but we can’t pop the public keys and signatures off the stack as we consume them, because now, if an old node were processing the OP_NOP as an OP_NOP where nothing happens, and a new node was processing the OP_NOP and it changes the stack and now there’s a different state in the validation of the transaction, that would be a hard fork.

With OP_SUCCESS, they work differently in that even if they’re not executed, just by being present in a script, they always make the script succeed. So, an old node that would process a script that includes an OP_SUCCESS will see, “Oh, there’s an OP_SUCCESS here. I succeed. I don’t have to do anything else”. And a new node that can interpret the new meaning of the OP_SUCCESS opcode that now has, I don’t know, maybe a covenant meaning or a signature check, can do whatever they want with the stack, can put new elements on the stack, can pop off things from the stack. And it is now a pure restriction on what was previously allowed, where it doesn’t change how it is evaluated by someone between a successful use of the new opcode, and a successful interpretation of the OP_SUCCESS that had no meaning.

So, while I don’t know of any specific upgrades that were in mind, OP_SUCCESS just makes it way easier to introduce new behavior with new opcodes, and it is much more powerful than OP_NOP. And OP_NOP also only appears in legacy script. So, we’re trying not to use legacy script too much anymore anyway. OP_SUCCESS is only present in tapscript, so it’s an upgrade for P2TR and maybe other output types that would use tapscript in the future. So, I guess, did I answer the question?

What is the difference between the long-term feerate and the discard feerate?

Mike Schmidt: Yeah, you did, wonderfully. And there’s another one that you’ve answered, which is the next question, “What is the difference between the long-term feerate and the discard feerate? Yeah, so the discard fee rate is used to calculate dust limits. The dust limit in Bitcoin Core is only a policy, so it’s implementation- and project-specific. But Bitcoin Core’s dust limit is calculated from, by default, 3 sats/vB (satoshis per vbyte). And if you spend more than one-third of the value of an output on the output script and input script that would spend it, we consider it dust. That’s how it’s calculated. The discard fee rate became configurable, I don’t know, several versions back. So, if people want to accept outputs with smaller amounts, they can set a lower discard feerate, and then their Bitcoin Core node would calculate lower dust limits. I do not recommend that. I think even though the feerates have been dropped recently, small outputs in payment outputs are still kind of iffy and we shouldn’t facilitate that. But of course, if a ton of people started doing it, it would be hard to block that, just as we learned with low feerates and large OP_RETURNs in the last couple of years.

The long-term feerate estimate is something else. The long-term feerate estimate is a guess on what might be a lower-bound feerate that you would reasonably be able to expect to make a transaction at in the future. So, even if the demand for blockspace gets very high, you probably will be able to make a transaction at 10 sats/vB once per week or so. This is a guest number that yours truly pulled out of his arse. We use that in Bitcoin Core for coin selection. And it is just some guess to where we switch from consolidatory behavior to thrifty behavior. So, above the long-term feerate estimate, we try to build the smallest possible transaction, and are thrifty with our blockspace; below the long-term term feerate estimate, we build transactions that may be more consolidatory and use some extra inputs in order to reduce our UTXO pool. And you can also configure this value if you think that 10 sats/vB is too high to have consolidatory behavior right now. Well, I’ve been thinking about maybe reducing it, because feerates have been much lower than 10 sats/vB. But not too long ago, two years ago, more than 10 sats/vB were quite common actually. So, anyway, Yancy found here a small bug in a fuzz test where a value could be fuzzed better.

What is the quickest method for migrating a legacy wallet to a descriptor wallet on a pruned node?

Mike Schmidt: Next question from the Stack Exchange, “What is the quickest method for migrating a legacy wallet to a descriptor wallet on a pruned node? And Pol answered this one and he explained sort of the core issue with the way things worked previously, which was when you executed a wallet migration, there would also be an attempt then to load that migrated wallet, which if you have a pruned node and depending on the timing and birthday of the wallet, could cause an issue currently. Yeah, go ahead, Murch.

Mark Erhardt: Maybe start from the other side. If you have a pruned node that has progressed past the height at which a wallet was last loaded, the wallet is outdated and your node doesn’t have the information to catch it up to the current chain state. Now, if you’re running a pruned node that currently doesn’t have the wallet loaded, and then you import that wallet and it is of the old format, it would suggest that you need to migrate the wallet. But then, it wouldn’t be able to load the wallet because it doesn’t have the blockchain information to catch it up. So, what it would do, I think it throws an error, although another option would be that it just starts resyncing the blockchain from scratch in order to get back out the old blocks. A potential improvement here would be that instead of going back the entire history and doing a whole new sync, it could, for example, use compact client-side block filters to get just the table of content of those blocks, and test against those whether there’s any transactions that are relevant to the wallet, and just sync the wallet against the compact block filters for the missing height, instead of doing a whole new IBD.

But if you just want to convert a legacy wallet to a descriptor wallet and you have a pruned node at hand that doesn’t have the correct chain, or has already discarded a part of the chain that you would need to bring it up to date, you can use a future argument on the migrate wallet call, which is the load_wallet argument, and just say, “Don’t load this wallet after migrating it”. Unfortunately, this is not released yet. This will come with v32. And if you really, really need to do it right now, you could run the development branch, although I would say be careful, make backups. Always make backups before migrating.

Mike Schmidt: And we did cover that option value edition in Newsletter #412, and we talked about it in Podcast #412. That was Bitcoin Core #35266, as Murch mentioned, also expected in v32 in the coming months.

Is there historical data on orphan/stale block rates during high-fee periods?

Last question from the Stack Exchange, “Is there historical data on orphan/stale block rates during high-fee periods?” And BNOC contributor, 0xB10C points to the stale-blocks dataset, and that’s maintained by the bitcoin-data project that he is a contributor to. It charts stale block rates over time and also provides raw data for deriving your own custom metrics. Yeah, so that’s interesting. Murch, you can comment on that, but you may also want to comment on this idea of parsing around P2P messages pointing out stale blocks or stale tips, I guess.

Mark Erhardt: Right. So, there is a project that collects stale blocks. People have been interested in stale blocks for a long time, because we spend a lot of time improving block propagation in order to reduce the stale block rate, because high latency between mining pools benefits larger mining pools disproportionately. So, the lower the latency is for blocks propagating on a network, the more fair it is for miners, and especially smaller miners, to participate in mining. There is currently a proposal, I think AJ proposed it first, to propagate stale chain tips if we see them on the network. The idea here is when someone finds a block that might have been a little later than a previous block at the same height, so there’s two competing blocks at the same height, it would be useful for people looking into stale chain tips and researching that, or to discover when people are doing selfish mining, or when people are forking off on their own chain tip, 50 blocks behind the chain tip, it would be useful for nodes to be aware of this chain split.

So, AJ proposed a stale chain tip propagation BIP, and full disclosure, two of my colleagues have been proposing and working on an implementation of that. So, there’s currently an open email thread, I think, maybe not a BIP yet, to propose that nodes forward stale chain tips and competing chain tips. The other context is that in May, we had a two-block reorg for the first time in over ten years. I think we haven’t had a two-block reorg, or two-block or longer, since the March 2013 accidental hard fork due to database format change.

Mike Schmidt: Wow, that long?

Mark Erhardt: Yes. So, a two-block reorg is uncommon, very uncommon. The one in May was due to Foundry finding a block right after someone else did, and then while they were working on their own chain tip, as is legitimate, they found another block right after the second block was found on the other chain tip. So, there were two blocks found just seconds after the competing chain tip was advanced. And nobody saw those blocks because we did not propagate stale chain tips. When a node has a chain tip for the for a height already, they will stick to that chain tip until it is exceeded. So, if someone else extends a chain tip past a height, it has more total work and then they will switch to it. They will reorganize to the best chain tip. But if there is a second chain tip announced at the same height, it will not propagate. Nodes that it is announced to will get that chain tip and store it, but they will not forward it, because it’s not their best trained tip.

So, the proposal here is since blocks are always encumbered with PoW, they are very hard to fake, we can safely forward this information to make the network aware that they are competing chain tips. And that is what my colleagues are proposing.

Mike Schmidt: Thanks for that color, Murch. That wraps up the News, Alert, and Stack Exchange segments for this newsletter. Gustavo’s here, who helped us with the Releases and Notable codes, and will take over. Hey, Gustavo.

BTCPay Server 2.4.1

Gustavo Flores Echaiz: Hey, guys, perfect. So, this week we have two releases. Both are maintenance releases. The first one comes from the BTCPay Server repo. So, here, v2.4.1 adds a feature we talked about, I believe last week, about enabling users to add BIP329 wallet label imports. So, that is a new feature. But mostly, besides that, it’s just a bunch of fixes related to integrations. BTCPay Server has a ton of different integrations, so a lot of fixes around that, specifically, those that come out are Boltcard, LNDHub. So, if you use one of those, you should take a look at the related fixes. But just a small release overall and mostly maintenance-focused.

Eclair 0.14.1

The next one, Eclair 0.14.1 is also a maintenance release. Here, the new requirement is that you now need to run Bitcoin Core v31 with Eclair, so that is now a new requirement. And the main bug fix here is that a new feature that was introduced a few weeks ago in Eclair, which basically allowed a recipient to pay for the routing fee of the sender, so the sender could delegate the payment of the fee to the recipient, there was a clash between that feature implemented in BOLT12 payments and multipath payments. So, the bug was that for each part of the payment, let’s say there’s three parts, the sender could basically bill to the receiver the full fee of the whole payment but on each part. So basically, the receiver could pay three times more the fee if the payment was split into three parts. So, quite a serious bug. So, this feature was simply disabled. This feature, called blinded-path fee discount, was simply disabled for BOLT12 while they figure out a better way to ship it to not have this conflict with multipath payments. Yes, Murch?

Mark Erhardt: A very small comment. You said that it requires Bitcoin Core 31. I assume that it requires at least Bitcoin Core 31 and later versions are probably fine.

Gustavo Flores Echaiz: Exactly. Thank you, Murch. So, yeah, there’s also a bunch of other changes. So, if anyone’s curious, they can look at the release notes. So, those are the two Releases of this week.

Bitcoin Core #34628

Next, in the notable code and documentation changes, we’ve got quite a heavy week. We’ve got about five different items from the Bitcoin Core repo. So, the first one, #34628, this one is about relay backlogs. So, when a node is going to relay transactions to its peers, it has backlogs of those transactions and they can just go out at a certain rate. If, let’s say, your node receives 1,000 transactions, you’re not going to broadcast those 1,000 transactions without any limits. There’s a certain size of how many initial transactions you’re going to broadcast. And then, once you reach that cap, then that queue will relay credits, they’re going to update to a certain rate, for example 14 transactions a second. Once you’ve relayed a certain number of transactions, those relay credits will update to a certain rate. Yes, Murch?

Mark Erhardt: I would like to jump in. I very briefly looked at it, but from what I understand, there are two important changes here. One is, so a few years ago, we had an issue where, I think it was during the initial ordinals craze, suddenly there were huge bursts of transactions being pushed to the network. And because they would all get queued by Bitcoin nodes to forward to their peers, and Bitcoin assumed that nobody would ever have to broadcast more than seven transactions per second to their peers, and this huge burst of transaction submissions exceeded that by far, these queues would grow faster than they would be flushed or processed. And then, I think before announcing a transaction to a peer, it would always sort them to have the highest mining score transactions, the highest effective feerate transactions at the top, and then pick like the crème de la crème and forward those first so that they would get propagated around the network the quickest. And as the queue was growing so quickly, sorting the queue over and over again turned out to be basically a DoS vector, and lower-resource nodes would keel over. So, the first solution to that was to just allow sending more quickly, and I think if it grew too quickly, to just throw away some transactions. Transaction propagation is best effort, we do not guarantee that transactions are actually forwarded, we only guarantee block propagation.

So, this is a more comprehensive fix to the same issue, from what I understand. We now queue everything into one global queue instead of having a queue for every peer. So, instead of having the entire mempool queued up to be relayed potentially to every peer, we have one central queue where we just keep what are the best transactions. And then, from the top of that, we feed into personal queues for each peer, where we now have smaller limits. And in the main queue, we have sort of a bucket system, a leaky bucket. As you fill the bucket, it keeps flowing out. The flow rate is limited. If the bucket gets too full, we probably start discarding stuff. But yeah, that’s what the whole credit system and token terminology there refers to. You have a bucket with, I don’t know, a few holes. So, it can only outflow with a steady rate, and there is a bit of a buffer how much can be in the bucket or not.

Gustavo Flores Echaiz: Yeah, that’s exactly what this is about. Just to be precise, there’s actually two backlogs, two global backlogs, one for inbound peers and one for outbound peers. And also, yes, once these transactions get selected for relay to peers, they do enter then small per-peer queues, mostly related to privacy benefits for you as a node. And yeah, I think also the issue before was the duplicate storage. So, yeah, sorting was a big issue, but also you were duplicating storage by having multiple per-peer queues. And now you have global ones, so you reduce considerably storage. And also, you can look at Newsletter #324 if you want to know more about the CPU issue that was related to the first implementation of this. But in the PR of item #34628, in the PR description, it points out to another issue, in February 2026, which we didn’t cover in Bitcoin Optech, called the Runestone surge. So, a similar issue related to mostly CPU exhaustion issues. So, this also fixes that problem.

Bitcoin Core #28463

Next item, #28463. Here, Bitcoin Core simply increases the default maximum number of connections from 125 to 200. So, that is the first change. The second change is a new option, which has a default of 50, called -inboundrelaypercent. What this defines is the maximum percentage of inbound slots for transaction-relaying peers, which means that let’s say now there’s 200 default maximum number of connections, by default 11 are attributed to outbound peers, which means 189 slots for inbound connections. But with this new setting of 50% for inbound relay percent for transaction-relaying peers, means at most 94 of those slots can be occupied by transaction-relaying peers, which means the rest is for block-only inbound peers. And the point of this PR is mostly to later add a follow-up PR that would increase the amount of outbound slots, but for blocks-only outbound peers. So, with a follow-up PR, the goal is to add those outbound peers that are blocks only, and the point here is to improve resistance to eclipse attacks.

Mark Erhardt: There’s two things here to mention. One is people might remember Erlay as the idea of how to improve or decrease bandwidth use with more peers. The idea was to synchronize what people would be announcing to each other, and then reduce the traffic necessary to keep transaction-relaying peers synchronized up. And out of that discussion, people also considered what exactly they were trying to achieve here. And one of the main things that we want to achieve with more peer connections is to make nodes more resistant to eclipse attacks. Block-only connections actually are very important in that regard. They are very hard to recognize by surveillance that are trying to guess the topology of nodes, because block-only peers only announce blocks to each other, so there is no chatter for all of the transactions. And also, if a peer already has a block, the announcement is very cheap. It’s just the block header, the 80 bytes.

So, out of the Erlay discussion, my understanding is that this idea that, “Why don’t we just massively increase the number of block-only connections, because it’s very cheap in traffic and it gets us a lot of the protection against eclipse attacks?” so if we have a lot more block-only connections, peers would announce to each other when they have found a block, and it would be way easier to have at least one peer that tells you about an honest blockchain if you have 100 more block-only peers. So, the idea here is probably to add maybe ten more block-only connections that we make outbound. I don’t know, just guessing, and we allow a lot more inbound block-only connections. So, if there are more nodes out there, especially non-listening nodes that can’t have inbound connections, they’re currently limited to their eight peers with which they trade transactions, their two peers that do block only, and then one feeler connection. And for nodes that are not listening, learning about the best chain tip is a lot more precarious. If eight of their peers or ten of their peers are sybilled, they are eclipsed, if they had ten more blocks-only connections outbound, that would make them a lot safer.

Bitcoin Core #32800

Gustavo Flores Echaiz: Thank you, Murch. Next item, Bitcoin Core #32800. Here, we’re now defining on several mempool RPC commands. Different fields now define different measures that are for transaction virtual size. So, there’s the BIP141 segwit virtual transaction size measure, but there’s also another thing that Bitcoin Core defines as transaction size, which is something related to how the mempool calculates transaction size. So, there’s this setting -bytespersigop operation. So, this setting, you basically define how many virtual bytes does each signature operation require, because each signature operation has a computational cost to your node to verify. So, basically, the mempool, when measuring transaction sizes, doesn’t just consider the virtual size, but also considers the computational cost that validating each transaction that has signature operations will have on the node. So now, this item basically introduces new fields for both the BIP141 transaction size, and policy-adjusted transaction size, as defined by the option -bytespersigop. So, this is added in a bunch of mempool RPC commands, but these two fields are now split into a bunch of RPC commands that already had the field, but it was a bit confusing which field was exactly defined. It was documented as the BIP141 virtual size, but actually contained the policy-adjusted value.

So now, there are two fields. The previous field, just called vsize, is kept, but is actually marked as deprecated. And some other commands now have those fields as well, such as getrawtransaction now reports vsize_adjusted when the transaction is in the mempool only. And the verbose output of getorphantxs also adds the explicit vsize_bip141 field.

Bitcoin Core #34683

So, next item, Bitcoin Core #34683. Here, an automatically generated description of the RPC interface is added for the protocol OpenRPC 1.4.1, which is a standard to define or to document RPC commands, also described as a standard programming language agnostic interface description for JSON RPC 2.0 APIs. So now, every Bitcoin Core node, when compiling, will generate at runtime from the RPCHelpMan metadata for all registered RPCs, will generate an open RPC description of the RPC interface. And there’s two new RPC Methods: one, rpc.discover, which returns the public interface; while getopenrpcinfo can optionally include all the hidden commands and the arguments as well. So, I’m guessing this is also very helpful for LLM models to read, in real time, the RPC commands of a specific Bitcoin Core node version.

Bitcoin Core #33014

The next item is a bug fix in Bitcoin Core, item #33014. This fixes how descriptorprocesspsbt, which is an RPC command that was documented as added in Newsletter #253, can be used to update an RPC with information that will help it later be signed or finalized. The problem here was that descriptorprocesspsbt was marking the PSBT as complete without properly checking if the signatures were valid inside the script fields. So, the RPC only checked for the presence of the final scripts, didn’t check if the signatures that were present were valid, would mark the PSBT as complete; but later, when transaction extraction would happen, that’s when an error would get returned. So now, this RPC is updated to verify every input, verify every signature before reporting completion, and simply return that it’s not complete if it has an invalid signature, instead of returning as complete.

Eclair #3325

Now, we get into the Eclair repository followed by 3 BOLTs items. So, Eclair #3325, here, Eclair now accepts BOLT12 invoice onion messages that include a reply_path. And a reply_path is something that a payee attaches to an invoice so that the payer can return an invoice error if it considers the invoice invalid. So, if I send an invoice to a payer, they can basically return to me that they consider that this invoice was invalid. So, we covered in Newsletter #321 that LDK added support for introducing reply_path in BOLT12 invoice onion messages, and this was causing some incompatibility issues with Eclair. So now, Eclair has updated its BOLT12 implementation to accept, not necessarily allow users to create, but to accept BOLT12 invoices that include reply_path in their onion messages.

BOLTs #1346

So, now we jump into the BOLTs section. We have three updates to the BOLTs repository, which defines the protocol for the LN. The first one is a new protocol, called BOLT12 payer proofs. We talked briefly about this in Newsletter #405, because CLN took a step in advance and actually implemented an experimental version for BOLT12 payer proofs. So, what BOLT12 payer proofs is, is a receipt format that basically allows a payer to prove that they paid an invoice using not only the payment preimage, but also the invoicing node’s signatures, so the recipient’s node signature, and also the payer signatures from the invoice request, which basically allows a payer to prove to a recipient, or to someone else, that he has successfully completed the payment of a BOLT12 invoice. So, CLN, like I said, is the only one that has implemented this, but probably an experimental version. So, we should probably expect CLN to update its implementation now that the BOLTs repository has included a final version for the BOLT12 payer proofs protocol.

BOLTs #1344

The next item is BOLTs #1344. Here, the protocol called attributable failures, which allows a node to basically know where an error message got corrupted, for example, if I make a payment and it fails at a specific node, I’m going to get an error message back, but a node in the way could sabotage that message, attributable failures allow us to identify approximately the node that would sabotage the message that was being returned to me as the payer. So now, BOLTs #1344 extends this protocol not only to failed payments, but also to successful payments. So, it adds a new optional message, called fulfillment_payload to the update_fulfill_htlc message, which is what I get back when an HTLC (Hash Time Locked Contract) payment has been successful, or also known as the message that returns the payment preimage and settles an HTLC.

So, this field is defined, but the PR establishes the transport mechanism for success-related data. However, it doesn’t standardize any specific message or any specific application. However, the PR description says that one motivating use case is proof of payments for spontaneous payments, also called keysend payments, where the sender picks the preimage so it cannot serve as proof. So, yeah, so this is just a system, a transport mechanism that extends the attributable failures protocol to success payments as well, but doesn’t specifically define any application. It just creates the transport mechanism for it.

BOLTs #1343

And finally, the last item of this section in this newsletter, BOLTs #1343. Here, a new feature bit, or a new option, is added, called option_onion_message_only_channels, which basically allows a node to signal to its peers that it only accepts onion messages from channel peers, or to signal it to the whole LN. So, I’m suspecting that the motivation here is that in Newsletter #409, we covered that LDK stopped using remote introduction nodes for BOLT12 blinded message paths, because LND would simply accept onion messages from channel peers. So, LDK had to adjust its internal implementation to ensure that it would always be compatible with how LND had implemented the onion message protocol. So now, this new feature bit, or option, would allow an LND node to basically indicate to an LDK node, or just the global LN as a whole, that it only accepts onion messages from channel peers. So, with this option, LDK can simply go back to its previous implementation, where it was using remote introduction nodes for BOLT12 blinded message paths, and basically ensure that it checks if an LND node or if another node simply accepts onion messages from channel peers, in order to not use them to forward onion messages.

So, this new option allows those LND nodes, but any node, to now advertise that it only accepts onion messages from channel peers. However, a node can, even if it accepts messages from peers without channels, it can still rate-limit or drop them, which has been a whole question for implementing onion messages in all of these different Lightning implementations. So, that is the final item and completes the section and it completes this episode. Thank you.

Mike Schmidt: Thanks, Gustavo, and thanks for co-hosting. Murch, thank you also for co-hosting, and we want to thank Rob, Portland, Chand, and hax for joining us earlier, and for you all for listening. We’ll hear you next week.