Background: Satoshi mostly implemented a 'headers only for initial block download' mode. See the fClient flag in the source, and the headersonly github branch.
The goal is to make newbie bitcoin users startup experience better-- it is painful to wait a day for the block-chain to download and verify.
The observation is that if you have an empty wallet and you aren't solo mining, you don't care about past transactions, you just need the best block chain. So bitcoin can just fetch block headers until it catches up with the current block, and then download and verify full blocks after that (once it shows the user a bitcoin receiving address, they might get transactions to it, so bitcoin has to fetch full blocks after the first time it starts up).
As I finish the implementation, I'll keep this gist up-to-date with issues or re-thinks.
Issue: generating nodes, or nodes that respond to the getwork RPC call (mining pool) need the full block chain.
Solution: Running -gen=1 or -rescan=1 will trigger NODE_NETWORK behavior, and will download any missing blocks. Once a NODE_NETWORK node, always a NODE_NETWORK node.
Add -allblocks=1 switch to force NODE_NETWORK and download missing blocks.
'getwork' call will fail (with error message saying to run -allblocks=1) if the node is not NODE_NETWORK.
Issue: I don't think a single boolean 'fClient' is the right way to go. Once this is implemented, each peer will have a different mix of full-blocks and just-headers.
Eventually, after this work is done, most peers on the network will have headers-only up until a certain point. Only block-generating nodes or "old timers" will have the full block chain. That will be a problem for nodes that stop and then restart, and try to fetch the full blocks that they missed when they were off the network.
Solution: Nodes tell each other which full blocks they have in the 'version' message. NODE_NETWORK nodes of any version are assumed to have the full chain. 'client' nodes of version 0.4 or later will broadcast (in version message) a new field: nFullStartingHeight
On initial startup, fClient nodes will connect to peers and download block headers from any of them. nFullStartingHeight is the first full block they have, and nStartingHeight is (as now) the last full block they have.
NODE_NETWORK nodes always have nFullStartingHeight=0 (they want/have all blocks from genesis).
On restart, nodes download full blocks from their previous nStartingHeight from either NODE_NETWORK peers or fClient peers that have the missing blocks. If none of their peers have peer->nFullStartingHeight <= nStartingHeight, peers are dropped and reconnected to try to find a NODE_NETWORK or fClient with the blocks needed.