2019-06-06

Great consensus cleanup https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-March/016714.html

https://twitter.com/kanzure/status/1136591286012698626

Introduction

There's not much new to talk about. Unclear about CODESEPARATOR. You want to make it a consensus rule that transactions can't be larger than 100 kb. No reactions to that? Alright. Fine, we're doing it. Let's do it. Does everyone know what this proposal is?

Validation time for any block-- we were lazy about fixing this. Segwit was a first step to fixing this, by giving people a way to do this in a more efficient way. So the goal of the big consensus cleanup is to fix that, and also fix timewarp, we have known about this for a long time and we should fix it. Three, we should do a soft-fork that is not the most critical thing and thus can be bikeshedded a little bit and if it doesn't activate then nobody is too sad. We can do it for the sake of doing a soft-fork and get something through and work our way through any problems that might emerge, prior to doing something more involved like Schnorr signatures.

Is there a risk of normalizing soft-forks? Maybe, but this isn't frivolous.

Timewarp

The soft-fork fix for timewarp is actually simple. I would like to get that pull request in. What is the fix exactly? The issue in timewarp is there's an off-by-one in the calculation of the height for difficulty adjustment. You can jump backwards or forwards significantly, not sure, just on the difficulty adjustment block change. If you just constrain those two blocks to be well ordered, then fine, timewarp is gone. So you just add a new rule saying these blocks must be well-ordered. If you set that rule such that it can go backwards up to 2 hours, then there should be no impact where a miner would generate such a block. The timestamp is allowed to go backwards no more than 7200 seconds.

Having a rule in between the two difficulty periods, and any constant limit on how much the time can go backwards, fixes the timewarp attack. Based on how many seconds it's allowed to go backwards, there's a small factor in block speedup that can be achieved but it's always bounded. If it's 600 seconds going backward, then actually the bound is exactly what we would have wanted in the first place, namely 2016 blocks per 2 weeks. If you allow it to go back more, you allow slightly more blocks. If you allow less, interestingly, you have fewer block.

What about using timewarp for forward blocks? Someone asked about doing forward blocks on litecoin. But litecoin had merged a timewarp fix a long time ago.

Is the timewarp bug something we should fix? Slushpool had feedback. Is it only Mark that wants to use it?

The best nrolling you have is to generate a bunch of midstates, and increment the timer by one second. Nobody does n rolling in hardware yet, but people want to do it. This is probably why the slushpool people were concerned. Median time past might be in the past, and the prior block might be 2 hours in the future, and therefore you're more than 2 hours behind the prior block. This is why it's allowed to go back by 2 hours. Median time past can be in the past, and the prior block can be 2 hours in the future. If you wanted as much n time rolling as possible, you start with median time past, and right now people start with current time and they don't really do n time rolling. There's basically no reason to n time roll significantly in the future, as long as you can store a bunch of midstates for every 1 second. You could argue there's no reason to do this, or you can't do this. There's no reason to do this, and nobody is doing it as far as I can tell.

The only evidence we saw of ntime rolling was up to maybe 10 minutes or something, we looked. The only times that jumped backwards were probably other issues. Do people mine blocks with timestamps in the past? Yes, but that's a different thing. No, it's not. It's old work. I only update you every 30 seconds. Someone else can screw you by mining a block 2 hours in the future. If you start at the current time and someone mines a block 2 hours in the future, that's always okay. You would have rejected a block more than 2 hours in the future. You'll meet the rule. They do mine in the past, but it starts with the time in the header, but they find it later in the future. Nobody mines a block whose timestamp is older than the actual time for the prior block? No, nobody does that. With miners, you do see that because stratum updates periodically, pretty much all miners are mining 15 seconds behind because they update every 30 seconds so on average that's 15 seconds. But you always start with the current time when the stratum job is generated and sent to the client.

How much does current time vary between miners? A few seconds. Harold crawled the bitcoin network and found that 90% of listening bitcoin nodes have a timestamp that is within the measurement accuracy of me. People without an accurate clock, are like 2 days off. So yeah. When you connect, the version message has the current unix time, system time. It's network-adjusted time, I think so? That would be infectious wouldn't. You announce system time, but you use the network-adjusted time. Your crawl data is still useful because it tells you the network-adjusted time. Pool servers probably do their own thing.

Does bfgminer or cgminer currently have any code to reject their pool telling them to participate in a timewarp based on previous headers? Clients don't do anything, nor should they. An ASIC should not be interpreting data based on consensus rules. It's stupid. bfgminer does some insane shit but that's because bfgminer is insane. In general you want the miner to be as dumb as a brick, they just throw out work to an ASIC. Right now they are too smart for their own good because they see the coinbase transaction.

