voyager/README.md
Relaying is hard. There are several key properties to a reliable relayer, the most important of which being:
Voyager takes a novel approach to solving these problems. Internally, everything
is modeled as a finite state machine, (voyager-vm), which is stored in
postgres to ensure transactional integrity (pg-queue). Every chain query,
transaction submission, and even the data itself is represented as a state
within the queue. This design solves two of the properties mentioned above out
of the box: Data Integrity and Quick Startup Times. Since no state is
stored in Voyager itself, it is able to crash and restart exactly where it left
off, making startup times lightning fast; and since every message is processed
within a postgres transaction, we are guaranteed that the data we're working
with is correct (barring a bug in the business logic, of course). The final
property, Speed, is also solved by this design - since each message fully
encapsulates all the state it needs to operate, multiple messages can safely be
executed in parallel. This means, for instance, that while one worker is
fetching events from a block, another could be submitting a light client update,
and another could be generating a state proof, and so on.
More information on voyager's architecture can be found here.
Voyager implements the relaying logic for several light client protocols. Some of these are existing specifications, such as tendermint and ethereum, but most are custom implementations for chains Union has connected to IBC.
Many of these custom light clients build off of our existing light client infrastructure for ethereum and tendermint, with additional logic specific to the protocol's finality.
Voyager supports several Ethereum L2s, which are implemented as conditional light clients (TODO: link to our doc on conditional clients)
The settlement condition and update logic is different for each L2, but the basic principles are the same:
The consensus height of L2 clients is the consensus height of the L1 (which in the case of Ethereum L2s is the height of the beacon chain), and L2 clients are can only be updated to heights that the L1 client it tracks has a consensus state for. As such, the finality time for L2s is the L2 settlement period + L1 finality time.