How to create a SPV client? What are the steps a SPV client takes in order to sync?


Connect to a peer
Set bloom filter for wallet addresses
Download all block-headers since latest checkpoint 
Request every block again with filters set 
Update wallet balance based on returned blocks


Obviously the above steps are wrong since it makes no sense to first download all blockheaders to determine the correct chain, and then re-request all blocks to calculate the wallet balance.

But what is the correct procedure?
This is what I do:


Connect to peer
Set bloom filter
Send 'getblocks' message
Send 'getdata' message with MSG_FILTERED_BLOCK set for any new blocks


Note that 'getblocks' returns a list of block chain hashes from the specified starting point, not the blocks themselves.  Then 'getdata' returns 'merkleblock' messages instead of full blocks.  The peer follows the 'merkleblock' message with any transactions that match the bloom filter as separate 'tx' messages.

More details are in BIP0037

If you want an example, my Java wallet can be found on GitHub