So you crawled node times, but did you look at pool times? No, I didn't get around to that. I was just looking at the bitcoin network and comparing their clock to my local clock. Almost all pools have a listening bitcoin node on the same IP address, which is weird. But for those who don't, they have a pool, and then a node in the same rack or data center running a bitcoin node and then maybe an internal bitcoin node that is not listening. In general, the clocks seem to be within a second, which is roughly what you would expect from NTP plus or minus a few seconds. A whole bunch of people are an hour out. It's probably buggy timezone. Buggy daylight savings time, probably. And Windows setting local time instead of setting to UTC. There's a 15-minute time zone. North Korea has the worst timezone stuff ever. Well, that's because they don't care about the rest of the world.

More on the great consensus cleanup proposal

There's a bunch of rules, including 64-byte transactions which primarily impacts segwit transactions. Yeah, that's another thing. The codesep thing is only ever intended to be for non-segwit transactions but maybe we will drop that in favor of a 100k rule. But the 100k rule is only for legacy? I haven't thought that far ahead. It should be 100k base size. You could just say 100k base size, and then it applies to segwit as well. Or 400k witness, really. 100k strip size, is what you want, right? Base size is weird language to me. Witness strip size, no more than 100kb should be the proposal. That's the only thing that matters to the sighashing rules. But you could also do it by witness weight because that's how we calculate size now. You're right, if you want to attack the exact thing that is causing problem, you would do it by.... we don't want to do it to the other thing because if you have a giant witness. Do we want witnesses larger than 400 kb?

Are you proposing this as the next soft-fork, or are you arguing this should be the next soft-fork? Given where we are on taproot, it seems possible that trying to do something first would only push that out further. Well, it was intended to be faster, but nobody really reviewed it or gave a shit, so whatever. It is completely orthogonal. It could happen in parallel, there's not really any harm to that. Also, if community agreement is there, there's no reason why they couldn't be activated at the same time if the agreement is there.

These DoS vectors, the timewarp bug and the sighash stuff-- how much time would we have to deploy a soft-fork like this and have it ready? If something bad happens... we've seen bad things happen, we've seen blocks that take way too long to validate. It's been exploited before. Timewarp is a different question. Timewarp can we deal with that when it happens? No, suddenly a timewarp block comes out and then we know it has happened. Exploiting timewarp is a very slow process. It's in multiple months, so we could choose to deploy the soft-fork then. If timewarp is happening then it's because the miners are doing it, who you need for the soft-fork activation that case. For sighashes, you need to setup 100's of thousands of UTXOs and we can see that particular one. But the f2pool-style dust cleanup isn't really that bad, but it's pretty nasty. Large scriptpubkey size, 10 kb scriptpubkeys or something.

If you want to do something non-controversial and easy to do a soft-fork, then I believe a 100kb size limit will make it very controversial. Any kind of size limit on transactions I expect to be controversial. It's been non-standard for 5-7 years forever now. Would this interfere with confidential transactions? Well, arguably it should not be effecting witness data. It wouldn't apply to that anyway.

What about the big giant transaction per block, giant coinjoin transaction with Schnorr? If you have a new signature scheme, and and and this other stuff, then maybe. The new sighash type in segwit generally prevents this, so you could say only non-witness ... only the data that is relevant to non-witness inputs, which mostly corresponds to the witness strip size. Only then do you check if it's over 100kb and if it is, then you fail. You want to be able to do it without validating the scripts. Counting the number of legacy inputs and put a limit on that. You can lookup the UTXOs, but you don't have to validate them. A second type of witness that gets added... you would not be counting that, so it's kind of dangerous, if we predict that.

Another comment, you really need numbers to show people that this change reduces the worst case. Yes, I have numbers. Having those numbers would be great for convincing people. I haven't gotten around to rewriting it yet. Nobody appeared to really care.

Soft-fork

Since the timewarp rule has not been violated, maybe nobody upgrades- how do you tell? Well, if they mine invalid blocks then it won't be accepted by the network. You don't have the assurance, except that everyone is running Bitcoin Core. If you start losing money, you're going to fix your shit very quickly.

The BIP says use bip9 versionbits with an explicit promise that if the nodes and ecosystem appear to upgrade robustly, and bip9 times out, then there will be a second bip9 signalling window in a future release where that bip9 signalling window times out with an activation instead of a timeout. With the signalling of bip9. Yeah, that's bip8. So yeah first don't make it explicitly activate, just see that everyone wants it, then you could see activation and see in the network and there's still-- we still want to use bip9 but you have to meet us there, otherwise bip8 and the carrot and the stick. Client could have an option to let you in the current release wihtout upgrading to add the new signalling parameters. That's kind of crazy. Then there might be people too impatient for bip9 to timeout... configuration file consensus is not the right way to go.

