In this commit, we fix a few issues with the streaming handling:
1. If it got an error on Recv() it would just spin for ever,
generating an endless stream of spammy logs.
2. It never listened on the Done() context channel for the stream. So
if the `lnd` had actually hung up, it wouldn't detect that and would
just keep spinning.
To make things more graceful, we also add back off when we try to
reconnect.
This includes upgrading the logging framework to the V2 framework. This
new framework lets us deprecate the `maxlogfiles` and
`maxlogfilesize` config options.
A sidecar ticket will always use the minimum version needed to encode
all the relavant information for that offer. In that way the tickets
from a provider with a newer version can be redeemed by recipeients
using older versions as long as the ticket does not encode new
functionalities.
If we can't clean up pending channels from a previous batch attempt,
that shouldn't block startup. So instead of shutting down, we just log
the warning and continue.
In this commit, we add automated sidecar negotiation for the recipient.
We'll use the new expose mailbox system to communicate with the provider
of the ticket to incrementally transform and complete it.
We add a new state machine attached to the sidecar acceptor that drives
the sidecar ticket to completion. We have two main states to handle:
sending the ticket w/ our node's information to the provider, and then
waiting for the final ticket from the provider that contains the order
information.
rpc: add automated ticket negotiation for the sidecar provider
In this commit, we add automated ticket negotiation for the sidecar
provider. The provider's state machine is a bit more involved as it
needs to do more in order to finalize the ticket. It starts by making a
new stream, and waiting for the recipient to send over the sidecar
information with their node information. From there it submits the bid,
checkpoints the state, and then adds the bid information before sending
the ticket back to the recipient.
If we're the provider of a sidecar channel we don't have to register a
funding shim or connect out to the taker. We'll just have to provide the
signature in the next step.
If we're the provider of a sidecar channel we don't have to wait for an
incoming channel as that won't be opened towards us. Therefore if there
are only sidecar channels in a batch, we don't have to wait at all.
If we're the provider of a sidecar channel then we don't actually have
the private key of the funding multisig key. Therefore we cannot
re-derive it on demand and have to use the key provided in the sidecar
ticket instead.
If we are the receiver of a channel, all we have to do in the channel
setup (OrderMatchSign) step is wait for all expected channels to be
opened to us in time.
With this commit we add the business logic for creating a sidecar
channel offer as the provider.
We choose the funding manager as the place for this logic as that
already has most of the required lnd clients and will ultimately be
responsible for kickstarting the funding of the sidecar channel on the
provider's side.
As a preparation for allowing multiple managers to consume the pending
channel updates, we move those events from a single channel to a
subscribe.Server construct.
We also pass in the subscription client to use into waitForChannelOpen
so we can use a different one in different flows.
As a preparation to be able to serve the pending channel updates from
lnd to multiple internal subscribers, we move the handling of those
events to the funding manager itself.
As a preparation to add non-exported fields to the funding manager, we
want to create a NewManager function that takes a config instead of
instantiating the manager directly.
To prepare for accepting sidecar channels where we don't have a real
order item in our local database, we use the order fetcher function in
the funding manager instead of the DB directly. That way we can pass in
fake bid orders during the sidecar acceptance.
The channel funding process for a sidecar channel will look different
from the normal process. To avoid too much code duplication, we first
extract the parts that remain the same into its own method.
We no longer need to hold a mutex since when we get to the
waitForChannelOpen method all previously spawned goroutines must have
completed.
We'll add a channel acceptor in the next commit that verifies self chan
amounts for incoming channels. We need to notify that acceptor about new
funding shims that we register when receiving new order matches.
Otherwise the acceptor won't be aware of the bids and their current
pending channel ID.
We need to use the DefaultBatchStepTimeout variable outside of the
funding manager as well and move it to the order package to not create a
circular dependency when accessing it from the root package.
Now that we have the self channel balance populated on the bid orders
and have also validated all diffs, we can set the push amount when
opening the channel as asker.
If we detect we have a pending batch in the local database that was
replaced by a different transaction, we try to clean up funding shims
and pending channels on startup as well.
To allow that, we use the funding manager as the BatchCleaner
implementation.
Since it's ultimately the funding manager's job to clean up
non-finalized pending channels and/or funding shims, we move that
functionality into the manager now.
To make testing easier and give the funding manager access to the
freshly refactored cleanup functions, we switch them over to use the
funding manager's base client interface instead of the full RPC client
interface.