`cuprated` peer list write is not atomic, prevents startup
## Bug
Peer list writes are not atomic:

https://github.com/Cuprate/cuprate/blob/21ad35d44a465efbb5414a902cb6c370b8358303/p2p/address-book/src/store.rs#L47

Peer list reads do not have a recovery method so if a un-readable file exists, it will prevent `cuprated` from starting due to:

https://github.com/Cuprate/cuprate/blob/21ad35d44a465efbb5414a902cb6c370b8358303/p2p/address-book/src/lib.rs#L70-L71

## Expected behavior
- Recovery method on the (de)serialization (e.g. skip + warn on read fail)
- Atomic writes (`write(tmp_file)` -> `rename(tmp_file, actual_file)` or database instead of binary file)

## Steps to reproduce
1. Start `cuprated`
2. Run out of disk space (and maybe have an unlucky peer list write at the same time?)
3. See error `ERROR Could not save peer list to disk, got error: No space left on device (os error 28)`
4. Cannot launch `cuprated`, blocked by: `ERROR Failed to open peer list, Unexpected length of input`