I don't want to get into an argument about UASF. It's better to have the conservative and slow approach for making sure we really have consensus for these changes. Why are we in a rush? Will there be any resistance to a soft-fork at all? I think this isn't simple enough. The codeseparator stuff is going to get removed from the proposal. There's a lot of undefined details still. It's a good idea. If we didn't have taproot potentially ready also close... be careful how you phrase that. What's the reasoning for fixing multiple vulnerabilities instead of just one? There's a lot of overhead to doing a soft-fork, and a soft-fork just to remove 64 byte transactions I don't think that sets the precedent on how soft-forks happen. We shouldn't be setting a precedent of doing a soft-fork every 6 months. Yes, there's overhead and risk to soft-fork. If you have a bunch of uncontroversial things, then sure it is helpful to bundle them. Also these have to be super simple. Matt has a few things that are pretty straightforward, and they have to be adequately socialized to tell people why it's important. Well, we want to avoid omnibus soft-forks. Not that this is happening here. There's a balance, of course.

It should be uncontroversial and simple which will make it go faster. But we also need to be highly motivated, which makes it go faster or smoother. I think this is an argument for taproot. I think that has been socialized for way longer. I think people understand might be a strong word, they get there's a benefit to them for this, whereas this stuff might be less clear. There will be drama around activation method. The twitter community is all the UASF morons.

You guys don't like bip8? Doing bip8 out of the gate is shitty. This is like saying Bitcoin Core developers have made the decision. You need to make it real for people, before you can know there is consensus. This is what bip9 allows for. I think you rollout with bip9, and then it should be likely you see adoption from nodes, miners might be slow, but who is going to object to it?

If we're going to throw manpower at something, why not something like taproot? Well, you have to fix these real vulnerabilities at some point. It's a question of sequencing and when do you do this? This might be true if we do a good job of motivating this and explaining it to people.

I would make a superlong bip9 window. If it happens before taproot that's great, if it happens after taproot that's fine. We would say we would like this to get out there, but it's not urgent. We don't want to set a precedent for setting two soft-forks because if you upgrade you get... we start with one, and then later we do the taproot one. They have to be separated one year or whatever. I think this discussion is premature until we have a clear idea of whether the ecosystem wants these changes. You can talk about activation mechanisms in the abstract, sure.

The taproot BIPs are relatively new. I would try to make the argument you don't get a clear picture of that until you write the pull requests and start writing code and merging and that's when you get people to understand this is real. Reviewing and publishing and merging the code is independent from the decision to add an activation mechanism. Don't you at least need a plan? I guess you can change the activation mechanism is going to be.

I would like to see more code for the cleanup soft-fork. Yes, there is a patch and pull request. It was just in one blob. No, there's tests and everything. The code is fairly readable. When I last looked it didn't seem separated. Fanquake, it needs to be tagged "needs author action". It's 5 commits, I'm looking at it right now.

You could also pull a Satoshi and do a commit "change makefile" ((laughter)).

There's a mining pool censoring shielded transactions for zcash. Bitcoin Cash miners have already activated a fork for Schnorr signatures so there's at least some interest there.

Do a bip9 signaling mechanism, do a release with it, really publicize it. The potential for controversy is higher with the great consensus cleanup because it's closer to bikeshed. But Schnorr-Taproot is Pieter bringing the tablets off the mountain ((laughter; nobody wants that)).

What about splitting up the great consensus cleanup? You overestimate how much people follow any of this stuff. They generally don't. What would be terrible about having multiple soft-forks? Well it becomes 32 combinations to test. Partial activation nightmares.

I don't think these soft-forks can be done in parallel. We're not good at managing social expectations in this project or communicating them in a good way. If we try to do this for two things, I think we're going to do an even worse job. I think it's better to focus on one thing, focus on how we're communicating it, how we're signaling there's consensus on this first before just throwing it out there. If we're doing two soft-forks, it's going to be confusing to us whether each of them have consensus or whatever, forget about how everyone else perceives it. None of the problems in the great cleanup soft-fork are particularly sexy, so you will struggle to get anyone motivated and interested. But if you have numbers, then maybe. I don't know how much to prioritize this because I don't know what the numbers are. It's weird to say "it's hard to justify, so we should just do it". I'm not saying hard to justify, it's just not sexy. It would be hard socially to get OP_CHECKMULTISIG soft-fork bug fix deployed, because it's just a byte and most people don't care. Well, we haven't tried to get people excited. It's hard for even me this is important, it's just not an exciting topic. If this group isn't superexcited about it, then how could the world get excited about it? I can't even remember the full thing and I wrote it.

