We introduce two distinct ways traders can express their closing
transaction fees: a single address/output script along with a fee rate,
or a list of outputs (script and value) which implicitly expresses the
transaction fees. This provides traders with greater coin control
flexibility, allowing them to directly send their account funds to their
desired destinations efficiently without needing multiple transactions.
To track whether or not an account was recently involved in one or more
batches, we need to add a new pending state. This pending state is
different from the normal pending update from a balance modification as
the auctioneer allows an account in this state to participate in a
batch. A scenario is possible where an account was involved in two or
more consecutive batches that both aren't confirmed on chain yet. To
handle that special case we need to also track the special account state
on the trader side.
In the future we might want to have the possibility to add additional
fields to a database object (like orders or accounts) without the need
for a migration. We add the code for that already, even if it's not
being used currently.
To make sure we don't run into an error when actually sending the
desired amount to an account output, we invoke lnd's fee estimation RPC
to make sure we can construct a transaction that also respects the new
fee parameter.
The account subscription doesn't need access to the full account,
only its key descriptor. This is a preparation for the account
recovery where we want to subscribe to the auctioneer but don't have
the full account anymore.
This commit aims to address a current gap within the system where trader
account states can become desynchronized if they participated in a batch
and they never received a Finalize message from the auctioneer.
From now on, if an account spend arrives while a trader has a pending
batch, then we assume they weren't able to receive its Finalize message,
and use the spend as an indication that the batch has been finalized.
This works because if a trader signs for a batch and disconnects, the
batch should have already been persisted, and if the batch was actually
finalized (i.e., broadcast without any changes), then the account should
have been spent.
Traders are now able to close their accounts, whether or not they have
already expired, to arbitrary outputs or to a wallet output by default.
If an account hasn't expired, then the auctioneer's signature of the
closing transaction is required to successfully close the account.
In this commit, we overhaul the keys used in the multi-sig construction
of an account to prevent script reuse and provide plausible deniability
between account outputs to third parties. This is done by tweaking the
trader's key with two new components:
1. A per-batch key, which is obtained from the auctioneer during account
creation. Every time the account is modified or participates in a
cleared batch within the system, the per-batch key is incremented by the
curve's base point, resulting in a different key used in the account
script.
2. A shared secret derived using Diffie-Hellman between the trader's and
auctioneer's base keys. By using this secret, we provide plausible
deniability to third parties with knowledge of the base keys and
per-batch key.
The resulting tweaked key for the trader is then used as the tweak for
the auctioneer's base key.
The account manager is a subsystem of the client that will be
responsible for management of all CLM accounts on-chain. This initial
version only supports opening accounts at the moment, but this will be
extended later on to also support closing and modifying them. Open
accounts are also watched for their confirmation and spend, though the
spend path remains unhandled.
The commit stands alone by itself, and is not yet integrated into the
server as we still need to satisfy its dependencies, which we'll do in
the following commits.