Since the breacharbiter will publish an adjusted justice tx after
detecing a spend from the breached commitment, we could get into a race
where sometime it would not get the second spend before publication,
resulting in a deadlock on the publTx channel.
Now we instead wait for the publication of this adjusted tx before
notifying the second spend.
Since we also must count revoked funds swept from second level revoked
outputs, we move the funds counting into the updateBreachInfo method,
where we already are checking whether the spend is by us or the remote.
We also clean up the logs a bit, to log the incremental sweep of funds
that now can happen.
We define a new struct justiceTxVariants, which holds three different
justice transactions:
1. The "normal" justice tx that spends all breached outputs
2. A tx that spends only the breached to_local output and to_remote output
(can be nil if none of these exist)
3. A tx that spends all the breached HTLC outputs (can be nil if no HTLC
outputs exist)
This will later be used to sweep the time sensitive outputs separately,
in case the normal justice tx doesn't confirm in time.
Now that we don't rely on the justice tx TXID anymore, we can remove
finalization of it. Instead we'll recreate the transaction when needed
from the persisted retribution info.
Since we want to potentially broadcast multiple versions of the justice
TX, instead of waiting for confirmation of a specific TXID, we instead
wait for the breached outputs to be spent.
inputs
Since we want to test more complex combinations of spends of the
breached outputs, we use two maps tracking
1. which transaction will spend the outpoint
2. which outpoints we expect the breacharbiter to include in the justice
tx
This let us trigger spends of the individual outputs, and depending on
what we want to test check whether the breacharbiter sweeps the expected
outpoints.
This commit again enables anchor channels by default.
During itests we still keep anchors opt-in, as many of the tests rely on
the behaviour of non-anchor channels.
Since private channels (most likely) won't be used for routing other
than as last hop, they bear a smaller risk that we must quickly force
close them in order to resolve a HTLC up/downstream.
In the case where it actually has to be force to resolve a payment (if
it is the first/last hop on a routed payment), we can assume that the
router will have UTXOs available from the reserved value from the
incoming public channel.
We cap the maximum value we'll reserve for anchor channel fee bumping at
10 times the per-channel amount such that nodes with a high number of
channels don't have to keep around a very large amount for the unlikely
scanario that they all close at the same time.
closed
This commit makes the handoff procedure between the breachabiter and
chainwatcher use a function closure to mark the channel pending closed
in the DB. Doing it this way we know that the channel has been markd
pending closed in the DB when ProcessACK returns.
The reason we do this is that we really need a "two-way ACK" to have the
breacharbiter know it can go on with the breach handling. Earlier it
would just send the ACK on the channel and continue. This lead to a race
where breach handling could finish before the chain watcher had marked
the channel pending closed in the database, which again lead to the
breacharbiter failing to mark the channel fully closed.
We saw this causing flakes during itests.
Since we want to support AMP payment using a different unique payment
identifier (AMP payments don't go to one specific hash), we change the
nomenclature to be Identifier instead of PaymentHash.
We'll use this AMP-specific ShardTracker for AMP payments. It will be
used to derive hashes for each HTLC attempt using the underlying AMP
derivation scheme.
We'll let the payment's lifecycle register each shard it's sending with
the ShardTracker, canceling failed shards. This will be the foundation
for correct AMP derivation for each shard we'll send.
We'll use this to keep track of the outstanding shards and which
preimages we are using for each. For now this is a simple map from
attempt ID to hash, but later we'll hide the AMP child derivation behind
this interface.
To distinguish the attempt's unique ID from the overall payment
identifier, we name it attemptID everywhere, and note that the
paymentHash argument won't be the actual payment hash for AMP payments.
Since zombie pruning can be very slow on some devices (e.g. mobile) it
would stall lnd startup. Since it is not essential for pruning to be
finished for lnd to be functional, we instead delay the initial prune by
30 seconds.
Note that we could also wait for the graphPruneInterval to tick, but
since this is by default 2 hours, it is unlikely that a mobile app will
ever be open that long.
After unification of the WalletUnlocker and RPC services on the same gRPC
server, the WalletUnlocker will no longer be shut down after the wallet
has been unlocked.
In case --no-macaroons was used, this lead to the caller getting stuck
after unlocking the wallet, since we would wait for a response on the
MacResponseChan. Earlier we would close the MacResponseChan always
when shutting down the WalletUnlocker, but this is no longer done.
To fix this we close this channel after the wallet is unlocked,
regardless of which combination of --no-macaroons and --noseedbackup
that is being used.
This commit makes us gate the calls to the RPC servers according to the
current RPC state. This ensures we won't try to call the RPC server
before it has been fully initialized, and that we won't call the
walletUnlocker after the wallet already has been unlocked.
This commit achieves what we have been building up to: running the
WalletUnlockerService and the LightningService on the same gRPC server
simultaneously!
To achieve this, we first create the RPC server in a "interface only"
way, only creating the struct and setting the dependencies we have
available before the wallet has been unlocked. After the wallet has been
unlocked and we have created all the subsystems we need, we add those to
the RPC server, and start the sub-servers.
This means that the WalletUnlockerService and the LightningService both
will be registered and available at all times on the gRPC server.
However, before the wallet has been unlocked, the LightningService
should not be used since the RPC server is not yet ready to handle the
calls. Similarly, after the wallet has been unlocked, the
WalletUnlockerService should not be used. This we will ensure in
following commits.
We don't have to define the external subserver config more than once, so
it is not needed to be defined for every listener. Instead we move it to
the ListenerConfig.
We extract common macaroon validating code into a method, and add a
method whitelist, for methods that won't need macaroons.
This give us explicit control over which methods don't require
macaroons, to avoid inadvertently adding RPCs that are unauthenticated.
For now this whitelist contains the WalletUnlocker methods, as the
wallet password is required to open the macaroon db.
This adds a new package rpcperms which houses the InterceptorChain
struct. This is a central place where we'll craft interceptors to use
for the GRPC server, which includes macaroon enforcement.
This let us add the interceptor chain to the GRPC server before the
macaroon service is ready, allowing us to avoid tearing down the GRPC
server after the wallet has been unlocked.
In order to be able to register the subservers with the root grpc server
before we have all dependencies available, we wrap them in an
GrpcHandler struct. This struct will initially hold an empty reference
to the subservers, which allows us to register with the GRPC server, and
later populate and create the subserver instance.
Similar to what we do for witnesses, check that the HTLC weight
constants check out.
They actually do not, since the spec is off by one. We ensure we agree
with the spec.
This to more easily track mismatches if constants and get more accurate
fee estimates for the two channel types.
The non-anchor weight estimates will now be smaller, this is okay since
these constants are only being used for fee estimation (and will now be
more accurate).
In this commit, we convert the delivery address in the open and accept
channel methods to be a TLV type. This works as an "empty" delivery
address is encoded using a two zero bytes (uint16 length zero), and a
tlv type of 0 is encoded in the same manner (byte for type, byte for
zero length). This change allows us to easily extend these messages in
the future, in a uniform manner.
When decoding the message we snip the bytes from the read TLV data.
Similarly, when encoding we concatenate the TLV record for the shutdown
script with the rest of the TLV data.
In this commit, we migrate all wire messages in the database from the
`legacy` to the `current` encoding.
This affects the way we write the `CommitDiff` and `LogUpdates` struct
to disk. We also need to migrate the network results bucket in the
switch as it includes a wire message without a length prefix.
We copy the new serialization togic to a new package 'current' and
export the methods we will need from the migration. This ensures that we
have isolation between the legacy and current serialization methods,
cleanly inidcating what type we are using during the migration.
In this commit, we modify the way we write wire messages across the
entire database. We'll now ensure that we always write wire messages
with a length prefix. We update the `codec.go` file to always write a 2
byte length prefix, this affects the way we write the `CommitDiff` and
`LogUpdates` struct to disk, and the network results bucket in the
switch as it includes a wire message.
The legacy encoding depends on the lnwire21 version of lnwire, so it will
let us change lnwire after the migration. To make sure it is separated
from the new encoding, we add it to a new package 'legacy'.
We also put common types in a new package 'common', which will house
types that won't change during the migration, and can be used by both
legacy and current serialization code.
To avoid code changing underneath the static migrations, we copy the
lnwire dependency in its current form into the migration directory.
Ideally the migrations doesn't depend on any code that might change,
this takes us a step closer.