It's significantly less exciting than taproot, and it could help build an understanding of soft-forks going forward, and then you do something that is more likely to result in drama. This soft-fork doesn't have any direct benefits so it's easier to argue against it. Well, we don't even have the performance numbers.

If you want community consent for these changes, which is what you need to make the changes, then despite how new the taproot stuff is, the general idea has been socialized for so long that we're in a good place for moving forward especially since it takes a long time anyway. But these cleanup ideas haven't been socialized, and packaging them up into something like this is recent. If we were going to leave the cleanup sitting out there for a while and signal that we're as a group think this is something we should do, it's probably the next thing we will do after taproot, then people will expect it. They expect Schnorr right now, and they should expect these cleanups. If there's determined opposition for those changes, we will have time to see what those arguments are.

We know the worst case performance is bad, but what we don't know is how much the cleanup soft-fork would improve things, like validation attacks. What if this was exploited, and we tell people ah well we knew about the vulnerability and we just did nothing about it. Timewarp has been well documented for 8 years now. It's theoretically possible for someone to construct a block that takes a long time to validate and there's negative repercussions from that. Is it going to be one block, a lot of block? How likely is this to actually happen? To be fair, it's been documented for years and most altcoins have fixed it. Bitcoin may never do it because it's a hard-fork used to be the old argument. Very early on I think people thought it was a hard-fork but that hasn't been the case for a while.

There was a large timewarp attack in 2013 against an altcoin that didn't fix the timewarp vulnerability. There was also a recent one, the two proof-of-work balancing thing and a timewarp attack.

As for activation ordering, I think it might be reasonable because it's a common pattern that people are used to, to maybe suggestion to do one feature fork, one cleanup fork. This could prepare people in a way with not so many drawbacks. I like that, and the suggestion to socialize it, which hasn't happened yet. We've been socialing removing CODESEPARATOR for like 4 years. At a developer meetup in SF a few months ago, CODESEPARATOR was news to them. There was no discussion about the timewarp fix there, but about CODESEPARATOR and the sighash modes I think-- what were the three things? 64 byte, codeseparator, pushdata requirement, scriptsig push only. I think 80% of the discussion there was about OP_CODESEPARATOR. If that's any indication; but it might be random crowd behavior. I think that's the correct indication, I think. It's hard to understand the utility of OP_CODESEPARATOR, and lots of people think they have found a use case, but it almost never works for anyone. It's not that it's useful, but that someone might think it's useful and therefore might lock up their funds permanently, which makes this discussion even more difficult. You could get around this with well any transaction created before this time and after this time, and then you have context problems...

Also, for the 100kb transaction limit, there's discussion to be had about setting precedence. Ignoring OP_CODESEPARATOR for a moment, what do you do if you want to remove something like that? It turns out it's a major vulnerability, but some people might have funds locked up with it, so what do you do about it? We haven't done much with soft-fork cleanups or vulnerability-fixing soft-forks, so how do you set precedent for removing something like that? I was a fan of doing something like, from activation of the soft-fork it's now 5 years before activation. Or it only applies to UTXOs created after the activation date. I'm also a fan of activating it for all UTXOs created after the soft-fork, and then 5 years later we activate it for all the old UTXOs before the soft-fork activated.

Probably going to drop the OP_CODESEPARATOR change. It turns out to not be.... there are some classes of transactions where it's really annoying for total hash data usage, but if you want to maximize total hash data usage, it's not really the immediately worse thing, it's not the way you would actually do it, especially if you add a 100 kb transaction limit. I have a text document where I wrote all of this up, it's been a while.

Does anyone really adamently think this should be deployed before the taproot soft-fork? It depends on activation. The question I'm most interested in, is this a good idea or not? I feel like that question hasn't been answered. If the soft-fork is useful, we should do it. Does anyone not like the idea of doing these cleanups? It depends on how much it improves the situation. 64-byte transactions- you don't want to soft-fork those out? I definitely want to soft-fork out the 64-byte transactions. I want to fix timewarp, too. We need to clarify things more, get some numbers, and then let things sink in. Also we have to figure out how to communicate these unsexy things to the Bitcoin community. Who is going to champion this to the community? We might be overestimating how much users care about this; why didn't we fix this earlier, okay just fix it. The way to do it is brand it, call it time bleed ((laughter; no don't do that)). Timewarp is a pretty good brand, except that it sounds cool or good.