Refactor TxState to separate read/write ops

By separating the read operations of the transaction state and the write
operations of the transaction state into separate interfaces we can
allow for API clients that only need to be able to read the state.

By ensuring that there is no overlap between the methods used for
reading and the methods used for writing (including in the internal
implementation - don’t use reader methods to access state for writing)
we can ensure that reading state never initialises lazy data structures.

When reading never initialises state we can allow reader methods to
return read-only objects when there is no state present, allowing us to
concentrate null checks to only a few places, and make the code that
reads the state simpler by having fewer special cases to deal with.
Looking through this, there is no benefit in the code base for having an interface that can perform writes but not reads. The only reason to do this is to satisfy that hunger for balance and uniformity that all developers have. To me this conflict between aesthetics and utility signals that the name of this interface is wrong. How about calling it `ReadWriteTxState` instead, would that satisfy your sense of aesthetics?