feat(blockstore): implement blockstore

This PR adds a simple `datastore` wrapper so we don't need to repeat boilerplate pack/unpacking in places where the datastore is used.

```
type Blockstore interface {
	Get(u.Key) (*blocks.Block, error)
	Put(blocks.Block) error
}
```

> How is this different from the `blockservice`?

The `blockservice` falls back to querying the `exchange` (bitswap) when values aren't present in the `blockstore`.

> Where does this belong?

I'm not so sure myself. Either as a top-level package or as as `util/blockstore`. Due to circular dependencies there are a number of places where it certainly cannot go (`dht`, `bitswap`, `blockservice`, etc.)
What are the benefits of ignoring the error?

If a function can return an error, the caller should explicitly handle that error. It's never a good idea  to start making exceptions to this rule. When callers start ignoring the contracts stipulated by the libraries they use, the system becomes a house of cards.