I am still trying to understand what actually happened.
What I have read is that BTCNuggets, a miner that was still running v2 software, mined a block B'(N) that was valid by v2 criteria but invalid by v3 criteria. Somehow F2Pool, a miner that was running v3 software, received the header of this block and successfully mined a block B'(N+1) that was valid under v3 rules (empty, in fact) except for having an invalid parent. As luck would have it, they also mined another (empty) block B'(N+2) with B'(N+1) as parent. Then AntPool, who was running v3 software too, mined B'(N+3) on top of B'(N+2). And so on; this was the 'bad' branch.
Meanwhile, other miners running v3 software either did not see block B'(N), or saw it and detected that it was not v3-valid; so they ignored it and eventually mined a block B''(N) that was v3-valid. Several v3 miners solved additional v3-valid blocks B''(N+1), B''(N+2), etc. on top B''(N). This was the 'good' branch.
For a while, the bad branch was ahead of the good one, in terms of total work. Fortunately the devs and other bitcoin hackers were watching the blockchain to monitor the onset of BIP66, spotted the problem immediately, alerted F2Pool and AntPool that they were mining a v3-invalid chain, and sent out an alert recommending a 30-confirmation (5 hour) wait for important transactions.
Is this a correct summary of the events?
Pretty much.
Some of the many questions that remain:
* How many blocks were actually mined on the bad branch (starting form B'(N)) before it was abandoned?
6 or 7
* Were F2Pool, AntPool, and the other pools that mined on the bad chain running modified versions of the v3 core? If so, what were the modifications?
I believe that they were using custom software for SPV Mining. SPV Mining means that the miner does not validate the block before beginning to mine on it. Thus, when F2Pool and AntPool received the v2 block, they did not verify the block but simply assumed that it was valid.
* Did F2Pool realize that the BIP66 rules had already started to apply when they received B'(N) from BTCNuggets? (Say, perhaps it had counted only 949 v3 blocks, or had its counter reset recently, etc.)
Yes, However, as I said above, they were SPV Mining so they did not validate the block which was in fact invalid by the new rules.
* How did F2Pool get the header of the invalid block B'(N): directly from BTCNuggets, from a v2-running relay node, or from a v3-running relay node?
Probably from a node that still considered v2 valid such as Core 0.9.3 or lower.
* In the standard version of the v3 core software, do miners get the whole parent node and verify its validity?
Yes
* Could there be an off-by-one bug in the v3 core software, that would have resulted in F2Pool verifying B'(N) with pre-BIP66 rules instead of BIP66 rules? (Note that a v3-valid node *can* have a v3-invalid parent, if the parent was mined before BIP66 went into effect.)
* If F2Pool knew that BIP66 had kicked in, and got B'(N) from a v2-running miner or node: why was it still accepting transactions, blocks, and block headers from v2-running players, without checking whether such data was v3-valid?
SPV Mining
* If F2Pool knew that BIP66 had kicked in, and got B'(N) from a v3-running node: which node was that, and why did it forward the v3-invalid node B'(N) to F2Pool?
It most likely did not come from a v3 node.
* If a miner receives a block B(M), how many blocks B(M), B(M-1), B(M-2) etc. should it validate on its own before daring to mine B(M+1) on top of it?
I think it is B(M-6) because that is what the hard fork detection in Bitcoin Core looks for (I think, could be wrong)
* Suppose that a miner receives block B(M) and starts validating it, while in parallel mining a new block B(M+1) on top of it; and happens to solve B(M+1) before the validation of B(M) is complete. Should it broadcast B(M+1), or wait until the verification of B(M) is complete?
Ideally they should wait for the verification of B(M), but, we all know that miners are greedy little bastards, and they will most likely not wait for the verification to complete because it could mean the difference between having their block win or having it lose.
The devs deserve a fat slice of the blame for not programming a reasonable delay (say, 2 weeks) between the "95% majority" event and the activation of the BIP66 rule. That delay would have given a chance for the remaining v2 miners and nodes, as well as more v2 clients, to upgrade to v3. (Using blockchain voting to trigger protocol changes also seems a terrible idea, but that is another discussion.)
I don't think that a delay would have made a difference. BIP66 has been public for months, and so has the clients supporting it. Really the only way I think that the remaining miners would switch is after they realize that their v2 blocks are no longer being accepted because who likes change?
The core devs or F2Pool's own devs may also deserve another fat slice of the blame, for the v3 software allowing v3 miners and nodes to receive blocks from v2-running miners and nodes after BIP66 was activated.
Can't really stop the reception of blocks, but F2Pool's own devs do deserve a lot of the blame for having SPV Mining that did not validate the blocks at all.