Let’s take a quick detour to talk about an architectural pattern that is generally useful for working with immutable databases like the blockchain.
In a traditional system, to mutate the state of an Entity/Domain Object one would affect that change directly, overwriting the previous state. Within an Event Sourcing model, the state of an Entity/Domain Object’s mutations are recorded as a series of state-change events. To know with absolute certainty what the current state of the system is, one would simply replay all the individual state-change events for a particular Entity to arrive at the current “canonical state”.
This architectural pattern was described in a 2005 blog post by Martin Fowler entitled Event Sourcing - Capture all changes to an application state as a sequence of events.
One of the consequences of persisting application state in this manner, is the creation of an Append-Only Database.
Bitcoin is an Event Sourcing system. Each Transaction records a state-change event for a specific UTXO, essentially appending a new record to the “Bitcoin Database”. One can check the validity of any UTXO that one is given by retracing and replaying all the state-change events (spending history) against that UTXO back to the originating “coinbase transaction” that released the bitcoins into the system.
There exists a very particular architectural pattern known as CQRS (Command/Query Responsibility Separation). This refers to a method of structuring an application in such a way that there exists clear boundaries between the parts of the application that mutates the application’s persistent state (database) and the part that retrieves the current view of persistent state(database).
In Figure 1 we attempt to represent a CQRS mode of interacting with the Bitcoin Node directly. This is not quite ideal and we do not have clear separation of concerns. We will have to refine our architectural model a little.
Do note that it is possible to have an event-sourced system without CQRS, but in the wild the two are usually found in each other’s company.
After some refinements (Figure 2), our Application now
- only needs to query the View DB to know the current state of an Entity (Transaction)
- needs to submit a JSON-RPC command to the Bitcoin Node in order to change or mutate the state of an Entity (Transaction)
- listen for state-change events (Transaction updates) on the zeroMQ interface exposed by the Bitcoin Node.
- only ever needs to query the JSON-RPC interface of the Bitcoin Node in order to rebuild the internal state of an Entity in the View DB.
- can reconstruct the View DB in it’s entirety by querying the JSON-RPC interface of the Bitcoin Node, and updating the ViewDB.
Within subsequent sections of our architectural explorations we will take this basic model of how an Application can interact with the Bitcoin Network, and look at different approaches available to the developer.
These alternative approaches will all take the form of disintermediating the connections to the Bitcoin network to one extent or another. I.e. we will insert API proxies between our application and the Bitcoin Node, and in the process gain a huge leap in productivity as well as make massive efficiency gains in our deployed infrastructure.