-
Notifications
You must be signed in to change notification settings - Fork 37.2k
Transition to requiring block height in block coinbases #1526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Does it stop being enforced if ver=2 falls below 75% majority later? |
Does it stop being enforced: yes, whether it is enforced or not depends on the previous 1,000 blocks. If more than 250 of the past 1,000 (starting at the block before the block being considered) is nVersion=0 or 1, then the rule isn't enforced. |
Is that intentional? Would there be any harm to having a point of no return? |
RE: point of no return: I don't see a good reason to write code to do that, and it would be hard to test (would have to notice when we hit the point of no return and record that in the block database, I suppose, then read and pay attention to that database setting). |
If there isn't a point of no return the transition for this particular feature can never be removed. If there is, then once its hit after the next checkpoint has been set the code for counting the quorum for this could just be removed and replaced with a simple height comparison. |
As I read the code of commit 93fdc48, it does not do what I expect. A version>1 block with invalid height is simply an invalid block, to be unconditionally rejected. No need for supermajority check. Nobody generates version>1 blocks right now (right?), so it should be fine to simply publish a BIP and note the new rejection policy. The logic just described could be deployed immediately. |
@jgarzik Then I, Greifer Mc. Greifer, mine a single invalid v2 block. The super majority of nodes will happily extend it and continue the chain, the minority of upgraded nodes will reject it forever and ignore that chain. Nice split you've got there. |
And perhaps half as importantly, that would be an abuse of the centralization in a single client to force a blockchain rule through like that. Besides, @sipa already was working on a proper "block/transaction version rules" BIP. |
@jgarzik Yes, I did. Sorry. |
RE: locking issues setting strMiscWarnings : before this pull, strMiscWarnings is set from exception handlers (a "should never happen" case) and AddTimeData(), which is called from ProcessMessage when a new node connects. The new code is in ProcessBlock(), which is also called from ProcessMessage but is also called from -loadblock. I'm tempted to ignore locking in this case, because I think the risks of doing something like protecting strMiscWarnings with a new critical section outweigh the benefits, and worst-case scenario is somebody running an obsolete version of bitcoin with an incorrectly set system clock has a small chance of getting a crash or garbled message. |
What would be needed to create a split with the code as it currently is? |
@rebroad it can't make a split as it currently is, but because the v2 blocks are not enforced as it is a malicious party who wants to create trouble by mining duplicate coinbases could do so by just choosing to mine v1 blocks. Basically the patch as is only protects against mistaken duplication by incorrectly modified mining code. |
As the pull request stands, the only way to get an orphan chain is:
25% of the network would build on idiot's block, the other 75% would reject that chain. |
@gavinandresen but as soon as the 75% produces two blocks (or whatever is require to get ahead again) the 25% moves back. (thus the distinction between a split and a orphan-stub: a split never heals) |
@gavinandresen thanks, you answered the question I had intended to ask. |
@gmaxwell : I think of orphan-stubs as temporary splits, and use the term "hard fork" for permanent splits (but don't really care about vocabulary as long as we all understand each other). Ok: One issue remains with this: should this pull include rules for eventually rejecting nVersion=1 blocks ? If that is not done now, then we'll be bumping block.nVersion=3 in a year and writing code that says "when X% of the network is v3 and less than Y% is v1 then reject nVersion=1 blocks as too old to support any more." Suggestion from @gmaxwell in IRC is: stop accepting v1 when v1 blocks are 5% or less of the last 1,000 blocks |
Agree with what someone (@gmaxwell?) said on IRC, about stopping v1 acceptance: don't make it a software rule that can "flap" (rule switches on and off and on and off). Just pick a height, once you hit 5% or whatever threshold. |
ACK |
I think we can add the "reject v1 blocks" rule later without bumping to version=3; since all the "this generation" nodes will enforce it so long as the majority remains over 75%, the only risk is someone making version=1 blocks having more than "future v1-rejecting version" plus this version combined... |
@jgarzik: once past 95% v2 blocks (assuming there's consensus on "orphan the last 5% of miners who refuse to get with the program and upgrade") there will be no flapping, because 95% of the network will reject v1 blocks past that point. The release after that happens a checkpoint can be added and the code can be simplified to "require valid v2+ blocks." @luke-jr: so we release code that creates v2 blocks, but always accepts v1 blocks. Then a while from now we release code that creates v2 blocks but rejects v1 blocks if some threshold has been reached. If I'm a miner, why would I risk running that code; I need to SEE network support for the "reject v1 block" rule before I start doing that. |
Added a commit with a "reject nVersion=1 blocks when 95% of the last 1,000 blocks are nVersion=2" -- the point of no return. |
Code ACK IMO this warrants a BIP |
I ran my 'coinbase_integers.py' tool on the chain, and somebody is producing block.nVersion=1 blocks with blockheight-1 in their coinbases; see blocks 172036 or 174854 for example (coinbases start with PUSH 172035/174853). Interesting, but not a problem. There are also some accidental "looks like a block height" blocks (e.g. block 164384 starts its coinbase with PUSH 1983702). That opens a tiny window for whoever created block 164384 to try to create a duplicate coinbase in the year 2046 when block 1,983,702 is mined. The chances of them mining that particular block will probably be pretty small, although maybe there would be some incentive for them to sell the private key to a big mining consortium who would... do something evil maybe. We could close that remote possibility by giving the coinbase transactions nVersion=2; the transaction's version is part of the transaction id hash, so a nVersion=1 transaction will never hash to the same id as a nVersion=2 transaction. We do have the problem that between the time we announce what we're going to do and the time when there is 75% main network support rogue miners could create block.nVersion=2 / coinbase.nVersion=2 coinbases that contain "height = sometime in the future". |
The most likely error scenario is probably a buggy miner creating a version=2, height=$ValidHeight+1 or height=$ValidHeight-1 block. |
First draft of BIP text: https://gist.github.com/3058253 |
@@ -817,6 +818,7 @@ class CBlock | |||
{ | |||
public: | |||
// header | |||
static const int CURRENT_VERSION=2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's confusing to have 2 variables called CURRENT_VERSION. Better would be: CURRENT_TX_VERSION and CURRENT_BLOCK_VERSION.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Their full names are CBlock::CURRENT_VERSION and CTransaction::CURRENT_VERSION; I'll modify the code to use their full names.
This is a good rule change, and I only wish it was in all blocks already. It's such a pain to have different transactions with the same hash. Does this mean sipa's rule change will be removed? This change seems to obselete that once network hashing majority is achieved. About blocks that have a coinbase which looks like a block number and could cause problems: the only way around that is to add a fixed workaround (if nHeight == foo). It's so far in the future though, that it's not worth worrying about. |
return DoS(100, error("AcceptBlock() : block height mismatch in coinbase")); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like we can get sequences of version 1 blocks following version 2 blocks. Doesn't seem good.
How were those magical numbers picked? Comments or constant names would be nice for illustrating them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The magical numbers are arbitrary, but 75% network support before enforcing a "If you produce a v=2 block, then it must have heigh in the coinbase" and 95% support before enforcing "no more v1 blocks" feel reasonable.
You can get a sequence of version 1 block following version 2 blocks, there is no way to avoid that unless we think we can tell everybody to upgrade and start producing version=2 blocks at exactly the same time.
New URL for spec, with assigned BIP number: https://en.bitcoin.it/wiki/BIP_0034 |
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user: | ||
strMiscWarning = _("Warning: this version is obsolete, upgrade required"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like transaction code to look at (potentially unrelated) blockchain data, but it's probably by far easier this way.
EDIT: nevermind, it looked like this code was part of IsStandard()
Can this be amended to only pay attention to the last octet, just in case we end up using the first 3 for something else? |
Automatic sanity-testing: FAILED BUILD/TEST, see http://jenkins.bluematt.me/pull-tester/fa174be9b58de7377b46416d3a040c979d27d7e2 for binaries and test log. This could happen for one of several reasons:
|
This should fix the test: diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index c9981fb..8ffc9b4 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -62,6 +62,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
std::vector<CTransaction*>txFirst;
for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
{
+ pblock->nVersion = 1;
pblock->nTime = pindexBest->GetMedianTimePast()+1;
pblock->vtx[0].vin[0].scriptSig = CScript();
pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce); |
Note that this should be merged only after #936: there is software (p2pool?) which will create version==2 blocks without the height right now. #936 will workaround this problem by breaking compatibility with said application, and BIP22 explicitly requires clients understand and implement height-in-coinbase for version 2. |
@luke-jr forrestv does not agree |
"Version 2" blocks are blocks that have nVersion=2 and have the block height as the first item in their coinbase. Block-height-in-the-coinbase is strictly enforced when version=2 blocks are a supermajority in the block chain (750 of the last 1,000 blocks on main net, 51 of 100 for testnet). This does not affect old clients/miners at all, which will continue producing nVersion=1 blocks, and which will continue to be valid.
If 950 of the last 1,000 blocks are nVersion=2, reject nVersion=1 (or zero, but no bitcoin release has created block.nVersion=0) blocks -- 75 of last 100 on testnet3. This rule is being put in place now so that we don't have to go through another "express support" process to get what we really want, which is for every single new block to include the block height in the coinbase.
Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/d18f2fd9d6927b1a132c5e0094479cf44fc54aeb for binaries and test log. |
Transition to requiring block height in block coinbases
581fab6 [UX] SendChangeAddressDialog: validate address on save (random-zebra) ca99eaa [GUI] Reset change address from within SendChangeAddressDialog (random-zebra) 15b56a2 [Bug][GUI] Send: Deactivate btnChangeAddress only when addr is not set (random-zebra) Pull request description: First commit fixes a bug where the `btnChangeAddress` in SendWidget was deactivated, despite a custom address still being saved (e.g. saving a valid address, and then trying to change it to an invalid one). Second commit addresses a feature request: being able to reset only the change address (without resetting the whole coin control) directly from within the dialog. With this PR, when a custom change address is set, the text of the "CANCEL" button in `SendChangeAddressDialog` is changed to "RESET" and, when clicked, resets the default change address to CNoDestination (which means that a new change address will be created during the send operation). The upright "X" button retains its original function of just closing the dialog. Closes bitcoin#1526 ACKs for top commit: furszy: ACK 581fab6 Fuzzbawls: re-ACK 581fab6 Tree-SHA512: 27487e47dac12681845d769fbfdc2efc9eab4f929b31df3ec73b0cdfd3f9ab571a72014dd51a82e4d3bbb94786dd49ab6a49afa9b2cc20e5e2971f26f045a48e
This builds on #1525 (the framework for smoothly rolling out new chain/transaction rules), defining "nVersion=2" blocks that include the block height as the first bytes of their coinbase.
Putting the height in the coinbase is desired for at least two reasons:
The format of the height is "serialized CScript" -- first byte is number of bytes in the number (will be 0x03 on main net for the next 300 or so years), following bytes are little-endian representation of the number.
Only blocks with nVersion=2 are expected to have the height as the first bytes, and the "must have the height in the coinbase" rule is only enforced if nVersion=2 blocks are a super-majority (75% of last 1,000 blocks on main network) of the block's immediate ancestors.
This pull also contains a rule to REJECT nVersion=1 blocks once 95% of hashing power is producing nVersion=2 blocks. That means the last 5% of hashing power who refuse to upgrade will get orphaned.
All of this won't affect users/merchants at all, they will happily accept nVersion=1 or nVersion=2 blocks.
I tested this with a testnet-in-a-box setup, creating a 100-block-long nVersion=2 chain and then making sure that: