This commit modifies the recently modified logic for self-channel
retransmission to exclude pruning *our* channels which haven’t been
updated since the broadcastInterval. Instead, we only re-broadcast
channels of ours that haven’t been updated in 24 hours.
Use binary.Read/Write in functions to serialize and deserialize
channel close summary and HTLC boolean data, as well as in
methods to put and fetch channel funding info. Remove lnd
implementations of readBool and writeBool as they are no
longer needed. Also fix a few minor typos.
This modifies the tests that deal serializing the Invoice type to limit
the creation date to seconds since Go1.9 added the concept of a
monotonic component to times which does not round trip through
MarshalBinary and UnmarshalBinary and therefore causes the tests to fail.
In particular, it modifies the creation dates in the randInvoice,
makeFakePayment, makeRandomFakePayment, and TestInvoiceWorkflow
functions.
This results in allowing TestOutgoingPaymentSerialization,
TestOutgoingPaymentWorkflow, and TestInvoiceWorkflow to pass.
This commit modifies the node.ForEachChannel to *also* return the
incoming edge as well as the outgoing edge. We make this modification
as when we’re doing path finding, we need to return the incoming edge
as well, since we need to use the to properly compute the time lock and
fees for transit on that edge.
Persists the state of a channel opening process after funding
transaction is confirmed. This tracks the messages sent to
the peer such that the process can be continued in case of a
restart. Also introduces that the receiver side forgets about
channel if funding transaction is not confirmed in 48hrs.
Adds a HaveNodeAnnouncement field to the LightningNode
struct, which is used to indicate if we have gotten
all the necessary information to fill the remaining
fields in the struct. If we haven't gotten a node
announcement for this specific node, then we only
know the pubkey, and can only fill that field in
the struct. Still, we should be able to add it to the
channel graph and use it for routes, as long as we
know about channels to this node.
This commit removes the RevocationDelay field from the HTLC struct as
with the latest commitment transaction scheme, it is no longer needed.
This is due to the fact the the delay is now observed when an on-chain
HTLC claim is attempted, rather than from Shane the HTLC itself has
been broadcast.
This commit adds a new method to the OpenChannel struct:
InsertNextRevocation. This functionality is required in order to
properly implement the new funding workflow and commitment transaction
state machine.
In the prior state machine, we utilized the “initial revocation window”
which would provide both sides with the necessary revocation keys that
they needed to create new commitment states. The version of the
commitment state machine within the specification has been simplified a
bit, and instead essentially incorporates a revocation window of 1. The
window is initially filled at the _opening_ of the commitment
transaction, then never extended, only “slid down” from there on.
This commit modifies the HTLC struct within the channeldb struct in
order to accommodate the additional storage that’s now required as a
result of the change to 2-of-2 HTLC covenant transactions within the
commitment transaction.
This commit is the next phase in a rather major overhaul of the
OpenChannel struct. With this commit we remove the old ours vs theirs
semantics with channel related state variables, and instead encapsulate
all local vs remote state into a ChannelConfig structure for each party
within the channel.
This commit introduces two new structs to the channeled package:
ChannelConfig and ChannelConstraints.
The ChannelConfig struct will eliminate many of the fields on the
OpenChannel struct (ours vs theirs), in favor of having a single config
for both sides (local and remote).
The ChannelConstraints struct will house the channel flow control and
HTLC policies for both sides. The fields of this struct will be used to
control the flow of HTLC’s within the channel. In the occasion that any
of these constraints are violated, either the connection, or the
channel entirely is to be failed.
This commit removes a database migration that was added to fix a bug
introduced within the first alpha release. This migration is no longer
needed as the underlying database scheme has changed since then.
This commit adds the possibility for the initiator of a
channel to send the update_fee message, as specified
in BOLT#2. After the message is sent and both parties
have committed to the updated fee, all new commitment
messages in the channel will use the specified fee.
The btclog package has been changed to defining its own logging
interface (rather than seelog's) and provides a default implementation
for callers to use.
There are two primary advantages to the new logger implementation.
First, all log messages are created before the call returns. Compared
to seelog, this prevents data races when mutable variables are logged.
Second, the new logger does not implement any kind of artifical rate
limiting (what seelog refers to as "adaptive logging"). Log messages
are outputted as soon as possible and the application will appear to
perform much better when watching standard output.
Because log rotation is not a feature of the btclog logging
implementation, it is handled by the main package by importing a file
rotation package that provides an io.Reader interface for creating
output to a rotating file output. The rotator has been configured
with the same defaults that btcd previously used in the seelog config
(10MB file limits with maximum of 3 rolls) but now compresses newly
created roll files. Due to the high compressibility of log text, the
compressed files typically reduce to around 15-30% of the original
10MB file.
This commit modifies the OpenChannel struct to include the full short
channel ID rather than simply the opening height. This new field will
be needed by an upcoming change to uniformly switch to using short
channel ID’s when forwarding HTLC’s due to the change in per-hop
payloads.
This commit expands the field within the OpenChannel struct in order to
start tracking the height that the funding transaction was initially
broadcast. Other sub-systems within lnd can now use this data to give a
more accurate height hint to the ChainNotifier, or to use during the
funding workflow to decide if a channel should be forgotten after it
fails to confirm for N blocks.
This commit modifies the name of a field in the OpenChannel struct to
better reflect its actual usage within this protocol. The FeePerKw
represents the amount of satoshi to be paid as fees per kilo-weight.
This field is set at the opening of a transaction and will be able to
be updated properly via the usage of the update_fee method.
In order to cleanly handle shutdowns and restarts during state machine operation, the fee for the current
commitment transaction must be persisted. This allows the fee to be
reapplied when the current state is reloaded.
This commit adds the total time locked balance of a closed channel at
closure time to the CloseChannelSummary struct. With this information,
we now provide sub-systems within the daemon further knowledge which
can aide them in properly handling querying for the state of pending
close transactions, or if they should watch a channel for closure or
not.
This commit modifies the OpenChannel structure on-disk to also track
that opening height of a channel. This change is being made in order to
make and more light client friendly. A follow up commit will modify
several areas of the codebase to use this new functionality.
This commit introduces a new method to the ChannelGraph struct:
ChannelView. This struct returns all the outpoints that represent the
set of active channels within the network. The set of items returned by
this new method will possibly shrink with each call to `PruneGraph`,
and possibly be expanded by each call to `AddChannelEdge`.
The graph pruning tests have been updated to ensure the description
above holds true.
This commit adds a new method to the database which allows callers to
mark a channel as fully closed once certain conditions have been
reached. If a channel was cooperatively closed, then it can be marked
as fully closed as soon as the channel has been confirmed. If the
channel was marked as force closed, then it should be marked as closed
as soon as _all_ the funds in limbo have been swept.
This commit builds upon the prior commit by adding a new method to
allows callers to query the state of all closed (fully) and pending
closed channel within the database.
This commit expands the close summaries within the database to include
additional information such as: how the channel was closed, if the
channel if fully closed, and other balance information. This new
information will be used in an upcoming expansion of the
pendingChannels RPC to display more comprehensive data w.r.t where the
node’s funds are and how soon they’ll be fully available.
The data stored in the closeChannel bucket has been expanded to include
the above. Additionally the CloseChannel method on the OpenChannel
struct now takes in the additional information that details how and who
it was closed by.
This commit borrows heavily from the initial work in #179 by @halseth.
This commit modifies the ForEachNode on the ChannelGraph and
ForEachChannel on the LightningNode struct to accept a database
transaction as its first argument. With this change, it’ll now be
possible to implement graph traversals that typically required a nested
loop with all the vertex loaded into memory using the callback API
instead:
c.ForEachNode(nil, func(tx, node) {
node.ForEachChannel(tx, func(…) {
})
})
This commit implements an easy optimization by using bolt db’s Batch
method when writing payment details to disk. The AddPaymnent method can
be concurrently called by thousands of grouting due to the way the
payment dispatch pipeline is architected. With this commit, we shave of
a significant amount of running time when users are sending thousands
of payments a second as what would’ve been thousands of writes can now
be coalesced into one or two writes!
Originally we adding the edge without proof in order to able to use it
for payments path constrcution. This method will allow us to populate
the announcement proof after the exchange of the half proofs and
constrcutrion of full proof finished.
In case if the channel shouldn't be announced to the rest of the network
the proof, which is needed to announce the channel, will not be
populated, fot that reason the ability to store the empty proof has
been added.
Minor change to server.go to add ExternalIPs to
channeldb.LightningNode. Also, added a test that utilizes this
functionality and exercises multiple addresses in NodeAnnouncement.
This commit modifies address handling in the NodeAnnouncement struct,
switching from net.TCPAddr to []net.Addr. This enables more flexible
address handling with multiple types and multiple addresses for each
node. This commit addresses the first part of issue #131 .
This commit adds a new method to the channel state: RevocationLogTail.
This new method will return the information concerning the latest
revoked state of the remote party’s commitment chain.
This new data can be used to properly initialize the states of the
in-memory commitment chains on node start up.
This commit removes all instances of the fastsha256 library and
replaces it with the sha256 library in the standard library. This
change should see a number of performance improvements as the standard
library has highly optimized assembly instructions with use vectorized
instructions as the platform supports.
This commit modifies the path finding routines to properly use the new
channel edge related API exposed by the database. Additionally, a new
type `ChannelHop` has been introduced which couples an edges routing
policy with the capacity and origin chain of the channel.
This commit alters the return value of PrunedGraph to me a bit more
useful: the function now returns all the channels that were closed when
processing the block (slice of spent outpoints). With this information,
callers gain greater visibility into exactly which channels were
closed. This can be used in higher levels to present detailed summaries
of how blocks affect closed channels.
This commit splits the prior ChannelEdge struct into two distinct
structs: ChannelEdgeInfo and ChannelEdgePolicy. The info structs stores
the _full_ information that was used to advertise the channel, while
the policy struct contains the information that’s needed in order to
use the information for routing purposes.
With this split we can eliminate a number of hacks within the rest of
the codebase that were added as a result of data unavailability if one
or neither edge was present.
Finally a bit of field renaming has taken place (Exipiry ->
TimeLockDelta), etc.
When a pending channel is persisted and then reloaded upon system startup
it's necessary to also persist the number of confirmations that will be required
before the pending channel can be opened.
In order to facilitate persistence during the funding process, added
the isPending flag to channels so that when the daemon restarts, we can
properly re-initialize the chain notifier and update the state of
channels that were going through the funding process.
In this commit the initial implementation of revocation hash
generation 'elkrem' was replaced with 'shachain' Rusty Russel
implementation which currently enshrined in the spec. This alghoritm has
the same asymptotic characteristics but has more complex scheme
to determine wish hash we can drop and what needs to be stored
in order to be able to achive full compression.
Fix SetStateNumHint and GetStateNumHint to properly
set and get the stateNumHints using the lower 24 bits
of the locktime of the commitment transaction as the
lower 24 bits of the obfuscated state number and the
lower 24 bits of the sequence field as the higher 24
bits.
This commit fixes a bug that was introduced when we moved to using
64-bit integers for storing the revocation log state. When we made this
change, we forgot to increase the size of the buffer which stores the
key for the particular channel state from 40 to 44 bytes to account for
the 4 additional bytes in the new 64-bit integer.
This bug has been fixed by properly sizing the key buffer. We’ve also
added an additional test to ensure that we retrieve the proper state
after multiple state updates.
This commit modifies the running update count within all ChannelDelta’s
to track the number of updates using a uint64 rather than a uint32.
This change reflects the fact that the obsfucated commitment hints are
to be encoded using a 48-bit integer, rather than a 32-bit integer.
This commit fixes a bug which would previously lead to corruption of
the channel state when a node had one or more channels open and one of
them was closed either forcibly or cooperatively. The source of the bug
itself as a typo: rather than using the construed `deliveryKey`
variable to fetch/put/delete the delivery scripts, `deliveryScriptsKey`
(the key prefix itself) as used. This bug would cause the database to
be unable to read _any_ channel from the database after one was
deleted, as each channel would actually be reading/writing-to the
_exact same_ delivery script.
The fix for the bug itself is simple: eliminate the typo.
This commit addresses some lingering TODO’s which ensure that related
state to a channel is properly deleted by the CloseChannel method.
Previously the values for the respective dust-limits of either side,
the on-disk HTLC’s, and any entries the revocation log for the channel
weren’t being properly deleted.
Additionally, we now modify the checks within the unit tests to ensure
that we can still read the channel from disk w/o running into an error
(thought the slice will be blank), and also the the revocation log is
properly garbage collected.
This commit fixes a panic that would arise when the daemon attempts to
query for a channel that doesn’t currently exist. The bug was the
result of a typo which checked for the nil existence of the incorrect
variable.
This commit fixes a prior bug in the graph database due to an invalid
assumption that both channel edges would _always_ be advertised. This
assumption is invalid, as it’s up to a node’s policy if the advertise
their direction of the channel.
The fix for this assumption is straight forward: ErrEdgeNotFound is no
longer a critical error, instead a nil pointer will now be passed into
the passed callback function.
This commit makes a large number of minor changes concerning API usage
within the deamon to match the latest version on the upstream btcsuite
libraries.
The major changes are the switch from wire.ShaHash to chainhash.Hash,
and that wire.NewMsgTx() now takes a paramter indicating the version of
the transaction to be created.
This commit modifies the error propagating behavior within the
HasChannelEdge struct. Rather than exiting the function early when a
single edge isn’t found, we instead continue to also possibly retrieve
the second directional edge.
With this change, we avoid a potential infinite gossiping loop in the
routing package that would result if we’d seen one edge but not the
other. In this case the timestamps returned for *both* edges would
always be zero, causing the daemon to always accept and rebroadcast the
announcement putting all other connected lnd’s into the same loop.
This commit modifies the new payment module within the database to
match the coding style of the rest of the package and the project as a
hole. Additionally, a few fields have been renamed, and the extra
timestamp added to the OutgoingPayment struct has been removed as
there’s already a CreationTime field within the Invoice struct that’s
embedded within the OutgoingPayment struct.
This commit modifies the FetchChannelEdgesByID slightly to use a
read-only transaction rather than a write-only transaction. As a result
we’ll no longer extraneously consume a writer’s slot when we’re only
reading data from the database.
This commit modifies the HasChannelEdge function to _always_ return
true if we know of the channel edge, meaning that it was previously
added on announce.
This change fixes a minor bug present in the code which would result in
extraneous re-transmissions of updates received by the new routing
package.
This commit adds a utility method whcih utilizes the edge index bucket
and allows caller to look up the channel ID of a channel by its funding
outpoint. This can be used to populate RPC’s with additional
information and also to provide users with an additional query
interface to build channel explorers, etc.
Previously, the edge index bucket which maps a channelPoint ->
channelID wasn’t properly created one start up during the initial
creation of the database. This caused some extraneous failure as
queries would unnecessarily fail with bucket non-existence errors.
To fix this we now properly create the bucket on start up if the
database doesn’t exist, and also properly delete the bucket within the
Wipe() function.
This commit fixes a minor bug in the ForEachChannel method of the
ChannelGraph struct. Rather than ErrGraphNoEdgesFound being returned if
either of the edge related buckets hadn’t been created yet,
ErrGraphNodesNotFound was being returned.
To fix this bug, we now properly return ErrGraphNoEdgesFound.
Additionally a mental note to roasbeef has been left as the current
code currently assumes that eventually both directions of the channel
edge will be advertised. However, this may not necessarily be the case
in a live network, since a side chooses to preferentially advertise a
channel or not.
This commit adds to new functions to the ChannelGraph struct which
allow the callers to query for the existence or non-existence of a
vertex (node) or edge (channel) within the graph. In addition to
returning whether the edge exists, the functions will also return the
last time the state has been modified for the edge or vertex. This will
allow callers to ensure that only the most up to date state is
committed to disk.
This commit adds support for channel graph pruning, which is the method
used to keep the channel graph in sync with the current UTXO state. As
the channel graph is essentially simply a subset of the UTXO set, by
evaluating the channel graph with the set of outfits spent within a
block, then we’re able to prune channels that’ve been closed by
spending their funding outpoint. A new method `PruneGraph` has been
provided which implements the described functionality.
Upon start up any upper routing layers should sync forward in the chain
pruning the channel graph with each newly found block. In order to
facilitate such channel graph reconciliation a new method `PruneTip`
has been added which allows callers to query current pruning state of
the channel graph.
This commit adds an additional check within CloseChannel to ensure that
sub-systems attempting to delete the channel one after the other (in
the event of any sort of closure) doesn’t result in an extraneous
error.
To fix this, we now check if the channel exists before attempting a
deletion. If the channel doesn’t exist, then we simply exit early with
a nil error.
This commit modifies the LightningNode.ForEachChannel method to give
the caller the option of re-using an existing database transaction
instead of always creating a new db transaction with each invocation.
Internally boltdb will run into an error/dead-lock if a nested
transaction is attempted.
Such an action might be attempted if one were to use the traversal
functions in a path finding algorithm. Therefore in order to avoid
that after, we now allow the re-use of transactions to facilitate
nested calls to ForEachChannel.
Go-fmt files. Refactored code according to the guidelines.
Enhanced payment test: add error checking
and individual context for each API call.
Add Timestamp field to payment struct.
This commit introduces a new capability to the database: storage of an
on-disk directed channel graph. The on-disk representation of the graph
within boltdb is essentially a modified adjacency list which separates
the storage of the edge’s existence and the storage of the edge
information itself.
The new objects provided within he ChannelGraph carry an API which
facilitates easy graph traversal via their ForEach* methods. As a
result, path finding algorithms will be able to be expressed in a
natural way using the range methods as a for-range language extension
within Go.
Additionally caching will likely be added either at this layer or the
layer above (the RoutingManager) in order keep queries and outgoing
payments speedy. In a future commit a new set of RPC’s to query the
state of a particular edge or node will also be added.
This commit adds a new method to the `OpenChannel` struct:
CommitmentHeight(). This method allows multiple callers holding the
same instance of an OpenChannel struct tied to the same on-disk channel
to consistently query the current commitment height for a channel. Such
a modification will prove useful later as sections of the code-base are
separated in order to allow more vigilant watching of channel breaches.
This commit performs a slight refactoring of the internals (and API) of
the [Fetch|Put]Meta methods. The changes are rather minor and simply
eliminate the conditional branching structure with usage of an internal
function. This new form is much easier to follow.
This commit modifies the composition of the boltdb pointer within the
DB struct to use embedding.
The rationale for this change is that the daemon may soon store some
semi-transient items within the database which requires us to expose
the boltdb’s transaction API. The logic for serialization of this data
will likely lie outside of the channeldb package as the items that may
be stored in the future will be specific to the current sub-systems
within the daemon and not generic channel related data.
This commit unexports the SyncVerions PR, in favor of making it private
and moving it into the .Open() method. With this change, callers no
longer need worry about ensuring the database version is up to sync
before usage, as it will happen automatically once the database is
opened.
This commit also unexports some additional variables within the package
that don’t need be consumed by the public, and exports the
DbVersionNumber attribute on the meta struct. Finally some minor
formatting fixes have neen carried out to ensure the new code more
closely matches the style of the rest of the codebase.
In this commit the upgrade mechanism for database was added which makes he current schema rigid and upgradeable. Additional bucket 'metaBucket' was added which stores
key that house meta-data related to the current/version state of the database. 'createChannelDB' was modified to create this new bucket+key during initializing. Also
backup logic was added which makes a complete copy of the current database during migration process and restore the previous version of database if migration failed.
This commit adds persistence for a channel’s
TotalSatoshis[Sent|Received] fields. Also, the functions that perform
this persistence were renamed from [put|delete|fetch]ChanTotalFlow to
[put|delete|fetch]ChanAmountsTransferred.
This commit modifies the ChannelType enum to no longer use iota as
changes in the definition would cause the values to shift, breaking the
long-term stability required for persistence. Instead, we now select
values manually to indicate the particular channel type.
This commit modifies the existing OpenChannel struct slightly to store
a bool which indicates if we were the one who initially initiated the
channel or not. This information is relevant as in the current draft of
the specification, much of the fee related negotiation is contingent on
who initiated the channel.
This commit removes all prior fee tracking attributes along with the
persistence code from OpenChannel. The rationale is that fees actually
don’t exist at the channel level, and instead should be tracked at
higher level of abstraction as fees come from the inbound/outbound
satoshi spread.
This commit modifies the OpenChannel struct along with all related
persistent to additional store a single byte which indicates the exact
type of the channel. This may be useful in the future as higher level
behavior may change depending on the precise type of the channel.
This commit introduces a new method to channeldb: ‘FetchAllChannels’.
This method can be used to obtain the state of all active (currently
open) channels within the database. This method can be used for compute
basic channel-based metrics or exposed as an RPC in order to allow
clients to display/query channel data.
This commit adds a new method ‘FullSyncWithAddr’ which is identical to
the existing ‘FullSync’ method other than it also creates an
association from the channel to a LinkNode object within the database.
This new method is required in order to create persistent links between
channels and link nodes which will later allow the development of
heuristics which decided when it “makes sense” to close a channel due
to inactivity. Additionally, this new association will allow for a
sub-system within the daemon to attempt to establish persistent
connections out to all LinkNodes in order to strive for channel
availability.
This commit slightly modifies the existing structure of the channeldb
scheme to replace the former concept of a “nodeID” with simply the
compressed public key of the remote node. This change paves the way for
adding useful indexes mapping a node to all it’s active channels and
the other way around.
Additionally, the current channeldb code was written before it was
agreed by many of those implementing Lightning that a node’s ID will
simply be its compressed public key.
This commit adds a new bucket to the database which is dedicated to
storing data pertaining to p2p related reachability for direct channel
counter parties. The data stored in this new bucket can be used within
heuristics when deciding to unilaterally close a channel due to
inactivity. Additionally, all known reachable IP addresses for a
particular LinkNode are to be stored and updated within the database in
order to facilitate the establishment of persistent connections to
direct channel counter parties.
This commit consists of a mass variable renaming to call the pkScript being executed for segwit outputs the `witnessScript` instead of `redeemScript`. The latter naming convention is generally considered to be reserved for the context of BIP 16 execution. With segwit to be deployed soon, we should be using the correct terminology uniformly through the codebase.
In addition some minor typos throughout the codebase has been fixed.
This commit modifies the on-disk storage of invoices to stop the
optional fields (memo+receipt) on-disk as variable length byte arrays.
This change saves space as the optional fields now only take up as much
space as is strictly needed, rather than always being padded out to max
size (1KB).
This commit adds a new invoice related method: FetchAllInvoices. This
method allows callers to query the state of all invoices currently
stored within the database. The method takes a toggle bit which
determines if only pending (unsettled) invoices should be returned, or
if they al should be.
This commit moves the location of the invoice counter key which is an
auto-incrementing primary key for all invoices. Rather than storing the counter
in the same top-level invoice bucket, the counter is now stored within the
invoiceIndex bucket. With this change, the top-level bucket can now cleanly be
scanned in a sequential manner to retrieve all invoices.
This commit adds the necessary database functionality required for a
high-level payment invoice workflow. Invoices can be added dealing the
requirements for fulfillment, looked by payment hash, and the finally
also settled by payment hash. For record keeping and the possibility of
reconciling future disputes, invoices are currently never deleted from
disk. Instead when an invoice is settled a bit is toggled indicating as
much.
The current invoiceManger within the daemon will be modified to use
this persistent invoice store, only storing certain “debug” invoices in
memory as dictated by a command line flag.
This commit introduces the concept of a manually initiated “force”
closer within the channel state machine. A force closure is a closure
initiated by a local subsystem which broadcasts the current commitment
state directly on-chain rather than attempting to cooperatively
negotiate a closure with the remote party.
A force closure returns a ForceCloseSummary which includes all the
details required for claiming all rightfully owned outputs within the
broadcast commitment transaction.
Additionally two new publicly exported channels are introduced, one
which is closed due a locally initiated force closure, and the other
which is closed once we detect that the remote party has executed a
unilateral closure by broadcasting their version of the commitment
transaction.
This commit splits the previously added RecordChannelDelta method into
two distinct methods: UpdateCommitment and AppendToRevocationLog. The
former method is to be used once the local party revokes their current
commitment, and the latter method to be used once the remote party
revokes their current commitment.
With the addition of the UpdateCommitment method, the active HTLC’s
from the local node’s point of view are now persisted to disk.
Snapshots returned by the channel now also includes the current set of
active HTLC’s. In order to maintain thread safety the channels mutex is
now grabbed within methods which modify/read state but don’t do so
solely via a boltDB transaction.
The tests have been updated to account for the storage of HTLC’s needed
in order to assert proper behavior.
This commit removes the revocation hash/keys from the channel deltas.
In the case of an uncooperative closure, we can efficiently re-generate
the proper elkrem pre-image so this storage was completely unnecessary
This commit implements a state update log which is intended the record
the relevant information for each state transition on disk. For each
state transition a delta should be written recording the new state. A
new method is also provided which is able to retrieve a previous
channel state based on a state update #.
At the moment no measures has been taken to optimize the space
utilization of each update on disk. There are several low-hanging
fruits which can be addressed at a later point. Ultimately the update
log itself should be implemented with an append-only flat file at the
storage level. In any case, the high level abstraction should be able
to maintained independent of differences in the on-disk format itself.