Compare commits

..

1336 Commits

Author SHA1 Message Date
rockstardev
db58257e24
Update README.md
Some checks failed
CI / Sqlc check (push) Has been cancelled
CI / RPC and mobile compilation check (push) Has been cancelled
CI / check commits (push) Has been cancelled
CI / lint code (push) Has been cancelled
CI / cross compilation (push) Has been cancelled
CI / sample configuration check (push) Has been cancelled
CI / run ubuntu itests (backend=bitcoind dbbackend=postgres nativesql=true, bitcoind-postgres-nativesql) (push) Has been cancelled
CI / run unit tests (btcd unit-cover) (push) Has been cancelled
CI / run unit tests (btcd unit-race) (push) Has been cancelled
CI / run unit tests (unit tags="kvdb_etcd") (push) Has been cancelled
CI / run unit tests (unit tags="kvdb_postgres") (push) Has been cancelled
CI / run unit tests (unit tags="kvdb_sqlite") (push) Has been cancelled
CI / run unit tests (unit-module) (push) Has been cancelled
CI / run ubuntu itests (backend="bitcoind notxindex", bitcoind-notxindex) (push) Has been cancelled
CI / run ubuntu itests (backend="bitcoind rpcpolling" cover=1, bitcoind-rpcpolling) (push) Has been cancelled
CI / run ubuntu itests (backend=bitcoind cover=1, bitcoind) (push) Has been cancelled
CI / run ubuntu itests (backend=bitcoind dbbackend=etcd, bitcoind-etcd) (push) Has been cancelled
CI / run ubuntu itests (backend=bitcoind dbbackend=postgres, bitcoind-postgres) (push) Has been cancelled
CI / run ubuntu itests (backend=bitcoind dbbackend=sqlite nativesql=true, bitcoind-sqlite-nativesql) (push) Has been cancelled
CI / run ubuntu itests (backend=bitcoind dbbackend=sqlite, bitcoind-sqlite) (push) Has been cancelled
CI / run ubuntu itests (backend=btcd cover=1, btcd) (push) Has been cancelled
CI / run ubuntu itests (backend=neutrino cover=1, neutrino) (push) Has been cancelled
CI / run windows itest (push) Has been cancelled
CI / run macOS itest (push) Has been cancelled
CI / check pinned dependencies (github.com/golang/protobuf v1.5.3) (push) Has been cancelled
CI / check pinned dependencies (google.golang.org/grpc v1.59.0) (push) Has been cancelled
CI / check release notes updated (push) Has been cancelled
CI / finish (push) Has been cancelled
2025-07-22 23:12:37 +02:00
rockstardev
d97fa8b923
Merge pull request #8 from btcpayserver/pr/lnd-v0.18.4-beta
Building BTCPay LND 0.18.4
2025-01-08 16:57:18 -05:00
rockstardev
655d470280 Updating docker files to build 0.18.4 lnd 2025-01-07 18:53:54 -06:00
rockstardev
ce16689d73 Merge remote-tracking branch 'source/0-18-4-branch' 2025-01-07 18:46:41 -06:00
rockstardev
3da675df42
Update README.md
Adding example of local docker build process
2025-01-07 09:57:32 -06:00
rockstardev
e2a063f0e3
Update README.md
Link to Loop and fixing link to commit
2025-01-07 09:47:47 -06:00
Oliver Gugger
ddeb835168
Merge pull request #9367 from lightningnetwork/0-18-4-branch-rc3
release: create branch for v0.18.4-beta
2024-12-17 21:17:09 +01:00
Oliver Gugger
74d15d1fbc
build: bump version to v0.18.4-beta 2024-12-17 21:15:07 +01:00
Oliver Gugger
88cbec291c
Merge branch '0-18-4-branch-rc3-9357' into 0-18-4-branch-rc3 2024-12-16 12:51:50 +01:00
George Tsagkarelis
d30cba1089
contractcourt: include custom records on replayed htlc
When notifying the invoice registry for an exit hop htlc we also want to
include its custom records. The channelLink, the other caller of this
method, already populates this field. So we make sure the contest
resolver does so too.
2024-12-16 12:51:49 +01:00
Oliver Gugger
3c0810963f
Merge pull request #9335 from lightningnetwork/0-18-4-branch-rc2
release: create branch for v0.18.4-beta.rc2
2024-12-11 13:33:04 +01:00
Oliver Gugger
3447484a66
Merge branch '0-18-4-branch-rc2-9316' into 0-18-4-branch-rc2 2024-12-10 22:29:38 +01:00
ziggie
71eb1ae57d
docs: add release-notes for 18.4 2024-12-10 22:29:29 +01:00
ziggie
4c61411802
routing: bugfix for mc reporting of blinded paths
When reporting an error  or a success case of a payment to a
blinded paths, the amounts to forward for intermediate hops
are set to 0 so we need to use the receiver amount instead.
2024-12-10 22:29:29 +01:00
ziggie
a1e5dfc266
routing: add pathfinding test
We add a test where we add duplicate hops in a route and verify
that the pathfinding engine can handle this edge case.
2024-12-10 20:27:25 +01:00
ziggie
c579a6bf2f
routing: improve lasthoppaylaod size calculation
Fixes a bug and makes the function more robust. Before
we would always return the encrypted data size of last hop
of the last path. Now we return the greatest last hop payload
not always the one of the last path.
2024-12-10 20:27:25 +01:00
ziggie
eb93eb7ee9
routing: Use NUMS point for blinded paths
To be able to do MPP payment to multiple blinded routes we need
to add a constant dummy hop as a final hop to every blined path.
This is used when sending or querying a blinded path, to let the
pathfinder be able to send MPP payments over different blinded
routes. For this dummy final hop we use a NUMS key so that we
are sure no other node can use this blinded pubkey either in a
normal or blinded route.
Moreover this helps us handling the mission control data for
blinded paths correctly because we always consider the blinded
pubkey pairs which are registered with mission control when
a payment to a blinded path fails.
2024-12-10 20:27:24 +01:00
ziggie
0b90d3c3c2
input: export NUMS key parser. 2024-12-10 20:24:01 +01:00
Oliver Gugger
f312064bfb
build: bump version to v0.18.4-beta.rc2 2024-12-05 21:49:08 +01:00
Oliver Gugger
b63ac70113
Merge branch '0-18-4-branch-rc2-9333' into 0-18-4-branch-rc2 2024-12-05 21:47:45 +01:00
Oliver Gugger
72b4a1cb34
multi: thread through and use AuxTrafficShaper 2024-12-05 21:46:27 +01:00
Oliver Gugger
662049681d
htlcswitch: thread through packet's inbound wire records
For calculating the available auxiliary bandwidth of a channel, we need
access to the inbound custom wire records of the HTLC packet, which
might contain auxiliary information about the worth of the HTLC packet
apart from the BTC value being transported.
2024-12-05 21:44:58 +01:00
Oliver Gugger
699e2b74f6
multi: move routing.TlvTrafficShaper => htlcswitch.AuxTrafficShaper
With this commit we move the traffic shaper definition from the routing
package to the HTLC switch package as a preparation for being able to
use it there as well.
At the same time we rename it to AuxTrafficShaper to be more in line
with the other auxiliary components.
2024-12-05 21:44:56 +01:00
Oliver Gugger
f5ad1ee438
Merge branch '0-18-4-branch-rc2-9324' into 0-18-4-branch-rc2 2024-12-05 21:41:27 +01:00
ziggie
ae227ce2c6
docs: add release-notes 2024-12-05 21:41:13 +01:00
ziggie
7e228f22a8
contractcourt: refactor start up of arbitrators
We decouple the state machine of the channel arbitrator from
the start-up process so that we can startup the whole daemon
reliably.
2024-12-05 21:40:31 +01:00
Oliver Gugger
c1129bb086
Merge pull request #9183 from lightningnetwork/0-18-4-branch-rc1
release: create branch for v0.18.4-beta.rc1
2024-11-21 20:19:40 +01:00
Oliver Gugger
9246d5c51c
Merge branch '0-18-4-branch-rc1-9288' into 0-18-4-branch-rc1 2024-11-20 15:31:13 +01:00
Oliver Gugger
117a145b97
docs: add release notes 2024-11-20 15:31:12 +01:00
Oliver Gugger
e074a8fab3
chanacceptor: add custom channel commitment type 2024-11-20 15:31:12 +01:00
Oliver Gugger
f9d876e8a3
Merge branch '0-18-4-branch-rc1-9253' into 0-18-4-branch-rc1 2024-11-20 10:44:12 +01:00
ziggie
a4211251bd
docs: add release notes 2024-11-20 10:43:59 +01:00
ziggie
d695383386
rpcserver: add robustness check 2024-11-20 10:42:54 +01:00
ziggie
79d0655a96
multi: introduce an option for resolutions
We don't always need the resolutions in the local force close
summary so we make it an option.
2024-11-20 10:42:54 +01:00
Oliver Gugger
78c8990772
Merge branch '0-18-4-branch-rc1-9272' into 0-18-4-branch-rc1 2024-11-19 12:44:51 +01:00
Olaoluwa Osuntokun
86de1ebdc2
sweep: update storeRecord to include utxo index
In this commit, we complete a recently added feature by ensuring that
even if we go through the RBF loop to create a txn, that we still
populate the `outpointToIndex` map. Unit tests have been updated to
ensure this is always set as expected.
2024-11-19 12:44:51 +01:00
Oliver Gugger
4c9d25cbe7
Merge branch '0-18-4-branch-rc1-9194' into 0-18-4-branch-rc1 2024-11-15 13:09:56 +01:00
Oliver Gugger
04b053e405
docs: move 0.18.4 items, add full list of custom chan PRs 2024-11-15 13:09:35 +01:00
Olaoluwa Osuntokun
e1a25f6c30
sweep: update BudgetInputSet.Budget() to factor in extra budget
In this commit, we update the `Budget()` call to factor in the
`extraBudget` value. Otherwise, when we go to intialize the fee
function, we won't factor in the extra budget, and will determine that
we can't broadcast/bump.
2024-11-15 13:09:10 +01:00
Olaoluwa Osuntokun
6db7d42654
lnwallet: add whoseCommit to FetchLeavesFromCommit
This is useful for additional context to know which commit the
AuxLeafStore is fetching the leaves for.
2024-11-15 13:09:10 +01:00
Olaoluwa Osuntokun
b8035d9db7
sweep: expand NotifyBroadcast to include an outpoint index
In this commit, we expand the `NotifyBroadcast` to include an outpoint
index. This is useful as it indicates the index of a given required tx
out input.
2024-11-15 13:09:09 +01:00
Olaoluwa Osuntokun
83f1c883ba
contractcourt: pass in new aux resolution blob to sweeper in resolvers
With this commit, we update all the resolvers to pass in the new htlc
resolution blobs. Along the way, we remove the old blocking guard on
this resolution logic for HTLCs with blobs.
2024-11-15 13:09:09 +01:00
Olaoluwa Osuntokun
f1a1c033d1
contractcourt: update encode/decode for taproot aux data
When we read/write the aux data, we need to make sure we always set the
new fields for aux HTLCs.
2024-11-15 13:09:09 +01:00
Olaoluwa Osuntokun
6914e6a4a5
contractcourt: add HtlcBlobs to taprootBriefcase
In this commit, we add the set of HtlcBlobs to the taprootBriefcase
struct. This new field will store all the resolution blobs for a given
HTLC. We also add some new property based tests along the way for
adequate test coverage.
2024-11-15 13:09:09 +01:00
Olaoluwa Osuntokun
413fdaf3fb
input: add new Preimage method to input.Input
In this commit, we add a new method to obtain an option of a preimage to
the input.Input struct. This is useful for callers that have an Input,
and want to optionally obtain the preimage.
2024-11-15 13:09:09 +01:00
Olaoluwa Osuntokun
e3eef0adff
lnwallet: populate resolution blob for incoming+outgoing HTLC resolutions
In this commit, we populate the resolution blobs for the incoming and
outgoing HTLCs. We take care to populate the AuxSigDesc with the correct
information, as we need to pass along the second-level aux signature and
also sign desc along with it.
2024-11-15 13:09:09 +01:00
Olaoluwa Osuntokun
84aacc6c39
channel: add ResolutionBlob to Incoming+Outgoing HtlcResolution
Similar to the other blobs we have for the commitment output force close
resolution, these blobs will be used to ensure that we have everything
needed to sweep aux HTLCs.
2024-11-15 13:09:08 +01:00
Olaoluwa Osuntokun
57617dc4f7
channel: always specify ChanType in ResolutionReq 2024-11-15 13:09:08 +01:00
Olaoluwa Osuntokun
a5beb340e4
lnwallet: expand attributes in ResolutionReq
In this commit, we add some additional attributes to the ResolutionReq
struct. These will be used to make sure that we can properly handle all
the HTLC variants, on chain.

The `AuxSigDesc` will be used to communicate if an HTLC needs to go to
the second level or not. It contains the second-level sig information
needed to finalize a broadcast to the second level.
2024-11-15 13:09:07 +01:00
Oliver Gugger
31ace742a5
Merge branch '0-18-4-branch-rc1-9084' into 0-18-4-branch-rc1 2024-11-13 12:52:32 +01:00
Matt Morehouse
2c25f38a5a
discovery: remove check for incorrect number of timestamps
The check is no longer required, as it is now done during decoding.
2024-11-13 12:52:32 +01:00
Matt Morehouse
c8033e1725
lnwire: fail decoding on incorrect number of timestamps
Currently if an incorrect number of timestamps is given, we fail later
on in the GossipSyncer. It makes more sense to fail right away, since we
already do that for incorrect SCID formats (e.g., unsorted or duplicate
SCIDs). There is already a matching check in Encode for incorrect number
of timestamps, so adding this check to Decode makes things symmetric.
2024-11-13 12:52:32 +01:00
Oliver Gugger
9bf48a7e9a
Merge branch '0-18-4-branch-rc1-9082' into 0-18-4-branch-rc1 2024-11-13 12:50:57 +01:00
Matt Morehouse
a4414fbbb9
lnwire: manually compare Timestamps in fuzz test
We can't use require.Equal because it considers nil slices and empty
slices to be not equal.
2024-11-13 12:50:56 +01:00
Oliver Gugger
af08c42d58
Merge branch '0-18-4-branch-rc1-9062' into 0-18-4-branch-rc1 2024-11-08 08:52:31 +01:00
Olaoluwa Osuntokun
b2b5ec052b
contractcourt: use the sweeper for HTLC offered remote timeout resolution
In this commit, we bring the timeout resolver more in line with the
success resolver by using the sweeper to handle the HTLC offered remote
timeout outputs. These are outputs that we can sweep directly from the
remote party's commitment transaction when they broadcast their version
of the commitment transaction.

With this change, we slim down the scope slightly by only doing this for
anchor channels. Non-anchor channels will continue to use the
utxonursery for this output type for now.
2024-11-08 08:52:31 +01:00
Olaoluwa Osuntokun
941590d384
contractcourt: use t.Run in TestHtlcTimeoutResolver
Along the way we refactor the test to eliminate some unnecessary line
length.
2024-11-08 08:52:30 +01:00
Oliver Gugger
906fa0b7b8
Merge branch '0-18-4-branch-rc1-9223' into 0-18-4-branch-rc1 2024-10-30 14:16:37 +01:00
Boris Nagaev
593afee12d
itest: coop_close_with_external_delivery with p2tr
Customize the itest with the type of external delivery address. Test with P2TR
address type in addition to P2WKPH.
2024-10-30 14:16:37 +01:00
Boris Nagaev
552d182594
lnwallet: fix closechannel for P2TR external addr
If the delivery address is P2TR, function InternalKeyForAddr checks its
existance in the wallet to return internal key for it in case it is a custom
taproot channel. It used to return the error returned by wallet.AddressInfo.
The error is now ignored if it is ErrAddressNotFound error. This fixes
"lncli closechannel --delivery_addr <external p2tr address" case.
2024-10-30 14:16:36 +01:00
Oliver Gugger
615f3d633e
Merge branch '0-18-4-branch-rc1-9199' into 0-18-4-branch-rc1 2024-10-25 11:00:09 +02:00
George Tsagkarelis
6f401b4265
invoices: cancel htlc on HtlcModify signal 2024-10-25 11:00:08 +02:00
George Tsagkarelis
2999b37607
lnrpc+invoices: add cancelSet to HtlcModifier interface 2024-10-25 11:00:08 +02:00
Oliver Gugger
b69fc15cc1
Merge branch '0-18-4-branch-rc1-9197' into 0-18-4-branch-rc1 2024-10-22 09:06:30 +02:00
Jonathan Harvey-Buschel
d650829f9b
gitignore: ignore vscode workspace files 2024-10-22 09:06:17 +02:00
Jonathan Harvey-Buschel
455cdffede
lnwallet: test link quit signal handling 2024-10-22 09:06:17 +02:00
Jonathan Harvey-Buschel
8703153c44
multi: link quit can interrupt commitment signing
In this commit, we make sig job handling when singing a next commitment
non-blocking by allowing the shutdown of a channel link to prevent
further waiting on sig jobs by the channel state machine. This addresses
possible cases where the aux signer may be shut down via a separate quit
signal, so the state machine could block indefinitely on receiving an
update on a sig job.
2024-10-22 09:06:17 +02:00
Oliver Gugger
6feb74137d
mod: bump fn to v1.2.3 2024-10-22 09:06:15 +02:00
Jonathan Harvey-Buschel
753301cf38
htlcswitch: pass quit chans as unidirectional
This is a requirement for replacing the quit channel with a Context.
The Done() channel of a Context is always recv-only, so all users of
that channel must not expect a bidirectional channel.
2024-10-22 09:05:42 +02:00
Jonathan Harvey-Buschel
afb7532f17
lnwallet: sort sig jobs before submission 2024-10-22 09:05:42 +02:00
Jonathan Harvey-Buschel
ed5d748a9f
lnwallet: test aux signer shutdown handling 2024-10-22 09:05:42 +02:00
Jonathan Harvey-Buschel
b6363a8da4
lnwallet: refactor test code for HTLC add and recv 2024-10-22 09:05:42 +02:00
Jonathan Harvey-Buschel
afdd53194b
multi: allow mock aux signer to customize sig jobs 2024-10-22 09:05:41 +02:00
Oliver Gugger
6f0d7f9a87
Merge branch '0-18-4-branch-rc1-9195' into 0-18-4-branch-rc1 2024-10-21 13:26:23 +02:00
yyforyongyu
f09b638343
lntest: add method AssertTxnsNotInMempool
So we only need to do one `GetRawMempool` lookup when checking the
exclusion of multiple txns.
2024-10-21 13:26:09 +02:00
yyforyongyu
56e05a3e1e
lntest: remove unused return value 2024-10-21 13:26:09 +02:00
yyforyongyu
1aae94f17d
itest+lntest: stop using pointer to chainhash.Hash
This commit fixes the methods used in `lntest` so they stop using
pointers to chainhash.
2024-10-21 13:26:09 +02:00
Oliver Gugger
3b8b738be9
Merge branch '0-18-4-branch-rc1-9059' into 0-18-4-branch-rc1 2024-10-16 16:00:25 +02:00
Oliver Gugger
55e6460707
docs: add release notes 2024-10-16 15:59:54 +02:00
Oliver Gugger
34ea769501
mod: fix unit tests by updating error matching in btcwallet 2024-10-16 15:59:52 +02:00
Oliver Gugger
57e7b41510
lnwallet: turn off RBF detection in test 2024-10-16 15:58:00 +02:00
Oliver Gugger
6aec5b00ad
lntest: avoid port collision on Tor listen port
bitcoind now seems to listen on the -bind port at all times. So we need
to make sure multiple instances don't collide by using a unique port.
2024-10-16 15:58:00 +02:00
Oliver Gugger
5966150db5
lntest: move debug flag, disable spammy libevent 2024-10-16 15:57:59 +02:00
Oliver Gugger
fe8b89dc2c
github+scripts: bump itests to bitcoind v28, allow testing with RCs 2024-10-16 15:57:59 +02:00
rockstardev
9f0402c685 Updating README 2024-10-15 19:01:28 -05:00
rockstardev
4f332436cc Merge branch 'lnd/v0.18.3-beta'
# Conflicts:
#	docker-initunlocklnd.sh
2024-10-15 18:58:46 -05:00
rockstardev
e888c2a317 Adding BtcPayServer related files and resources 2024-10-15 18:38:30 -05:00
rockstardev
eb64ae0260 Update README 2024-10-15 18:11:52 -05:00
rockstardev
48120906c9 Merge branch 'lnd/v0.18.3-beta'
# Conflicts:
#	.circleci/config.yml
#	Makefile
#	README.md
#	build/version.go
#	go.mod
#	go.sum
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2024-10-15 18:09:25 -05:00
rockstardev
ae4bb33c6a Adding BtcPayServer related files and resources 2024-10-15 17:56:11 -05:00
rockstardev
8742a9a506
Merge pull request #7 from ziggie1984/fix-lnd-wallet-pw
Fix Password for lnd instance.
2024-10-15 17:36:29 -05:00
Oliver Gugger
9ca21ecf2d
Merge branch '0-18-4-branch-rc1-9187' into 0-18-4-branch-rc1 2024-10-15 17:33:27 +02:00
Oliver Gugger
58bf721f2e
cmd/commands: don't error out on replacement failure 2024-10-15 17:33:26 +02:00
Oliver Gugger
560b7286b5
rpcserver: don't write any custom channel data if empty 2024-10-15 17:33:26 +02:00
ziggie
33508380e7
Fix Password for lnd instance 2024-10-13 15:14:25 +02:00
Oliver Gugger
ca3bde901e
build: bump version to v0.18.4-beta.rc1 2024-10-11 14:46:28 +02:00
Oliver Gugger
89c84f1da6
lnwallet: fix import issue 2024-10-11 14:46:09 +02:00
Oliver Gugger
a3db2145dc
Merge branch '0-18-4-branch-rc1-9154' into 0-18-4-branch-rc1 2024-10-11 14:23:41 +02:00
ziggie
a5eca91602
multi: bump btcd version.
The new SignCompact return values had to be adopted across the
code base.
2024-10-11 14:23:41 +02:00
Oliver Gugger
5c7be35ca5
Merge branch '0-18-4-branch-rc1-8960' into 0-18-4-branch-rc1 2024-10-11 14:23:05 +02:00
Olaoluwa Osuntokun
16edbf3026
sweep: ensure we factor in extra change addrs in MaxFeeRateAllowed 2024-10-11 14:22:50 +02:00
George Tsagkarelis
00ed751ee5
docs: update release notes 2024-10-11 14:22:47 +02:00
Olaoluwa Osuntokun
9f048b0ea3
lnd: signal taproot overlay chans based on config
We also add a sanity check to make sure they can't be signaled without
the aux interfaces.
2024-10-11 14:22:13 +02:00
Olaoluwa Osuntokun
6619646088
lncfg: add new config option for taproot overlay chans 2024-10-11 14:22:13 +02:00
Olaoluwa Osuntokun
3031f21182
rpc+funding: add taproot overlay as RPC chan type 2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
4eaba9b3db
lnrpc: add SIMPLE_TAPROOT_OVERLAY feature bit 2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
72d437d5c8
funding: add chan type awareness for new taproot chans overlay 2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
4efa39ddb1
lnwallet: add awareness of taproot overlay chan type to reservations 2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
745f3a6181
feature: add awareness of new taproot chans overlay feature bit
This bit will be false by default in current production deployments.
2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
1a3c94a501
lnwire: add new taproot chans overlay feature bit 2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
3d7d9d2612
contractcourt: integration aux sweeper to breach arb
Similar to the sweeper, when we're about to make a new breach
transaction, we ask the sweeper for a new change address, if it has one.
Then when we go to publish, we notify broadcast.
2024-10-11 14:22:12 +02:00
Olaoluwa Osuntokun
4c16e55aca
contractcourt: update makeBreachedOutput to accept resolution blob 2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
ded6959fd5
contractcourt: update GenSweepScript to return internal key
For the upcoming aux sweeper integration, the internal key is needed for
the call backs.
2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
d0501ab840
multi: hook up new aux interfaces 2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
678028cee9
contractcourt: pause resolution for HTLCs w/ custom records
This is a hold over until the aux resolution is finalized for HTLC
outputs.
2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
a21fb1b69c
sweep: update sweeper to use AuxSweeper to add extra change addr
In this commit, we start to use the AuxSweeper (if present) to obtain a
new extra change addr we should add to the sweeping transaction. With
this, we'll take the set of inputs and our change addr, and then maybe
gain a new change addr to add to the sweep transaction.

The extra change addr will be treated as an extra required tx out,
shared across all the relevant inputs. This'll also be used in
NeedWalletInput to make sure that we add an extra input if needed to be
able to pay for the change addr.
2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
23e99ddd4d
sweep: add new AuxSweeper interface
In this commit, we add a new AuxSweeper interface. This'll take a set of
inputs, and a change addr for the sweep transaction, then optionally
return a new sweep output to be added to the sweep transaction.

We also add a new NotifyBroadcast method.  This'll be used to notify
that we're _about_ to broadcast a sweeping transaction. The set of
inputs is passed in, which allows the caller to prepare for the ultimate
broadcast of the sweeping transaction.

We also add ExtraTxOut to BumpRequest pass fees to NotifyBroadcast. This
allows the callee to know the total fee of the sweeping transaction.
2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
3726cfa319
server+sweep: convert GenSweepScript to use new addr type
We convert it to use lnwallet.AddrWithKey, as in the future, knowing the
internal key for an address will be useful.
2024-10-11 14:22:11 +02:00
Olaoluwa Osuntokun
fef368bb38
contractcourt: set resolution blob in commitSweepResolver 2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
080771db62
input: add ResolutionBlob method to inputKit
We also update breachedOutput w/ the new API.
2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
fc02cd7b0c
input: refactor all inputs to use MakeBaseInput, add opts
In this commit, we refactor all the other constructors for the input to
use MakeBaseInput. We also add a new set of functional options as well.
This'll be useful later on to ensure that new options are properly
applied to all the input types.
2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
07ee114116
lnwallet+peer: move internalKeyForAddr to lnwallet package
This way we can re-use it. We also make it slightly more generalized.
2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
74d27f2c7c
contractcourt: add CommitBlob to taprootBriefcase
This'll be used to store the extra resolution information for the
commitment outputs.
2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
f4710ca639
lnwallet: add new aux resolver interface
This will be used by external callers to modify the way we resolve
contracts on chain. For a given contract, we'll store an extra "blob",
that will later be presented during the sweeping phase.
2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
900a0a114a
contractcourt: convert taprootBriefcase to use new tlv record type
This commit doesn't yet go all the way to modify all the other records
quite yet.
2024-10-11 14:22:10 +02:00
Olaoluwa Osuntokun
035126b280
lnwire: modify TestLightningWireProtocol to use sub-tests
This way, it's possible to run induvidual tests to target failures.
2024-10-11 14:22:09 +02:00
George Tsagkarelis
9d50e273a3
routing: add htlcAmt to PaymentBandwidth method of TlvTrafficShaper
This commit was added to the 0-19-staging branch recently and therefore
didn't make it into a previous part yet. So it's unrelated to the
changes in this part but is required for the whole custom channel saga.
2024-10-11 14:22:09 +02:00
Oliver Gugger
053b6bcfad
Merge branch '0-18-4-branch-rc1-9134' into 0-18-4-branch-rc1 2024-10-11 14:20:33 +02:00
Elle Mouton
663f4c251e
feature: remove b11 feature bit from default invoice set 2024-10-11 14:20:19 +02:00
Elle Mouton
6df4f27929
server: stop interceptable switch in Stop 2024-10-11 14:20:19 +02:00
Elle Mouton
575d699917
invoices: init quit channel of modifier
Also add atomic start and stop vars to prevent close of a closed
channel.
2024-10-11 14:20:19 +02:00
Elle Mouton
d2c745e610
multi: update PaymentAddr to use fn.Option
Since it is allowed to not be set and so can lead to nil deref panics if
it is a pointer.
2024-10-11 14:20:17 +02:00
Oliver Gugger
7857f38f45
Merge branch '0-18-4-branch-rc1-9095' into 0-18-4-branch-rc1 2024-10-11 14:17:28 +02:00
Oliver Gugger
9ce799578c
multi: add co-op close custom data to close update
With this commit we populate additional information about the close
outputs (including potential custom channel data) in the close update
RPC message.
This will allow custom channels to find out how the additional close
outputs look like on chain and what data they might commit to.

We also hook up the aux custom data formatter, so it can format the
custom channel data to JSON.
2024-10-11 14:17:28 +02:00
Olaoluwa Osuntokun
39e4e8d8a4
peer: decorate delivery addr w/ internal key
In this commit, we move to add the internal key to the delivery addr. This way, we give the aux chan closer the extra information it may need to properly augment the normal co-op close process.
2024-10-11 14:17:28 +02:00
Olaoluwa Osuntokun
fbbcecc635
server+peer: init peer struct w/ AuxChanCloser if present 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
8b97d4f833
lnwallet: modify CoopCloseBalance to not depend on chan commit 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
e536cfad0f
lnwallet/chancloser: add aux chan closer, use in coop flow 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
e2dae56698
lnwallet/chancloser: add new AuxChanCloser interface 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
2d8c4fda2f
lnwallet: add ability to do custom sort for coop close txn 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
0cb211e14c
lnwallet: add ability to add extra co-op close outputs 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
7e4f6f5b4a
lnwallet: add FundingBlob method to LightningChannel 2024-10-11 14:17:27 +02:00
Olaoluwa Osuntokun
6feb189a21
lnwire: add CustomRecords to shutdown message 2024-10-11 14:17:26 +02:00
ffranr
35ce62c021
itest: add basic invoice HTLC modifier integration test
This commit introduces a basic integration test for the invoice
HTLC modifier. The test covers scenarios where an invoice is settled with a
payment that is less than the invoice amount, facilitated by the invoice
HTLC modifier.
2024-10-11 14:17:26 +02:00
Oliver Gugger
0cb599dbf6
lnrpc+rpcserver: encode custom records as custom channel data
With this commit we encode the custom records as a TLV stream into the
custom channel data field of the invoice HTLC.
This allows the custom data parser to parse those records and replace it
with human-readable JSON on the RPC interface.
2024-10-11 14:17:26 +02:00
ffranr
c1aa44c476
multi: pass UpdateAddHtlc message custom records to invoice modifier 2024-10-11 14:17:26 +02:00
Oliver Gugger
109e27cfb2
lnwire: add MergedCopy method to CustomRecords 2024-10-11 14:17:26 +02:00
ffranr
ce7c053de0
lntest: add HtlcModifier support to node RPC harness
This commit enhances the itest LND node harness to include support for
the new `HtlcModifier` RPC endpoint.
At the same time we move another method to the correct file.
2024-10-11 14:17:26 +02:00
ffranr
e417250f6d
invoicesrpc: add HtlcModifier RPC endpoint and modifier RPC server
This commit introduces a singleton invoice HTLC modifier RPC server and
an endpoint to activate it. The server interfaces with the internal
invoice HTLC modifier interpreter, handling the marshalling between RPC
types and internal formats.
2024-10-11 14:17:26 +02:00
ffranr
7285dfa66a
invoicesrpc: add HTLC modifier to invoices RPC server
This commit integrates the HTLC modifier service into the
invoices RPC server.
2024-10-11 14:17:25 +02:00
ffranr
f903e16c47
lnd: initialize invoice settlement interceptor at server startup
This commit initiates the invoice settlement interceptor during the
main server startup, assigning it a handle within the server.
2024-10-11 14:17:25 +02:00
ffranr
4d9422a064
invoices: integrate settlement interceptor with invoice registry
This commit updates the invoice registry to utilize the settlement
interceptor during the invoice settlement routine. It allows the
interceptor to capture the invoice, providing interception clients an
opportunity to determine the settlement outcome.
2024-10-11 14:17:25 +02:00
ffranr
acf0d0ebe8
invoices: add invoice htlc interceptor service
This commit introduces a new invoice htlc interceptor service
that intercepts invoice HTLCs during their settlement phase. It forwards
HTLCs to a subscribed client to determine their settlement outcomes.

This commit also introduces an interface to facilitate integrating the
interceptor with other packages.
2024-10-11 14:17:25 +02:00
Oliver Gugger
153a133ea6
Merge branch '0-18-4-branch-rc1-9072' into 0-18-4-branch-rc1 2024-10-11 14:16:36 +02:00
Oliver Gugger
c3627545be
htlcswitch: override amount check on custom records 2024-10-11 14:16:36 +02:00
Oliver Gugger
b35dae72a5
channeldb: add NextHeight, fix formatting 2024-10-11 14:16:36 +02:00
Oliver Gugger
f9debb148b
lnd: add aux data parser
This commit adds an optional data parser that can inspect and in-place
format custom data of certain RPC messages.
We don't add an implementation of the interface itself, as that will be
provided by external components when packaging up lnd as a bundle with
other software.
2024-10-11 14:16:36 +02:00
Oliver Gugger
23ef68a2f7
lnrpc+rpcserver: add and populate custom channel data 2024-10-11 14:16:36 +02:00
Jonathan Harvey-Buschel
9c80088abd
lnwallet: sort sig jobs before submission
To make sure we attempt to read the results of the sig batches in the
same order they're processed, we sort them _before_ submitting them to
the batch processor.
Otherwise it might happen that we try to read on a result channel that
was never sent on because we aborted due to an error.
We also use slices.SortFunc now which doesn't use reflection and might
be slightly faster.
2024-10-11 14:16:35 +02:00
Olaoluwa Osuntokun
69155bc60b
multi: obtain+verify aux sigs for all second level HTLCs
In this commit, we start to use the new AuxSigner to obtain+verify aux sigs for all second level HTLCs. This is similar to the existing SigPool, but we'll only attempt to do this if the AuxSigner is present (won't be for most channels).
2024-10-11 14:16:35 +02:00
Oliver Gugger
4db0d76ca4
lnwire: add custom records field to type CommitSig 2024-10-11 14:16:35 +02:00
Olaoluwa Osuntokun
b83783cc3d
lnwallet: add WithAuxSigner option to channel 2024-10-11 14:16:35 +02:00
Oliver Gugger
6d3f8af007
lnwallet: clarify usage of cancel and response channels 2024-10-11 14:16:35 +02:00
Oliver Gugger
266aba8a6c
lnwallet: allow read-only access to HtlcView's HTLCs
Due to a recent refactor, the HTLCs are no longer an exported type.
Custom channels need access to those updates, so we provide them in a
read-only manner.
2024-10-11 14:16:35 +02:00
Olaoluwa Osuntokun
6dda51d026
lnwallet: add new AuxSigner interface to mirror SigPool
In this commit, we add a new aux signer interface that's meant to mirror the SigPool. If present, this'll be used to (maybe) obtain signatures for second level HTLCs for certain classes of custom channels.
2024-10-11 14:16:35 +02:00
Oliver Gugger
dbb87b4ef9
funding: inform aux controller about channel ready/finalize 2024-10-11 14:16:34 +02:00
Oliver Gugger
18dca6f4c8
multi: add tapscript root to gossip message 2024-10-11 14:16:34 +02:00
Olaoluwa Osuntokun
1402f087ab
funding+lnwallet: finish hook up new aux funding flow
For the initiator, once we get the signal that the PSBT has been
finalized, we'll call into the aux funder to get the funding desc. For
the responder, once we receive the funding_created message, we'll do the
same.

We now also have local+remote aux leaves for the commitment transaction.

Some old TODO comments that in retrospect aren't required anymore are
removed as well.
2024-10-11 14:16:34 +02:00
Olaoluwa Osuntokun
f2dff16c37
funding+lnwallet: only blind tapscript root early in funding flow
In this commit, we modify the aux funding work flow slightly. We won't
be able to generate the full AuxFundingDesc until both sides has
sent+received funding params. So we'll now only attempt to bind the
tapscript root as soon as we send+recv the open_channel message.

We'll now also make sure that we pass the tapscript root all the way
down into the musig2 session creation.
2024-10-11 14:16:34 +02:00
Olaoluwa Osuntokun
39b1080166
lnwallet: for PsbtIntent return the internal key in the POutput
We also add a new assertion to the itests to ensure the field is being properly set.
2024-10-11 14:16:34 +02:00
Olaoluwa Osuntokun
0a7139c9ca
lnwallet: add TaprootInternalKey method to ShimIntent
If this is a taproot channel, then we'll return the internal key which'll be useful to callers.
2024-10-11 14:16:34 +02:00
Olaoluwa Osuntokun
723621bd2b
config+serer: add AuxFundingController as top level cfg option 2024-10-11 14:16:34 +02:00
Olaoluwa Osuntokun
7f3aff9e10
funding: create new AuxFundingController interface
In this commit, we make a new `AuxFundingController` interface capable of processing messages off the wire. In addition, we can use it to abstract away details w.r.t how we obtain a `AuxFundingDesc` for a given channel.

We'll now use this whenever we get a channel funding request, to make sure we pass along the custom state that a channel may require.
2024-10-11 14:16:33 +02:00
Olaoluwa Osuntokun
5f5bbf9ae2
lnwallet: use AuxFundingDesc to populate all custom chan info
With this commit, we'll now populate all the custom channel information within the OpenChannel and ChannelCommitment structs.
2024-10-11 14:16:33 +02:00
Olaoluwa Osuntokun
f73f5f5582
lnwallet: add new AuxFundingDesc struct
This struct will house all the information we'll need to do a class of custom channels that relies primarily on adding additional items to the tapscript root of the HTLC/commitment/funding outputs.
2024-10-11 14:16:33 +02:00
Oliver Gugger
a7534597dd
Merge branch '0-18-4-branch-rc1-8981' into 0-18-4-branch-rc1 2024-10-11 14:15:30 +02:00
Keagan McClelland
56866448dc
lnwallet: remove unnecessary chanID argument form unsignedLocalUpdates 2024-10-11 14:15:16 +02:00
Keagan McClelland
f8979c0614
htlcswitch+lnwallet: quarantine paymentDescriptor to lnwallet
The objective of this commit is to make paymentDescriptor a private
data structure so we can quarantine it to the lnwallet package.
To accomplish this we had to prevent it from leaking out via the
arguments or return values of the public functions in lnwallet.
This naturally had consequences for the htlcswitch package as we
choose other mechanisms for tracking the data that paymentDescriptor
was responsible for.

Astoundingly, this was highly successful and allowed us to remove
a ton of redundant code. The diff for this commit represents a
substantial reduction in total lines of code as well as extraneous
arguments and return values from key functions.

This also sets the stage for future commits where we actually will
be attempting to rid lnwallet of paymentDescriptor completely.
2024-10-11 14:15:14 +02:00
Keagan McClelland
7e5f6b5802
lnwallet: remove unused function PayDescsFromRemoteLogUpdates
This function is no longer used as of the last commit and it is the
last remaining leak of the PaymentDescriptor type through the public
API.
2024-10-11 14:14:41 +02:00
Keagan McClelland
addf9e8dbe
htlcswitch: remove PaymentDescriptor conversion from reforwardSettleFails
This is part of a systematic removal of PaymentDescriptor from the mechanics
of the htlcswitch package.
2024-10-11 14:14:41 +02:00
Keagan McClelland
870800b81a
htlcswitch+lnwallet: remove PaymentDescriptor from ReceiveRevocation returns
This is part of a systematic removal of PaymentDescriptor from the public
API of the lnwallet package. This marks the last change needed before we
make the PaymentDescriptor structure private.
2024-10-11 14:14:41 +02:00
Keagan McClelland
a3e127d1d6
htlcswitch: remove PaymentDescriptor from processRemoteSettleFails call signature
This is part of a systematic removal of PaymentDescriptor from the mechanics
of the htlcswitch package.
2024-10-11 14:14:41 +02:00
Keagan McClelland
875d2e4664
htlcswitch: remove PaymentDescriptor from processRemoteAdds call signature
This is part of a systematic removal of PaymentDescriptor from the mechanics
of the htlcswitch package.
2024-10-11 14:14:41 +02:00
Keagan McClelland
dd9568b648
htlcswitch: remove PaymentDescriptor from hodlHtlc
This is part of a systematic removal of PaymentDescriptor from the
mechanics of the htlcswitch package.
2024-10-11 14:14:40 +02:00
Keagan McClelland
e7d545fb0a
htlcswitch: remove PaymentDescriptor from the processExitHop's call signature
This is part of a systematic removal of PaymentDescriptor from the mechanics
of the htlcswitch package.
2024-10-11 14:14:40 +02:00
Keagan McClelland
160747cf5e
htlcswitch: remove PaymentDescriptor from settleHTLC's call signature
This is done as part of a systematic removal of PaymentDescriptor from
the mechanics of the htlcswitch package.
2024-10-11 14:14:40 +02:00
Keagan McClelland
22b2568f22
htlcswitch: remove PaymentDescriptor from sendHTLCError's call signature
This is done as part of a systematic removal of PaymentDescriptor from
the mechanics of the htlcswitch package.
2024-10-11 14:14:40 +02:00
Keagan McClelland
7f2fe2e5ff
channeldb: add convenience functions for generating Source/Dest Refs 2024-10-11 14:14:40 +02:00
Keagan McClelland
d364b9b9f8
lnwallet: add function to convert paymentDescriptor to LogUpdate
Here we add a function that is capable of recovering LogUpdates from
paymentDescriptors and we refactor the lnwallet code to use this
rather than doing JIT inline construction of the LogUpdates.
2024-10-11 14:14:40 +02:00
Keagan McClelland
9904af5d96
lnwire+htlcswitch: change NewInvalidBlinding to use array instead of slice 2024-10-11 14:14:40 +02:00
Keagan McClelland
e4497b4f45
htlcswitch: change sendMalformedHTLCError to take array instead of slice 2024-10-11 14:14:39 +02:00
Keagan McClelland
fb841b6436
htlcswitch+lnwallet: fix OnionBlob to 1366 bytes 2024-10-11 14:14:39 +02:00
Keagan McClelland
391370de20
lnwallet: track ChannelID on PaymentDescriptor
In this commit we track the ChannelID on the PaymentDescriptor.
This will be useful in upcoming commits that need to be able to
reconstruct lnwire.Message values from PaymentDescriptors as the
Messages that are exchanged to update channel state all include
the ChannelID.
2024-10-11 14:14:39 +02:00
Keagan McClelland
a40d363936
lnwallet: add ChannelID method to LightningChannel
In this commit we introduce a convenience method to LightningChannel
to allow us to quickly grab the channel id. This will be important
in upcoming commits where we need to remember the ChannelID to
reconstruct update messages.
2024-10-11 14:14:39 +02:00
Oliver Gugger
8cb8f589ee
Merge branch '0-18-4-branch-rc1-9049' into 0-18-4-branch-rc1 2024-10-11 14:13:49 +02:00
George Tsagkarelis
b0be0adcef
itest: add interceptor and first hop data tests 2024-10-11 14:13:49 +02:00
Oliver Gugger
1822b2f79a
lnrpc: add first hop custom data to route 2024-10-11 14:13:48 +02:00
George Tsagkarelis
444ef199a6
routing: use first hop records on path finding 2024-10-11 14:13:48 +02:00
Oliver Gugger
5489b06628
channeldb+routing: persist first hop custom data for route 2024-10-11 14:13:48 +02:00
George Tsagkarelis
6ac750955f
lnd: use impl cfg TlvTrafficShaper 2024-10-11 14:13:48 +02:00
Olaoluwa Osuntokun
ec2b2c6e1e
routing: skip amtInRange for custom HTLCs
We might be trying to send an invoice amount that's greater than the size of the channel, but once you factor in the custom channel logic, an actual HTLC can be sent over the channel to pay that larger payment.

As a result, we'll skip over this check if a have a custom HTLC.
2024-10-11 14:13:48 +02:00
George Tsagkarelis
f927563049
routing: add TlvTrafficShaper to bandwidth hints 2024-10-11 14:13:48 +02:00
George Tsagkarelis
69430ce042
htlcswitch: expose custom channel blob from link 2024-10-11 14:13:48 +02:00
George Tsagkarelis
c70832a823
lnwallet: expose commitment blob from channel 2024-10-11 14:13:47 +02:00
Oliver Gugger
0403b97a87
lnrpc: add first hop custom records to RPC payment info 2024-10-11 14:13:47 +02:00
Oliver Gugger
ff1a45549e
channeldb+routing: persist first hop custom records
With this commit we make sure the first hop custom records aren't lost
on restart/resume of a payment, so we persist it as part of the
PaymentCreationInfo struct.
2024-10-11 14:13:47 +02:00
George Tsagkarelis
857a16d838
lnrpc: add wire records fields to payment+interceptor RPCs 2024-10-11 14:13:47 +02:00
George Tsagkarelis
ef2c9801fb
multi: use wire records on payment and intercept flows 2024-10-11 14:13:47 +02:00
Oliver Gugger
b5efc0ef3e
lnwallet: extract diskCommit, remove unused error return value 2024-10-11 14:13:47 +02:00
ffranr
1b28f47c1d
itest: add itest for field modification HTLC interception response
Implement an integration test where an HTLC is intercepted and the
interception response modifies fields in the resultant p2p message.
2024-10-11 14:13:47 +02:00
ffranr
533b9f2d45
routerrpc: extend HTLC forward interceptor resp with modification fields
This commit extends the forward HTLC intercept response with fields that
can be used in conjunction with a `ResumeModified` action to modify the
intercepted HTLC p2p message.
2024-10-11 14:13:46 +02:00
ffranr
49db662b82
htlcswitch: add resume modified HTLC action to switch
Introduce `ResumeModified` action to resume standard behavior of a p2p
message with optional modifications as specified by the client during
interception.
2024-10-11 14:13:46 +02:00
ffranr
cb15297853
lnwire: add custom records field to type UpdateFulfillHtlc
- Introduce the field `CustomRecords` to the type `UpdateFulfillHtlc`.
- Encode and decode the new field into the `ExtraData` field of the
`update_fulfill_htlc` wire message.
- Empty `ExtraData` field is set to `nil`.
2024-10-11 14:13:46 +02:00
ffranr
2cfa89c719
lnwire: add custom records field to type UpdateAddHtlc
- Introduce the field `CustomRecords` to the type `UpdateAddHtlc`.
- Encode and decode the new field into the `ExtraData` field of
  the `update_add_htlc` wire message.
2024-10-11 14:13:46 +02:00
ffranr
ed69bb8757
lnwire: add ExtraOpaqueData helper functions and methods
Introduces a couple of new helper functions for both the ExtraOpaqueData
and CustomRecords types along with new methods on the ExtraOpaqueData.
2024-10-11 14:13:46 +02:00
ffranr
b07e857aef
lnwire: add unit tests for ExtraOpaqueData.PackRecords 2024-10-11 14:13:46 +02:00
George Tsagkarelis
08ca28773c
itest: add dynamic scid alias routing test 2024-10-11 14:13:46 +02:00
George Tsagkarelis
d6ef2a122f
routerrpc: add XAddLocalChanAliases & XDeleteLocalChanAliases 2024-10-11 14:13:45 +02:00
Oliver Gugger
2b1f347f98
aliasmgr: export alias start and end ranges
Because we restrict custom SCID aliases to be in a specific range, we
export the range start and end values so a user of the RPCs we're going
to add in the next commits can adjust their values to fit within the
range.
2024-10-11 14:13:45 +02:00
Oliver Gugger
148ba49530
aliasmgr: avoid collision when requesting alias
With the new RPC calls that we are going to add in the next commits, it
will be possible for users to add (local only, non-gossipped) SCID
aliases for channels. Since those will be in the same range as the ones
given out by RequestAlias, we need to make sure that when we generate a
new one that it doesn't collide with an already existing one.
2024-10-11 14:13:45 +02:00
Oliver Gugger
4757e891a2
aliasmgr: add map type alias 2024-10-11 14:13:45 +02:00
George Tsagkarelis
4ef68512a9
multi: refresh htlcswitch aliases on aliasmgr update 2024-10-11 14:13:45 +02:00
George Tsagkarelis
0c95dc2118
aliasmgr: add delete local alias method 2024-10-11 14:13:45 +02:00
Oliver Gugger
2da56bd776
Merge branch '0-18-4-branch-rc1-9044' into 0-18-4-branch-rc1 2024-10-11 14:13:12 +02:00
Keagan McClelland
d4a4233e96
lnwallet+htlcswitch: define expanded NumPendingUpdates
This commit squashes the below operations for a net result where
we have an expanded capability of assessing pending updates. This
is made possible by packing the components into Duals in the prior
commits. We squash the operations to simplify review.

htlcswitch+lnwallet: rename PendingLocalUpdateCount

lnwallet: complete pending update queries API for LightningChannel

lnwallet+htlcswitch: consolidate NumPendingUpdates using ChannelParty

This commit makes the observation that we can cleanly define the
NumPendingUpdates function using a single expression by taking
advantage of the relevant fields being properly packed into Duals.
2024-10-11 14:12:54 +02:00
Keagan McClelland
b337213fb2
lnwallet: pack commitment message indices into Dual
This is yet another commit that packs a symmetric structure into
a Dual. This is the last one needed for the time being to consolidate
Num{X}UpdatesPendingOn{Y} functions into a single one.
2024-10-11 14:12:53 +02:00
Keagan McClelland
214dac0c45
lnwallet: pack update logs into Dual
This commit, like the last one packs the update logs into a symmetric
Dual structure. This will allow us to index into them more concisely
in higher order logic.
2024-10-11 14:12:52 +02:00
Keagan McClelland
61383f1014
lnwallet: pack commit chains into Dual
This commit packs the LightningChannel's localCommitmentChain and
remoteCommitmentChain into a Dual structure for better symmetric
access. This will be leveraged by an upcoming commit where we want
to more concisely express how we compute the number of pending
updates.
2024-10-11 14:12:28 +02:00
Keagan McClelland
89a94e9ac8
htlcswitch: extract error handling for syncChanStates 2024-10-11 14:12:27 +02:00
Oliver Gugger
767a6f99a5
Merge branch '0-18-4-branch-rc1-9030' into 0-18-4-branch-rc1 2024-10-11 14:11:58 +02:00
Oliver Gugger
b0728647c9
lnwallet: thread thru input.AuxTapleaf to all relevant areas
In this commit, we start to thread thru the new aux tap leaf structures to all relevant areas. This includes: commitment outputs, resolution creation, breach handling, and also HTLC scripts.
2024-10-11 14:11:58 +02:00
Oliver Gugger
860cacb70a
lnwallet: refactor commit keys to use lntypes.Dual 2024-10-11 14:11:58 +02:00
Oliver Gugger
b1c8a836e3
multi: thread thru the AuxLeafStore everywhere 2024-10-11 14:11:58 +02:00
Olaoluwa Osuntokun
180648072c
channeldb: add HtlcIndex to HTLCEntry
This may be useful for custom channel types that base everything off the index (a global value) rather than the output index (can change with each state).
2024-10-11 14:11:58 +02:00
Olaoluwa Osuntokun
eb600a9447
channeldb: add custom blobs to RevocationLog+HTLCEntry
This'll be useful for custom channel types that want to store extra information that'll be useful to help handle channel revocation cases.
2024-10-11 14:11:58 +02:00
Olaoluwa Osuntokun
1f785e897e
channeldb: convert RevocationLog to use RecordT 2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
314a24689c
channeldb: convert HTLCEntry to use tlv.RecordT 2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
12ab2c3b51
lnwallet: add TLV blob to PaymentDescriptor + htlc add
In this commit, we add a TLV blob to the PaymentDescriptor struct. We also now thread through this value from the UpdateAddHTLC message to the PaymentDescriptor mapping, and the other way around.
2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
ef56d8654e
lnwallet+channeldb: add new AuxLeafStore for dynamic aux leaves
In this commit, we add a new AuxLeafStore which can be used to dynamically fetch the latest aux leaves for a given state. This is useful for custom channel types that will store some extra information in the form of a custom blob, then will use that information to derive the new leaf tapscript leaves that may be attached to reach state.
2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
9db810d67a
input: add some utility type definitions for aux leaves
In this commit, we add some useful type definitions for the aux leaf.
2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
ae1b121cdd
lnwallet: add custom tlv blob to internal commitment struct
In this commit, we also add the custom TLV blob to the internal commitment struct that we use within the in-memory commitment linked list.

This'll be useful to ensure that we're tracking the current blob for our in memory commitment for when we need to write it to disk.
2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
da9ceb131b
lnwallet: export the HtlcView struct
We'll need this later on to ensure we can always interact with the new aux blobs at all stages of commitment transaction construction.
2024-10-11 14:11:57 +02:00
Olaoluwa Osuntokun
cd155d7d17
channeldb: new custom blob nested TLV
In this commit, for each channel, we'll now start to store an optional custom blob. This can be used to store extra information for custom channels in an opauqe manner.
2024-10-11 14:11:56 +02:00
Olaoluwa Osuntokun
41bd293f33
input+lnwallet: update taproot scripts to accept optional aux leaf
In this commit, we update all the taproot scripts to also accept an
optional aux leaf. This aux leaf can be used to add more redemption
paths for advanced channels, or just as an extra commitment space.
2024-10-11 14:11:56 +02:00
Olaoluwa Osuntokun
ca5dcbbf5c
lnwallet: add initial unit tests for musig2+tapscript root chans 2024-10-11 14:11:56 +02:00
Olaoluwa Osuntokun
cae4f21897
lnwallet+peer: add tapscript root awareness to musig2 sessions
With this commit, the channel is now aware of if it's a musig2 channel, that also has a tapscript root. We'll need to always pass in the tapscript root each time we: make the funding output, sign a new state, and also verify a new state.
2024-10-11 14:11:56 +02:00
Olaoluwa Osuntokun
62713c1270
lnwallet: update internal funding flow w/ tapscript root
This isn't hooked up yet to the funding manager, but with this commit, we can now start to write internal unit tests that handle musig2 channels with a tapscript root.
2024-10-11 14:11:56 +02:00
Olaoluwa Osuntokun
b7e153fd82
multi: update GenTaprootFundingScript to pass tapscript root
In most cases, we won't yet be passing a root. The option usage helps us keep the control flow mostly unchanged.
2024-10-11 14:11:56 +02:00
Olaoluwa Osuntokun
9fd8287c7b
lnwallet/chanfunding: add optional tapscript root 2024-10-11 14:11:55 +02:00
Olaoluwa Osuntokun
1e71b1e544
multi: add new tapscript root option to GenTaprootFundingScript
This'll allow us to create a funding output that uses musig2, but uses a tapscript tweak rather than a normal BIP 86 tweak.
2024-10-11 14:11:55 +02:00
Olaoluwa Osuntokun
74cb1f48ad
channeldb: add optional TapscriptRoot field + feature bit 2024-10-11 14:11:55 +02:00
Olaoluwa Osuntokun
e71627f893
channeldb: consolidate root bucket TLVs into new struct
In this commit, we consolidate the root bucket TLVs into a new struct.
This makes it easier to see all the new TLV fields at a glance. We also
convert TLV usage to use the new type param based APis.
2024-10-11 14:11:55 +02:00
Oliver Gugger
264dcd0641
Merge branch '0-18-4-branch-rc1-9025' into 0-18-4-branch-rc1 2024-10-11 14:04:01 +02:00
Oliver Gugger
830dd49fa8
routing+lnrpc: fix log statements 2024-10-11 14:04:00 +02:00
Oliver Gugger
1447493081
server: fix logging of pubkey 2024-10-11 14:04:00 +02:00
Oliver Gugger
2d6ba8c056
cmd/commands: export StripPrefix 2024-10-11 14:04:00 +02:00
Oliver Gugger
4fd1abfe52
lnwallet: add Tree() method, fix formatting 2024-10-11 14:04:00 +02:00
Oliver Gugger
89f75e7d1b
lnwallet: export GenTaprootHtlcScript 2024-10-11 14:04:00 +02:00
Oliver Gugger
29f139225b
lnwallet: export AnchorSize 2024-10-11 14:04:00 +02:00
Oliver Gugger
90470065ba
cmd/lncli: move commands and export
We want to export some of our CLI code to re-use in other projects. But
in Golang you cannot import code from a `main` package.
So we need to move the actual code into its own package and only have
the `func main()` in the `main` package.
2024-10-11 14:04:00 +02:00
Olaoluwa Osuntokun
41ca01a1b7
funding: use atomic.Uint64 for chanIDNonce
This lets us get rid of the mutex usage there. We also shift the algo slightly to increment by 1, then use that as the next value, which plays nicer with the atomics.
2024-10-11 14:03:59 +02:00
Olaoluwa Osuntokun
cd5fa5976a
funding: add new type alias for PendingChanID = [32]byte
This'll be useful for new interface definitions that use the contents of the package.
2024-10-11 14:03:59 +02:00
ffranr
b59ecc9270
htlcswitch: add missing method doc 2024-10-11 14:03:59 +02:00
ffranr
cc2b7b6fda
multi: improve comment grammar 2024-10-11 14:03:59 +02:00
ffranr
58ed8e751d
lnwire: add type CustomRecords
This commit introduces the `CustomRecords` type in the `lnwire` package,
designed to hold arbitrary byte slices. Each entry in this map can
associate with TLV type values that are greater than or equal to 65536.
2024-10-11 14:03:59 +02:00
Oliver Gugger
1893104392
mod: bump tlv to v1.2.6 2024-10-11 14:03:59 +02:00
Olaoluwa Osuntokun
213618adcc
lnwallet/chanfunding: rename assembler.go to interface.go
In this commit, we rename the files as assembler.go houses the primary
interfaces/abstractions of the package. In the rest of the codebase,
this file is near uniformly called interface.go, so we rename the file
to make the repo more digestible at a scan.
2024-10-11 14:03:59 +02:00
Oliver Gugger
7e656257d1
Merge branch '0-18-4-branch-rc1-9007' into 0-18-4-branch-rc1 2024-10-11 14:02:44 +02:00
Oliver Gugger
c849f91590
.golangci: fix config, update new-from-rev 2024-10-11 14:02:31 +02:00
Oliver Gugger
03493d491b
multi: update linter, fix new issues 2024-10-11 14:02:30 +02:00
Oliver Gugger
7502bf3ad9
.golangci: remove or rename old and deprecated linters 2024-10-11 14:01:44 +02:00
Olaoluwa Osuntokun
e735f77d43
build: set min build version to Go 1.22.6
Go 1.23 was released this week, so with this PR we update the build
system to officially support the last two releases.
2024-10-11 14:01:44 +02:00
Oliver Gugger
3b5e1fa764
Merge branch '0-18-4-branch-rc1-8520' into 0-18-4-branch-rc1 2024-10-11 14:01:29 +02:00
Olaoluwa Osuntokun
8eae1eec4a
peer: don't stop global msg router
In this commit, we fix a bug that would cause a global message router to
be stopped anytime a peer disconnected. The global msg router only
allows `Start` to be called once, so afterwards, no messages would
properly be routed.
2024-10-11 14:01:29 +02:00
Olaoluwa Osuntokun
35e48838c3
multi: make MsgRouter available in the ImplementationCfg
With this commit, we allow the `MsgRouter` to be available in the
`ImplementationCfg`. With this, programs outside of lnd itself are able
to now hook into the message processing flow to direct handle custom
messages, and even normal wire messages.
2024-10-11 14:01:29 +02:00
Olaoluwa Osuntokun
e257188017
peer: update readHandler to dispatch to msgRouter if set
Over time with this, we should be able to significantly reduce the size
of the peer.Brontide struct as we only need all those deps as the peer
needs to recognize and handle each incoming wire message itself.
2024-10-11 14:01:29 +02:00
Olaoluwa Osuntokun
a888573fcc
msgmux: add new abstract message router
In this commit, we add a new abstract message router. Over time, the
goal is that this message router replaces the logic we currently have in
the readHandler (the giant switch for each message).

With this new abstraction, can reduce the responsibilities of the
readHandler to *just* reading messages off the wire and handing them off
to the msg router. The readHandler no longer needs to know *where* the
messages should go, or how they should be dispatched.

This will be used in tandem with the new `protofsm` module in an
upcoming PR implementing the new rbf-coop close.
2024-10-11 14:01:29 +02:00
Oliver Gugger
0719c808dd
Merge branch '0-18-4-branch-rc1-8996' into 0-18-4-branch-rc1 2024-10-11 11:42:24 +02:00
Keagan McClelland
8344699a0d
lntypes: Add Dual[A] primitive type
This commit introduces a new type Dual[A] to make it easier to
manage symmetric configurations or state for lightning channels.
2024-10-11 11:42:23 +02:00
Oliver Gugger
d72a3aaf26
Merge pull request #9088 from Roasbeef/0-18-3-branch
build: bump version to v0.18.3
2024-09-11 05:22:27 -06:00
Olaoluwa Osuntokun
6eea5f3b13
build: bump version to v0.18.3 2024-09-10 19:44:13 -07:00
Olaoluwa Osuntokun
4f40e43b26
Merge pull request #9061 from Roasbeef/0-18-3-branch
release: create branch for v0.18.3 rc3
2024-09-06 15:34:20 -07:00
Olaoluwa Osuntokun
d85ce8415b
build: bump version to v0.18.3 rc3 2024-09-06 12:59:37 -07:00
Olaoluwa Osuntokun
e1351eaa0a Merge branch '0-18-3-branch-9050' into 0-18-3-branch 2024-09-06 12:59:32 -07:00
Olaoluwa Osuntokun
ce442a5083 Merge branch '0-18-3-branch-9046' into 0-18-3-branch 2024-09-06 12:59:32 -07:00
Andras Banki-Horvath
d4fbc815c6 docs: update docs/release-notes/release-notes-0.18.3.md 2024-09-06 12:59:32 -07:00
Olaoluwa Osuntokun
2341019016 lnwallet: expand chan sync tests to cover taproot channels
In this commit, we expand some of the existing chan sync tests to cover
taproot channels (the others already did). Along the way, we always
assert that the `PartialSig` is populated on retransmission. In
addition, we now send the new commit sig rather than the existing
in-memory one to test the new logic that re-signs the commitment.
2024-09-06 12:59:32 -07:00
Andras Banki-Horvath
b62db3733d sqldb: fix end date filter when querying invoices
Previously, the SQL implementation of the invoice query simply
converted the start and end timestamps to time and used them
in SQL queries to check for inclusivity. However, this logic
failed when the start and end timestamps were equal.

This commit addresses and corrects this issue.
2024-09-06 12:59:32 -07:00
Andras Banki-Horvath
9298133614 sqldb+invoices: synchronize SQL invoice updater behavior with KV version
Previously SQL invoice updater ignored the set ID hint when updating an
AMP invoice resulting in update subscriptions returning all of the AMP
state as well as all AMP HTLCs. This commit synchornizes behavior with
the KV implementation such that we now only return relevant AMP state
and HTLCs when updating an AMP invoice.
2024-09-06 12:59:32 -07:00
Andras Banki-Horvath
b3dc3ed5c8 channeldb: filter AMP state to relevant set IDs
When fetching an AMP invoice we sometimes filter HTLCs to selected set
IDs, however we always kept the full AMP state which is irrelevant as it
contains state for all AMP payments. This was a side effect of
UpdateInvoice needing to serialize the whole invoice when storing after
an update but it is an unwanted "feature" as users will need to filter
to relevant set when listing an AMP payment or subsribing to an update.
2024-09-06 12:59:32 -07:00
Alex Akselrod
cadce23b47 invoices: ensure AMP subinvoices are correctly updated w/nativesql 2024-09-06 12:59:32 -07:00
Alex Akselrod
8c6e24346a itest: check that AMP subinvoices are correctly updated w/nativesql 2024-09-06 12:59:32 -07:00
Alex Akselrod
e152a52625 invoices/sqldb: query by ChanID when updating AMP invoice preimage 2024-09-06 12:59:32 -07:00
Olaoluwa Osuntokun
d13908881c lnwallet: extract initMusigNonce from initRevocationWindows
This'll be useful later to make some enhancements to the existing unit
tests.
2024-09-03 17:26:06 -07:00
Olaoluwa Osuntokun
c7300f452c lnwallet: ensure we re-sign retransmitted commits for taproot channels
In this commit, we fix an existing bug with the taproot channel type
that can cause force closes if a peer disconnects while attempting to
send the commitment signature.

Before this commit, since the `PartialSig` we send is never committed to
disk, the version read wouldn't contain the musig2 partial sig. We never
write these signatures to disk, as each time we make a new session, we
need to generate fresh nonces to avoid nonce-reuse.

Due to the above interaction, if we went to re-send a signature after a
disconnection, the `CommitSig` message we sent wouldn't actually contain
a `PartialSigWithNonce`, causing a protocol error.
2024-09-03 17:26:06 -07:00
Olaoluwa Osuntokun
3bb4d6d370
Merge pull request #9036 from Roasbeef/0-18-3-branch
release: bump version to v0.18.3 rc2
2024-08-28 18:48:05 -05:00
Olaoluwa Osuntokun
d111d8d53c
build: bump version to v0.18.3 rc2 2024-08-27 18:52:44 -05:00
Olaoluwa Osuntokun
e69fdf5b83 Merge branch '0-18-3-branch-9009' into 0-18-3-branch 2024-08-27 18:52:20 -05:00
Eugene Siegel
6111ac3468 release-notes: update for 0.18.3 2024-08-27 18:52:10 -05:00
Eugene Siegel
53a8d37df7 discovery: implement ChannelAnnouncement banning
This commit hooks up the banman to the gossiper:
- peers that are banned and don't have a channel with us will get
  disconnected until they are unbanned.
- peers that are banned and have a channel with us won't get
  disconnected, but we will ignore their channel announcements until
  they are no longer banned. Note that this only disables gossip of
  announcements to us and still allows us to open channels to them.
2024-08-27 18:52:10 -05:00
Eugene Siegel
ae33b760f8 graph: export NewErrf and ErrorCode for upcoming gossiper unit tests 2024-08-27 18:52:09 -05:00
Eugene Siegel
de58e3e98e discovery: clean up scid variable usage 2024-08-27 18:51:38 -05:00
Eugene Siegel
3e318b4187 multi: extend lnpeer.Peer interface with Disconnect function
This will be used in the gossiper to disconnect from peers if their
ban score passes the ban threshold.
2024-08-27 18:51:38 -05:00
Eugene Siegel
b7c4a3cd18 discovery: add banman for channel announcements
This commit introduces a ban manager that marks peers as banned if
they send too many invalid channel announcements to us. Expired
entries are purged after a certain period of time (currently 48 hours).
2024-08-27 18:51:38 -05:00
Eugene Siegel
4558eb04d0 channeldb: add PutClosedScid and IsClosedScid
This commit adds the ability to store closed channels by scid in
the database. This will allow the gossiper to ignore channel
announcements for closed channels without having to do any
expensive validation.
2024-08-27 18:51:38 -05:00
Olaoluwa Osuntokun
e431e5b71f Merge branch '0-18-3-branch-9026' into 0-18-3-branch 2024-08-26 20:19:31 -05:00
ziggie
72929079c9 docs: add release-notes. 2024-08-26 20:19:31 -05:00
ziggie
59355b17a5 blindedpath: minHTLC for blinded path change.
We will not add a buffer to the chan policy for blinded paths in case
the sender amount violates the minHTLC restriction in the first place.

Moreover we disgard a route fast if the payment amount is smaller than
the minHTLC along the route.
2024-08-26 20:19:31 -05:00
ziggie
89ef3737b1 blindedpath: fix log output. 2024-08-26 20:19:31 -05:00
ziggie
38c81516ec blindedpath: remove blockexpiry check.
Removes a check where we would NOT allow to create a blinded invoice
with an expiry (invoice expiry in seconds considered as block time)
lower than the min_final_ctlv_delta.
2024-08-26 20:19:31 -05:00
Olaoluwa Osuntokun
dbe4ca3efe Merge branch '0-18-3-branch-9011' into 0-18-3-branch 2024-08-26 20:19:11 -05:00
ziggie
4102e33670 docs: update release-notes. 2024-08-26 20:19:11 -05:00
ziggie
d906010508 discovery: add detailed comment.
Describe why it is ok to resurrect zombie channels based on the
timestamp of the `ReplyChannelRange` msg although its not verifiable
data.
2024-08-26 20:19:11 -05:00
ziggie
44413868c7 multi: fix time.Time initialization.
ChanUpdate timestamps are now restircted so that they cannot be
more than two weeks into the future. Moreover channels with both
timestamps in the ReplyChannelRange msg either too far in the past
or too far in the future are not queried.

Moreover fix unitests.
2024-08-26 20:19:11 -05:00
ziggie
b23e69c0b7 discovery: fix log line.
if we use %x here we would get the hex representation of the
String() method of the vertex, which is wrong.
2024-08-26 20:19:11 -05:00
Olaoluwa Osuntokun
53799e9f91 Merge branch '0-18-3-branch-9002' into 0-18-3-branch 2024-08-26 20:18:47 -05:00
Olaoluwa Osuntokun
57221bd760 discovery: fix bug that can lead to sending invalid chan_ann msgs
Initially in lnd, we didn't store the extra TLV data that could be
dangling off of gossip messages. This was fixed initially in lnd v0.5
with this PR: https://github.com/lightningnetwork/lnd/pull/1825.

Within the PR, we incorrect set the `ExtraOpaqueData` (extra TLV blob)
of the `ChannelAnnouncement` to the value stored in `edge`, which is
actually our channel update. As 6-ish years ago we didn't yet have
anything that used the TLV gossip fields, this went unnoticed.

Fast forward to 2024, we shipped an experimental version of inbounbd
fees. This starts to store additional data in the `ExtraOpaqueData`
field, the TLV for the inbound fee. Initially, everything is valid when
the first `ChannelAnnouncement` is sent, but as soon as a user attempts
to set an inbound fee policy, we'd incorrectly swap in that new
serialized TLV for the _channel announcement_:
841e24399c (diff-1eda595bbebe495bd74a6a0431c46b66cb4e8b53beb311067c010feac2665dcbR2560).

Since we're just trying to generate a new `channel_update`, we don't
also regenerate the signature for the `channel_announcement` message. As
a result, we end up storing a `channel_announcement` with an invalid sig
on disk, continuing to broadcast that to peers.
2024-08-26 20:18:29 -05:00
Oliver Gugger
8f25de054d
Merge pull request #9023 from ellemouton/testHTLCPersistenceAcrossRestart
lnwallet: correctly set UpdateAddHTLC.BlindingPoint on reload from disk
2024-08-22 07:29:50 -06:00
Elle Mouton
e99b09d38a
docs: update release notes 2024-08-22 14:21:30 +02:00
Elle Mouton
fcbd1e14d3
lnwallet+itest: fix PaymentDescriptor creation for blinded path htlc
This commit fixes the instantiation of the BlindingPoint member of
PaymentDescriptor during the conversion from persisted LogUpdates.
Previously, the blinding point was not set correctly. The test from the
previous commit is also updated to now assert that this behaviour is now
correct.
2024-08-22 14:21:30 +02:00
Elle Mouton
58fa379cc7
itest: demonstrate UpdateAddHTLC reloading bug
This commit adds a new route blinding itest that demonstrates that the
reloading and re-forwarding of an UpdateAddHTLC message on restart
currently is done incorrectly for a blinded path payment. This is due to
the fact that the blinding point member is not currently set correctly.
This is fixed in the next commit which will also change the test to
assert that the behaviour is now correct.
2024-08-22 14:21:30 +02:00
Olaoluwa Osuntokun
8d5f66b5fc
Merge pull request #8995 from Roasbeef/0-18-3-branch-rc1
build: bump to v0.18.3-beta.rc1
2024-08-09 13:58:50 -07:00
Olaoluwa Osuntokun
7c2cf49d66
build: bump to v0.18.3-beta.rc1 2024-08-09 13:58:05 -07:00
rockstardev
d946972ac8 Updating README 2024-07-07 08:18:03 -05:00
rockstardev
c28190c73b Documenting LND update process 2024-07-07 08:11:14 -05:00
rockstardev
a309bbbbf0 Merge branch 'lnd/v0.18.1-beta' and Update README
# Conflicts:
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2024-07-07 08:05:27 -05:00
rockstardev
fc7b2c1d59 Merge branch 'lnd/v0.18.0-beta' and Update README
# Conflicts:
#	.github/workflows/main.yml
#	Makefile
#	README.md
#	build/version.go
#	contractcourt/channel_arbitrator.go
#	docs/release-notes/release-notes-0.17.4.md
#	go.mod
#	go.sum
#	htlcswitch/link.go
#	itest/list_on_test.go
#	itest/lnd_channel_backup_test.go
#	itest/lnd_channel_force_close_test.go
#	itest/lnd_multi-hop_test.go
#	itest/lnd_onchain_test.go
#	itest/lnd_open_channel_test.go
#	itest/lnd_psbt_test.go
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
#	lncfg/config.go
#	lncfg/dev.go
#	lncfg/dev_integration.go
#	lnrpc/walletrpc/walletkit.pb.go
#	lntest/harness.go
#	lnwallet/channel.go
#	lnwallet/channel_test.go
#	peer/brontide.go
#	peer/brontide_test.go
#	peer/test_utils.go
#	server.go
#	sweep/sweeper.go
#	sweep/tx_input_set.go
#	sweep/txgenerator.go
2024-07-07 08:04:55 -05:00
rockstardev
6495ab7066 Updating README 2024-07-07 08:03:26 -05:00
rockstardev
9f94d045ae Adding BtcPayServer related files and resources 2024-07-07 06:11:06 -05:00
Olaoluwa Osuntokun
42b856dbb9
Merge pull request #8866 from ellemouton/0-18-1-fix
build: create v0.18.1-beta release branch
2024-06-25 15:34:32 -07:00
Oliver Gugger
f695451da0
build: bump version to v0.18.1-beta 2024-06-25 13:54:50 -07:00
yyforyongyu
362182bd88
docs: update release notes for 0.18.1-beta 2024-06-25 13:46:56 -07:00
yyforyongyu
e34702ab5b
mod: update btcd and btcwallet versions 2024-06-25 13:46:56 -07:00
rockstardev
c841954c51 Bumping golang to 1.22.3 2024-05-31 08:51:13 -05:00
rockstardev
b3aecc7ac5 Bumping loop to 0.28.2 2024-05-31 08:35:44 -05:00
rockstardev
0faa1f4de2 Adding BtcPayServer related files and resources 2024-05-31 08:33:46 -05:00
rockstardev
f6f5e312f3 Merge commit '3da3d28064d2712400f1b579bd4dfa34e04fd227' 2024-05-31 08:25:35 -05:00
rockstardev
8fca329810 Merge basedon-v0.17.3-beta
# Conflicts:
#	docker-initunlocklnd.sh
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2024-05-31 08:25:24 -05:00
rockstardev
9b43b0aa1a Merge commit 'b8c6baa94a949297397faba034a0979fd365609a' 2024-05-31 08:24:06 -05:00
rockstardev
6de26dc8ad Merge basedon-v0.17.1-beta
# Conflicts:
#	build/version.go
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2024-05-31 08:23:52 -05:00
rockstardev
3da3d28064 Adding BtcPayServer related files and resources 2024-02-06 21:29:46 -06:00
Olaoluwa Osuntokun
8bba79222f
build: bump version to v0.17.4-beta 2024-02-05 16:32:42 -08:00
Olaoluwa Osuntokun
ab8f319750
Merge pull request #8455 from Roasbeef/v0-17-4-branch
release: update v0.17.4 release branch to rc2
2024-02-05 11:57:31 -08:00
Olaoluwa Osuntokun
504f0d0024
build: bump version to v0.17.4 rc2 2024-02-02 17:08:07 -08:00
Olaoluwa Osuntokun
18d94a22a3 Merge branch 'v0-17-4-branch-7372' into v0-17-4-branch 2024-02-02 17:06:44 -08:00
Andras Banki-Horvath
b119ac87f9 docs: update release notes for 0.17.4 2024-02-02 17:06:27 -08:00
Andras Banki-Horvath
b1506eca95 itests: add itest for ListSweeps's start_height 2024-02-02 17:05:25 -08:00
Andras Banki-Horvath
1ae89d67ad walletkit: add startheight parameter to ListSweeps
By default ListSweeps will list all sweeps known to the wallet. Over
time this may become expensive to call and callers may not be interested
in the full history. This commit adds a `startheight` parameter to the
`ListSweeps` RPC call. This parameter can be used to fetch sweeps only
from a specified start block height or only unconfirmed ones if it is
set to -1.
2024-02-02 17:04:18 -08:00
Olaoluwa Osuntokun
ed6f03ea3e
Merge pull request #8416 from Roasbeef/v0-17-4-branch
release: create v0.17.4 rc1 release branch
2024-01-30 15:32:34 -08:00
Olaoluwa Osuntokun
b5cfc2fa05 Merge branch 'v0-17-4-branch-8437' into v0-17-4-branch 2024-01-30 11:24:27 -08:00
Elle Mouton
8f1460464e tls_manager: let REST proxy skip tls cert verification 2024-01-30 11:24:12 -08:00
Olaoluwa Osuntokun
6cbe5172d6 Merge branch 'v0-17-4-branch-8428' into v0-17-4-branch 2024-01-29 17:58:17 -08:00
ziggie
b02bbd5e95 docs: update release-notes. 2024-01-29 17:58:08 -08:00
ziggie
f9a2818d95 mod: update btcwallet version.
Update the btcwallet version to fix a case where fetching of
already pruned blocks from our peers was not garbage collected
when the request failed.
2024-01-29 17:57:14 -08:00
Olaoluwa Osuntokun
08cb77c415
build: bump version to v0.17.4-beta.rc1 2024-01-24 16:52:01 -08:00
Olaoluwa Osuntokun
2859a5a16d Merge branch 'v0-17-4-branch-8401' into v0-17-4-branch 2024-01-24 16:51:00 -08:00
yyforyongyu
a6fc5a901a chainreg: satisfy chain.Interface in NoChainSource 2024-01-24 16:50:52 -08:00
yyforyongyu
6d566068df docs: update release notes for mem leak fix 2024-01-24 16:50:51 -08:00
yyforyongyu
033292f2c2 blockcache: fix heap escape in GetBlock
This commit fixes a heap escape found in `GetBlock`. This happens
because the `msgBlock` is a pointer returned from `getBlockImpl`, and
the whole `getBlockImpl` escapes to the heap because it's referenced in
two places,
- in the `Cache`, it's used as a reference type to create the new block.
- this pointer is also returned and now needs to stay on the heap.

The fix is simple, we now make a copy of the block and use the copy
instead, freeing `getBlockImpl` from the heap.
2024-01-24 16:48:32 -08:00
yyforyongyu
68c24831df gomod: update btcd version to fix mem leak 2024-01-24 16:48:30 -08:00
Olaoluwa Osuntokun
599ff50fd4 Merge branch 'v0-17-4-branch-8406' into v0-17-4-branch 2024-01-24 16:46:48 -08:00
ziggie
a258ff74e9 docs: add release-notes. 2024-01-24 16:46:40 -08:00
ziggie
8a825a4687 multi: Add itest for a failed funding flow.
This adds an itest for a failed funding flow by our peer.
2024-01-24 16:46:38 -08:00
ziggie
192c35b2c7 peer: add unit test.
Add a unit test for the removal of a pending channel.
2024-01-24 16:46:02 -08:00
ziggie
39206a96fb funding: initialize remove channel. 2024-01-24 16:46:02 -08:00
Olaoluwa Osuntokun
0d5deef407 Merge branch 'v0-17-4-branch-8413' into v0-17-4-branch 2024-01-24 16:45:41 -08:00
Elle Mouton
c2a597747d docs: add template for 0.17.4 2024-01-24 16:45:41 -08:00
rockstardev
ba80ce46e4 Adding BtcPayServer related files and resources 2023-12-24 23:39:40 -06:00
Olaoluwa Osuntokun
13aa7f9924
build: bump version to v0.17.3-beta 2023-12-05 16:37:53 -08:00
Olaoluwa Osuntokun
d5b05d6930
Merge pull request #8241 from Roasbeef/v0-17-3-branch
release: create v0.17.3-beta.rc1 release branch
2023-12-01 14:17:21 -08:00
Olaoluwa Osuntokun
937fe6fda6
build: bump version to v0.17.3-beta.rc1 2023-11-30 15:08:20 -08:00
Olaoluwa Osuntokun
f550d04c7d Merge branch 'v0-17-3-branch-8232' into v0-17-3-branch 2023-11-30 15:06:14 -08:00
yyforyongyu
01eb7e539a gomod: update btcwallet version 2023-11-30 15:06:14 -08:00
Olaoluwa Osuntokun
b4425f6eea Merge branch 'v0-17-3-branch-8151' into v0-17-3-branch 2023-11-30 15:05:52 -08:00
Eugene Siegel
41e251b0d7 release-notes: update for 0.17.3 2023-11-30 15:05:52 -08:00
Eugene Siegel
dd2ead1022 routing: launch fetchFundingTx in goroutine so router can exit
This commit introduces a wrapper function fetchFundingTxWrapper
which calls fetchFundingTx in a goroutine. This is to avoid an issue
with pruned nodes where the router is attempting to stop, but the
prunedBlockDispatcher is waiting to connect to peers that can serve
the block. This can cause the shutdown process to hang until we
connect to a peer that can send us the block.
2023-11-30 15:05:52 -08:00
Olaoluwa Osuntokun
5565dffbd1 Merge branch 'v0-17-3-branch-8220' into v0-17-3-branch 2023-11-30 15:01:15 -08:00
yyforyongyu
87b4749d60 docs: add release notes for v0.17.3 2023-11-30 15:01:15 -08:00
yyforyongyu
bb27135477 lnwallet: make sure loop var is properly referenced 2023-11-30 15:01:15 -08:00
yyforyongyu
c6d52147e8 lnwallet: add unit test for extractPayDescs 2023-11-30 15:01:15 -08:00
yyforyongyu
8ac3480942 multi: enhance logging around channel reestablishment 2023-11-30 15:01:15 -08:00
Olaoluwa Osuntokun
97975098b9 Merge branch 'v0-17-3-branch-8224' into v0-17-3-branch 2023-11-30 14:58:52 -08:00
yyforyongyu
c6836d777e docs: add release notes for v0.17.3 2023-11-30 14:58:52 -08:00
yyforyongyu
dd8be9fc87 lntest: add verbose logging when node fails to shutdown 2023-11-30 14:58:52 -08:00
yyforyongyu
23e177514f input: use lnutils.SyncMap to store musig2 sessions 2023-11-30 14:58:52 -08:00
rockstardev
b8c6baa94a Adding BtcPayServer related files and resources 2023-11-20 14:43:29 -06:00
Olaoluwa Osuntokun
6744c64e62
build: bump version to v0.17.2-beta 2023-11-20 14:31:32 -06:00
Olaoluwa Osuntokun
ceb8e8a109
Merge pull request #8187 from Roasbeef/v0-17-2-branch
release: create v0.17.2-beta release branch
2023-11-17 16:10:27 -08:00
Olaoluwa Osuntokun
0aaf144b76
build: bump version to v0.17.2-beta.rc2 2023-11-17 18:09:34 -06:00
Olaoluwa Osuntokun
01761ab99b
docs/release-notes: update release notes for v0.17.2 2023-11-17 18:09:17 -06:00
Olaoluwa Osuntokun
04e0c9bc39 Merge branch 'v0-17-2-branch-8198' into v0-17-2-branch 2023-11-17 18:05:43 -06:00
Matt Morehouse
a331308a02 peer: add test for startup race on writeMessage
The test reliably detects
https://github.com/lightningnetwork/lnd/issues/8184.
2023-11-17 18:05:43 -06:00
Matt Morehouse
a283fc62fa peer: enable mockMessageConn to detect data races
We use unsynchronized counters to trigger a report under the race
detector if multiple reads or writes happen concurrently.
2023-11-17 18:05:43 -06:00
Matt Morehouse
0f5e4077ba peer: add missing Close() method to mockMessageConn 2023-11-17 18:05:43 -06:00
Olaoluwa Osuntokun
2988c85479
docs/release-notes: add release notes for v0.17.2 2023-11-16 13:08:15 -08:00
Eugene Siegel
a41833c466 peer: send reestablish, shutdown messages before starting writeHandler
This is to avoid a potential race on WriteMessage and Flush internals.
Because there is no locking on WriteMessage and Flush, if we allow
writeMessage calls in Start after the writeHandler has started,
the writeMessage calls may call WriteMessage/Flush at the same time
that writeMessage calls from the writeHandler does. Since there is
no locking, internals like b.nextHeaderSend can race and cause
panics.
2023-11-16 13:05:16 -08:00
rockstardev
c8bd66e881 Adding BtcPayServer related files and resources 2023-11-14 20:45:27 -06:00
Olaoluwa Osuntokun
744feb04e2
build: bump version to v0.17.1-beta 2023-11-13 11:13:18 -08:00
Olaoluwa Osuntokun
eea15f0952
Merge pull request #8162 from Roasbeef/v0-17-1-branch-rc3
build: create v0.17.1 rc3 release branch
2023-11-08 17:10:55 -08:00
Olaoluwa Osuntokun
18a5dda6a9
build: bump version to v0.17.1-beta.rc3 2023-11-08 15:00:20 -08:00
Olaoluwa Osuntokun
31791aadc8 Merge branch 'v0-17-1-branch-rc3-8158' into v0-17-1-branch-rc3 2023-11-08 14:58:41 -08:00
Eugene Siegel
8e8923c251 release-notes: update for 0.17.1 2023-11-08 14:58:41 -08:00
Eugene Siegel
f7e2db9687 peer: send messages in Start via writeMessage to bypass writeHandler
Without this the following could happen:

* InboundPeerConnected is called while we already have an inbound
connection with the peer. This calls removePeer which calls Disconnect.
* If the peer is starting up in Start, it may be sending messages
synchronously via SendMessage(true, ...). This eventually calls the
writeMessage function which will exit if disconnect is set to 1.
* Since Disconnect was called, disconnect will be 1 and writeMessage
will exit, causing writeHandler to exit.
* If there is more than 1 message being sent, later messages will
queue in queueHandler but be unable to get into sendQueue as the
writeHandler goroutine has exited.
* The synchronous sends will be waiting on the errChan indefinitely
and startReady will never get closed meaning Disconnect will never
proceed.

The end result is that the server's mutex will be held until shutdown.

Avoid this by using writeMessage to bypass the writeHandler goroutine.
2023-11-08 14:58:41 -08:00
Olaoluwa Osuntokun
0116d9bd0b
Merge pull request #8155 from Roasbeef/v0-17-1-branch-rc2
release: create v0.17.1 rc2 release branch
2023-11-07 16:25:20 -08:00
Olaoluwa Osuntokun
8ffd64b554
build: bump version to v0.17.1-beta.rc2 2023-11-06 16:10:55 -08:00
Olaoluwa Osuntokun
7dffad8e13 Merge branch 'v0-17-1-branch-rc2-8116' into v0-17-1-branch-rc2 2023-11-06 16:09:38 -08:00
Oliver Gugger
30fc8e96be GitHub: bump pinned versions in CI check 2023-11-06 16:09:38 -08:00
dependabot[bot]
cbccf61c7f build(deps): bump google.golang.org/grpc from 1.53.0 to 1.56.3
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.56.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.56.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 16:09:38 -08:00
Olaoluwa Osuntokun
710545b829
Merge pull request #8138 from Roasbeef/v0-17-1-branch-rc1
build: create v0.17.1-rc1 branch
2023-11-01 15:27:51 -07:00
Olaoluwa Osuntokun
155f66b16f Merge branch 'v0-17-1-branch-rc1-8063' into v0-17-1-branch-rc1 2023-11-01 11:17:04 -07:00
Oliver Gugger
464ddb4206 cmd/lncli: fix linter complaint by running make fmt 2023-11-01 11:17:04 -07:00
Olaoluwa Osuntokun
c8409575bb
build: bump version to v0.17.1-beta.rc1 2023-10-31 16:49:13 -07:00
Olaoluwa Osuntokun
2c2ba34537 Merge branch 'v0-17-1-branch-rc1-8132' into v0-17-1-branch-rc1 2023-10-31 16:44:35 -07:00
Olaoluwa Osuntokun
76862ed10b macaroons: reject unknown macaroon versions
We've only ever made macaroons with the v2 versions, so we should
explicitly reject those that aren't actually v2. We add a basic test
along the way, and also add a similar check for the version encoded in
the macaroon ID.
2023-10-31 16:44:35 -07:00
Olaoluwa Osuntokun
948f8732d6 Merge branch 'v0-17-1-branch-rc1-8104' into v0-17-1-branch-rc1 2023-10-31 16:44:17 -07:00
Olaoluwa Osuntokun
6c7bca2a17 docs/release-notes: add entry for nonce init fix 2023-10-31 16:44:17 -07:00
Slyghtning
9fa2057cd4 itest: simple taproot channel status 2023-10-31 16:44:17 -07:00
Slyghtning
b2a5368846 itest: assertions to check channel status 2023-10-31 16:44:17 -07:00
Eugene Siegel
280a97cbaa multi: skip InitRemoteMusigNonces if we've already called it
Prior to this commit, taproot channels had a bug:

- If a disconnect happened before peer.AddNewChannel was called,
  then the subsequent reconnect would call peer.AddNewChannel and
  attempt the ChannelReestablish dance.

- peer.AddNewChannel would call NewLightningChannel with
  populated nonce ChannelOpts. This in turn would call
  InitRemoteMusigNonces which would create a new musig pair session
  and set the channel's pendingVerificationNonce to nil.

- During the reestablish dance, ProcessChanSyncMsg would be called.
  This would also call InitRemoteMusigNonces, except it would fail
  since pendingVerificationNonce was set to nil in the previous
  invocation.

To fix this, we add a new functional option to signal to the init logic
that it doesn't need to call InitRemoteMusigNonces in   in
ProcessChanSyncMsg.
2023-10-31 16:44:17 -07:00
Olaoluwa Osuntokun
db6acec141 Merge branch 'v0-17-1-branch-rc1-8111' into v0-17-1-branch-rc1 2023-10-31 16:43:15 -07:00
Jonathan Harvey-Buschel
452af8ffa1 doc: add release notes for 8111 2023-10-31 16:43:15 -07:00
Jonathan Harvey-Buschel
6ea7d92c2e itest: add GetBlockHeader to ChainKit tests 2023-10-31 16:43:15 -07:00
Jonathan Harvey-Buschel
6a4dabc684 chainrpc+lncli: expose GetBlockHeader + add to CLI 2023-10-31 16:43:15 -07:00
Jonathan Harvey-Buschel
b04927f688 multi: add GetBlockHeader to BlockChainIO 2023-10-31 16:43:15 -07:00
Jonathan Harvey-Buschel
35bfd27467 chainrpc: update proto to expose GetBlockHeader 2023-10-31 16:43:15 -07:00
Olaoluwa Osuntokun
c0b14c7c39 Merge branch 'v0-17-0-branch-rc1-8094' into v0-17-0-branch-rc1 2023-10-31 16:24:16 -07:00
yyforyongyu
52fdf7086c gomod: update btcwallet re rescan race fix 2023-10-31 16:24:16 -07:00
Olaoluwa Osuntokun
6806a13f68 Merge branch 'v0-17-0-branch-rc1-8090' into v0-17-0-branch-rc1 2023-10-31 16:23:00 -07:00
ziggie
42dd0fa912 multi: clarify co-op closure failures. 2023-10-31 16:23:00 -07:00
Olaoluwa Osuntokun
58193ef18c Merge branch 'v0-17-0-branch-rc1-8019' into v0-17-0-branch-rc1 2023-10-31 16:22:29 -07:00
yyforyongyu
a0448eb14a gomod: update btcwallet version 2023-10-31 16:22:29 -07:00
Olaoluwa Osuntokun
5c4f2c129f Merge branch 'v0-17-0-branch-rc1-7965' into v0-17-0-branch-rc1 2023-10-31 16:21:57 -07:00
yyforyongyu
7be54096b6 itest: update related tests to reflect anchor sweeping
This commit updates all related tests to reflect the latest anchor
sweeping behavior. Previously, anchor sweeping is always attempted as
CPFP when a force close is broadcast, while now it only happens when the
deadline is less than 144. For non-CPFP purpose sweeping, it will happen
after one block is mined after the force close transaction is confirmed
as the anchor will be resent to the sweeper with a floor fee rate, hence
making it economical to sweep.
2023-10-31 16:21:57 -07:00
yyforyongyu
b8464ddd7e itest: fix testMultiHopRemoteForceCloseOnChainHtlcTimeout 2023-10-31 16:21:57 -07:00
yyforyongyu
0cb9ccd066 itest: update test testMultiHopHtlcLocalChainClaim to skip CPFP
Since we now only perform CPFP when both the fee rate is higher and the
deadline is less than 144, we need to update the test to reflect that
Bob will not CPFP the force close tx for the channle Alice->Bob.
2023-10-31 16:21:57 -07:00
yyforyongyu
2cb208e97c docs: update release notes 2023-10-31 16:21:57 -07:00
yyforyongyu
91719b0f49 contractcourt+itest: relax anchor sweeping for CPFP purpose
This commit changes from always sweeping anchor for a local force close
to only do so when there is an actual time pressure. After this change,
a forced anchor sweeping will only be attempted when the deadline is
less than 144 blocks.
2023-10-31 16:21:57 -07:00
yyforyongyu
c2148ad757 sweep: prioritize smaller inputs when adding wallet UTXOs
This commit sorts wallet UTXOs by their values when using them for
sweeping inputs. This way we'd avoid locking large UTXOs when sweeping
inputs and also provide an opportunity to aggregate wallet UTXOs.
2023-10-31 16:21:57 -07:00
yyforyongyu
dde605d375 sweeper: add more docs and debug logs 2023-10-31 16:21:57 -07:00
yyforyongyu
7ebc538c10 sweep: use longer variable name for clarity in addToState 2023-10-31 16:21:57 -07:00
Olaoluwa Osuntokun
738e0c64ec Merge branch 'v0-17-0-branch-rc1-7937' into v0-17-0-branch-rc1 2023-10-31 16:21:19 -07:00
eugene
28c260e4ea release-notes: update for 0.17.1 2023-10-31 16:21:19 -07:00
eugene
75406d177b htlcswitch/hop: use InvalidOnionVersion for replayed packets
The link will send an update_fail_malformed_htlc, so we need to set
the BADONION bit. Since there isn't a replay-specific error, we
set the failure code to InvalidOnionVersion which has the BADONION bit.
2023-10-31 16:21:19 -07:00
Olaoluwa Osuntokun
3c605dbff5 Merge branch 'v0-17-0-branch-rc1-8053' into v0-17-0-branch-rc1 2023-10-31 16:20:50 -07:00
Kilian
6521576f42 lncli: fix description of connect/disconnect peer 2023-10-31 16:20:50 -07:00
rockstardev
c54373522e Updating README 2023-10-25 13:59:06 -05:00
rockstardev
11bae66d31 Merge branch 'lnd/v0.17.0-beta' 2023-10-25 13:52:18 -05:00
rockstardev
9115aa385f Updating loop to v0.26.4-beta 2023-10-25 13:49:30 -05:00
rockstardev
e234af10a2 Updating README file 2023-10-25 13:46:50 -05:00
rockstardev
dd83fa5286 Merge branch 'lnd/v0.17.0-beta'
# Conflicts:
#	.github/workflows/main.yml
#	.github/workflows/release.yaml
#	.travis.yml
#	Dockerfile
#	cmd/lncli/cmd_open_channel.go
#	contractcourt/htlc_timeout_resolver.go
#	dev.Dockerfile
#	docs/release-notes/release-notes-0.16.0.md
#	docs/release-notes/release-notes-0.16.1.md
#	docs/release-notes/release-notes-0.16.3.md
#	funding/manager.go
#	funding/manager_test.go
#	go.mod
#	go.sum
#	itest/list_on_test.go
#	itest/lnd_channel_funding_fund_max_test.go
#	itest/lnd_funding_test.go
#	itest/lnd_multi-hop_test.go
#	itest/lnd_open_channel_test.go
#	lnrpc/lightning.pb.go
#	lnrpc/lightning.proto
#	lnrpc/lightning.swagger.json
#	lnrpc/walletrpc/walletkit_server.go
#	lntest/harness.go
#	lntest/harness_assertion.go
#	lnutils/sync_map.go
#	lnwallet/chanfunding/assembler.go
#	lnwallet/chanfunding/coin_select_test.go
#	lnwallet/chanfunding/wallet_assembler.go
#	lnwallet/wallet.go
#	make/builder.Dockerfile
#	peer/brontide.go
#	rpcserver.go
2023-10-25 13:42:10 -05:00
rockstardev
bc951d7c24 Merge branch 'lnd/v0.16.4-beta'
# Conflicts:
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2023-10-25 13:41:40 -05:00
rockstardev
39ecf64086 Merge branch 'lnd/v0.16.3-beta'
# Conflicts:
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2023-10-25 13:41:20 -05:00
rockstardev
5dd6d0a588 Merge branch 'lnd/v0.16.2-beta'
# Conflicts:
#	docker-entrypoint.sh
#	docker-initunlocklnd.sh
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2023-10-25 13:40:51 -05:00
rockstardev
38726b19ad Merge branch 'lnd/v0.16.1-beta'
# Conflicts:
#	Makefile
#	build/version.go
2023-10-25 13:39:14 -05:00
rockstardev
97629cbae2 Merge branch 'lnd/v0.16.0-beta'
# Conflicts:
#	.github/ISSUE_TEMPLATE/bug_report.md
#	aliasmgr/aliasmgr.go
#	aliasmgr/aliasmgr_test.go
#	channeldb/channel.go
#	channeldb/db.go
#	channeldb/meta.go
#	channeldb/meta_test.go
#	channeldb/migration30/iterator.go
#	channeldb/migration30/iterator_test.go
#	channeldb/migration30/lnwallet.go
#	channeldb/migration30/migration.go
#	channeldb/migration30/migration_test.go
#	channeldb/migration30/revocation_log.go
#	channeldb/migration30/test_utils.go
#	channeldb/migtest/migtest.go
#	channeldb/options.go
#	channeldb/payment_control_test.go
#	channeldb/revocation_log_test.go
#	cmd/lncli/cmd_open_channel.go
#	cmd/lncli/walletrpc_active.go
#	config.go
#	config_builder.go
#	discovery/gossiper.go
#	discovery/gossiper_test.go
#	docker-entrypoint.sh
#	docker-initunlocklnd.sh
#	docs/INSTALL.md
#	docs/release-notes/release-notes-0.15.1.md
#	docs/release-notes/release-notes-0.15.3.md
#	funding/manager.go
#	funding/manager_test.go
#	go.mod
#	go.sum
#	htlcswitch/link_test.go
#	htlcswitch/mock.go
#	htlcswitch/switch.go
#	htlcswitch/switch_test.go
#	itest/lnd_nonstd_sweep_test.go
#	itest/lnd_psbt_test.go
#	itest/lnd_remote_signer_test.go
#	itest/lnd_rpc_middleware_interceptor_test.go
#	itest/lnd_signer_test.go
#	itest/lnd_zero_conf_test.go
#	keychain/btcwallet.go
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
#	lncfg/db.go
#	lnd.go
#	lnrpc/invoicesrpc/addinvoice.go
#	lnrpc/invoicesrpc/addinvoice_test.go
#	lnrpc/invoicesrpc/invoices.swagger.json
#	lnrpc/lightning.pb.go
#	lnrpc/lightning.pb.gw.go
#	lnrpc/lightning.pb.json.go
#	lnrpc/lightning.proto
#	lnrpc/lightning.swagger.json
#	lnrpc/lightning.yaml
#	lnrpc/lightning_grpc.pb.go
#	lnrpc/neutrinorpc/neutrino_grpc.pb.go
#	lnrpc/routerrpc/router.pb.go
#	lnrpc/signrpc/signer.pb.go
#	lnrpc/signrpc/signer_grpc.pb.go
#	lnrpc/walletrpc/walletkit.pb.go
#	lnrpc/walletrpc/walletkit.pb.gw.go
#	lnrpc/walletrpc/walletkit.pb.json.go
#	lnrpc/walletrpc/walletkit.proto
#	lnrpc/walletrpc/walletkit.yaml
#	lnrpc/walletrpc/walletkit_grpc.pb.go
#	lnrpc/walletrpc/walletkit_server.go
#	lntest/harness_net.go
#	lntest/harness_node.go
#	lntest/itest/lnd_channel_backup_test.go
#	lntest/itest/lnd_multi-hop_htlc_aggregation_test.go
#	lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go
#	lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go
#	lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go
#	lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go
#	lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go
#	lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go
#	lntest/itest/lnd_multi-hop_test.go
#	lntest/itest/lnd_onchain_test.go
#	lntest/itest/lnd_recovery_test.go
#	lntest/itest/lnd_switch_test.go
#	lntest/itest/lnd_taproot_test.go
#	lntest/itest/lnd_test_list_on_test.go
#	lntest/itest/utils.go
#	lntest/mock/secretkeyring.go
#	lntest/mock/walletcontroller.go
#	lnwallet/btcwallet/btcwallet.go
#	lnwallet/chancloser/chancloser_test.go
#	lnwallet/interface.go
#	peer/brontide.go
#	peer/test_utils.go
#	routing/control_tower_test.go
#	routing/payment_lifecycle.go
#	routing/router.go
#	routing/router_test.go
#	rpcperms/interceptor.go
#	rpcserver.go
#	sample-lnd.conf
#	server.go
2023-10-25 13:37:25 -05:00
rockstardev
9786a1fa2c Adding BtcPayServer related files and resources 2023-10-25 13:22:30 -05:00
rockstardev
f1c2739118 Add watchtowerrpc to install tags
Co-authored-by: d11n <mail@dennisreimann.de>
2023-09-06 15:44:35 -05:00
rockstardev
b8570fcd9d Adding BtcPayServer related files and resources 2023-07-07 10:32:11 -05:00
Olaoluwa Osuntokun
6bd30047c1
build: bump version to v0.16.4
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-07-04 12:56:21 -07:00
rockstardev
3c60fc0857 Adding BtcPayServer related files and resources 2023-06-26 11:32:03 -05:00
Olaoluwa Osuntokun
3bf179a888
build: bump version to v0.16.4 rc1
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-06-22 11:29:27 -05:00
Olaoluwa Osuntokun
8dcd8529a2 Merge branch 'v0-16-4-branch-7767' into v0-16-4-branch 2023-06-22 11:28:32 -05:00
yyforyongyu
dea815dac2 mod: update btcwallet version 2023-06-22 11:27:53 -05:00
Olaoluwa Osuntokun
47483f1c66
build: bump version to v0.16.3
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-06-05 11:51:04 -07:00
Olaoluwa Osuntokun
f76e52e60a
Merge pull request #7724 from Roasbeef/v0-16-3-branch
build: create v0.16.3 release branch
2023-05-29 12:51:56 -07:00
Olaoluwa Osuntokun
29f9fe5c1a
build: bump version to v0.16.3-beta.rc1
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-05-29 12:50:34 -07:00
Olaoluwa Osuntokun
96435425e9 Merge branch 'v0-16-3-branch-7726' into v0-16-3-branch 2023-05-29 12:50:05 -07:00
Olaoluwa Osuntokun
96a24e035c docs/release-notes: add release notes for adamant htlc sweeps 2023-05-29 12:50:05 -07:00
Olaoluwa Osuntokun
1ba6467c6b contractcourt: force the sweeper to always resolve outgoing HTLCs
In this commit, we attempt to fix an issue that may lead to force closes due
to small value HTLCs. The sweeper has built in a "negative yield" heuristic
where it won't sweep something that'll result in paying more fees than the
HTLC amount. However for HTLCs, we want to always sweep them, as we don't
cancel back the HTLCs before the outgoing contract is fully resolved.

In the future, we'll start to make more uneconomical decisions about if we
should go to chain at all for small value HTLCs, and also do things like
cancel back early if the HTLC is small and we think we might be contested by
chain fees.
2023-05-29 12:50:05 -07:00
Olaoluwa Osuntokun
9b4fce1468 Merge branch 'v0-16-3-branch-7711' into v0-16-3-branch 2023-05-23 14:23:15 -07:00
Olaoluwa Osuntokun
ddf551f16d htlcswitch: add new LinkFailureDisconnect action
In this commit, we add a new LinkFailureDisconnect action that'll be
used if we detect that the remote party hasn't sent a revoke and ack
when it actually should.

Before this commit, we would log our action, tear down the link, but
then not actually force a connection recycle, as we assumed that if the
TCP connection was actually stale, then the read/write timeout would
expire.

In practice this doesn't always seem to be the case, so we make a strong
action here to actually force a disconnection in hopes that either side
will reconnect and keep the good times rollin' 🕺.
2023-05-23 14:23:05 -07:00
Olaoluwa Osuntokun
5d20d088e9 htlcswitch: add new LinkFailureAction enum
In this commit, we add a new LinkFailureAction enum to take over the old
force close bool. Force closing isn't the only thing we might want to do
when we decide to fail the link, so this is a prep refactoring for an
upcoming change.
2023-05-23 14:22:39 -07:00
Olaoluwa Osuntokun
fcbe6844c0 Merge branch 'v0-16-3-branch-7705' into v0-16-3-branch 2023-05-22 18:13:39 -07:00
Elle Mouton
bd43defefd docs: add release note for 7705 2023-05-22 18:13:26 -07:00
Elle Mouton
9b98352caf macaroons: let ChangePassword re-encrypt all root keys
The ChangePasswords method should re-encrypt all the root keys found
in the store, not just the default root key.
2023-05-22 18:12:19 -07:00
Elle Mouton
143fc4ced4 macaroons: demo ChangePassword bug
This commits uses TestStoreChangePassword to demonstrate that currently
the ChangePassword function only changes the password of the default
root key and not that of other root keys. This will be fixed in an
upcoming commit.
2023-05-22 18:12:19 -07:00
Elle Mouton
51f0082c53 macaroons: Let GenerateNewRootKey be applied to all root keys
With this commit, GenerateNewRootKey will regenerate the Default root
key and will then also check if any other root keys exist and regenerate
those as well.
2023-05-22 18:12:19 -07:00
Elle Mouton
ee01956978 macaroons: demo GenerateNewRootKey bug
This commit adds to the existing TestStoreGenerateNewRootKey to show
that the method only successfully regenerates the root key in the
default root key ID location. This will be fixed in an upcoming commit.
2023-05-22 18:12:19 -07:00
Olaoluwa Osuntokun
b26be81c7a Merge branch 'v0-16-3-branch-7681' into v0-16-3-branch 2023-05-22 18:11:34 -07:00
yyforyongyu
4d0136af8c docs: add release notes 0.16.3 2023-05-22 18:11:26 -07:00
yyforyongyu
caabfb7eb4 itest: cleanup channels for testSwitchOfflineDeliveryOutgoingOffline 2023-05-22 18:11:26 -07:00
yyforyongyu
43b774d1e6 itest: make sure edges are updated in mpp tests 2023-05-22 18:11:26 -07:00
yyforyongyu
1ce7559110 lntest+itest: clean mempool in testHtlcTimeoutResolverExtractPreimageRemote 2023-05-22 18:11:26 -07:00
yyforyongyu
5e1664dc82 mod: update btcwallet's version 2023-05-22 18:11:24 -07:00
rockstardev
15d920456a Accepting signet as LND_ENVIRONMENT variable 2023-05-07 22:41:53 -05:00
rockstardev
cd70936a77 Adding BtcPayServer related files and resources 2023-04-29 08:39:47 -05:00
Olaoluwa Osuntokun
fdbeb1e702 Merge branch 'v0-16-2-branch-7647' into v0-16-2-branch
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-04-28 14:03:30 -05:00
yyforyongyu
6cf1b086a9 contractcourt: skip checkpoint timeout resolver upon mempool spend
Previously when a block spend is found for the outpoint, our htlc
timeout resolver will do a checkpoint, which implicitly creates a db
record if there isn't one. Now, if the spend is found in mempool,
the resolver will be deleted once the contract is resolved. Later on
when the spend is found in the block again, the resolver will be created
again, but never gets resolved this time.
2023-04-28 14:03:30 -05:00
yyforyongyu
12f3cd5bb1 contractcourt: add debug logs for unresolved contracts 2023-04-28 14:03:30 -05:00
Olaoluwa Osuntokun
63f01c1ebd
build: bump version to v0.16.2 2023-04-27 16:37:27 -05:00
Olaoluwa Osuntokun
5b00c4fc93 Merge branch 'v0-16-2-branch-7641' into v0-16-2-branch 2023-04-27 16:36:51 -05:00
Olaoluwa Osuntokun
a6345797ae build: update to btcwallet version with async mempool scan
This version of btcwallet demotes some spammy logs (txns replaced in the
mempool), and makes the initial mempool scan async.

Fixes https://github.com/lightningnetwork/lnd/issues/7640
2023-04-27 16:36:51 -05:00
Olaoluwa Osuntokun
f7129c1d62 Merge branch 'v0-16-2-branch-7637' into v0-16-2-branch 2023-04-27 16:35:23 -05:00
yyforyongyu
0d1c5f85fc lnd: skip canceling rebroadcast for neutrino backend 2023-04-27 16:35:23 -05:00
rockstardev
2f4b515afc Adding BtcPayServer related files and resources 2023-04-26 14:34:42 -05:00
Olaoluwa Osuntokun
fb765fdb1d
build: bump version to v0.16.1-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-04-24 13:10:16 -05:00
Olaoluwa Osuntokun
a82192efb7
build: bump version to v0.16.1-beta.rc3
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-04-21 15:55:42 -07:00
Olaoluwa Osuntokun
508b0a4426 lnd v0.16.0-beta
-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE9Pxw8HMQAoQk78IKjkJWWT8XdyAFAmQkNkYACgkQjkJWWT8X
 dyC5fRAAvhiI4TTDqxdJmTcj1nxA6iUYB4nAqL4wegnXSv9ntcaQ5c10vGLiBi9Y
 D/Uqqfnz73OaATRcDjaeZdONTFd4q7mM21ymrAqbfv8OpjeccO5fOrtsAPQKMNK3
 3ipT7Ej+KgF5QatAUlm8joqBJ4SXB9y6AmPqRbdNyBu4yf3AJf69EOjTG2dW+E3x
 XPQfeMw5cBSSM6VKIdTY3cQvzX5jUU3lBtahSL4wChPzh4bYZTnn6hydkSkkmqjp
 SyYD6KYZ4Ul4Mh+evlWzqDwfJHfNL82ZwHxJ1bfrVJQ34ZQanlH014/baRYNR1in
 eALSUf/YRkf65HNETF8g4oeiUFc2ymx4zY3dZMeNZ9Rij0KE6OJVg3ZS/5zUITkJ
 1TWpO92nPe9v6f9SkZA6YotHwUg7GX+II7frs+8d0RGbEipc2JjN2p8DewuszDGi
 QT5iYk+PQcoQVYJM79GmoZAa7DgZASodJGz2Huml6J7cjMXq+3bJ4JCo9L0SMu0B
 mSESi+3Y9Sy4Ujpq3ryqbsehTq/nWQq5nFuA3miLsqEfLy5sunOct0/RhyWtGnFu
 2YEVQPI0cmAFV5v8QsLKtOXj8QSpSsZK7w+G1nbukpa0HhkUZxk3WQxbcbYctIkW
 5D133P3E7yNQm7Nr3JYkwN0foDdWUvAdkQQSVtSBlpZw6kyGnuQ=
 =BNTa
 -----END PGP SIGNATURE-----

Merge tag 'v0.16.0-beta' into v0-16-1-branch-rc3

lnd v0.16.0-beta
2023-04-21 15:52:34 -07:00
Olaoluwa Osuntokun
c2851c2342 Merge branch 'v0-16-1-branch-rc1-7599' into v0-16-1-branch-rc2
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-04-21 14:02:01 -07:00
Olaoluwa Osuntokun
fc3b8bff69 sweep: remove conflicted sweep txns from the rebroadcaster
In this commit, we an existing gap in our rebroadcast handling logic. As
is, if we're trying to sweep a transaction and a conflicting transaction
is mined (timeout lands on chain, anchor swept), then we'll continue to
try to rebroadcast the tx in the background.

To resolve this, we give the sweeper a new closure function that it can
use to mark conflicted transactions as no longer requiring rebroadcast.
2023-04-21 14:01:48 -07:00
Olaoluwa Osuntokun
31b27fdd3d
build: bump version to v0.16.1-beta.rc2 2023-04-20 11:35:29 -07:00
Olaoluwa Osuntokun
4c10599ae0 build: bump version to v0.16.1-beta.rc2 2023-04-19 20:59:46 -07:00
Olaoluwa Osuntokun
8c1f9a8e5a Merge branch 'v0-16-1-branch-rc1-7609' into v0-16-1-branch-rc1
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2023-04-19 11:44:32 -07:00
Olaoluwa Osuntokun
c96fe0ec58 chainreg: increase default CLTV value to 80 blocks (~13 hrs)
In this commit, we increase the default CTLV value to 80 blocks.
Initially this was set to 144 blocks in the early days, but then was
lowered to 40 blocks as the lnd implementation matured. By setting this
to a higher value, we increase the safety window (MTTR) when it comes to
node downtime, and also add some buffer room around time locks which may
become more stressed in the future assuming the current mempool load
remains persistent.
2023-04-19 11:43:04 -07:00
Olaoluwa Osuntokun
e808e913ec
Merge pull request #7611 from Roasbeef/v0-16-1-branch-rc1
release: create v0.16.1-beta.rc1 branch
2023-04-19 11:37:05 -07:00
Olaoluwa Osuntokun
a4e815c05c
docs/release-notes: move docs for postgres kvdb 2023-04-19 11:31:28 -07:00
Olaoluwa Osuntokun
334f005ba1 Merge branch 'v0-16-1-branch-rc1-7613' into v0-16-1-branch-rc1 2023-04-19 11:29:49 -07:00
Elle Mouton
11f1735e85 funding: use default fwding policy if persisted values not found
In this commit, a bug is fixed in the funding manager that could result
in the funding process erroring out if the persisted initial forwarding
policy is not found. This could occur if a node restarts after opening a
channel that is not yet fully confirmed and also upgrades their node
from a pre-0.16 version to 0.16 since the values are only expected to be
persisted after 0.16.
2023-04-19 11:29:49 -07:00
yyforyongyu
b90b66ea80 chainreg: update bitcoind polling config 2023-04-18 18:29:27 -07:00
yyforyongyu
e207424da8 docs: update release notes for mempool watch 2023-04-18 18:29:20 -07:00
yyforyongyu
7149b12cd9 itest+lntest: add itest for mempool preimage watch 2023-04-18 18:28:28 -07:00
yyforyongyu
946b4f0184 lntest: add more methods to assert mempool state 2023-04-18 18:28:28 -07:00
yyforyongyu
c15a38407f lnd+contractcourt: add more debug logs
This commit adds more debug logs for witness beacon and channel
arbitrator.
2023-04-18 18:28:28 -07:00
yyforyongyu
f9b1250ecf chainntnfs: remove subscriptions when the relevant tx is confirmed
This commit removes the subscribed inputs from mempool notifier when the
relevant transaction is confirmed.
2023-04-18 18:28:28 -07:00
yyforyongyu
1fa269425e contractcourt+lnd: watch for preimage reveal in mempool
This commit extends the current htlc timeout resolver to also watch for
preimage spend in mempool for a full node backend.

If mempool enabled, the resolver will watch the spend of the htlc output
in mempool and blocks **concurrently**, as if they are independent.

Ideally, a transaction will first appear in mempool then in a block.
However, there's no guarantee it will appear in **our** mempool since
there's no global mempool, thus we need to watch the spend in two places
in case it doesn't go through our mempool.

The current design favors the spend event found in blocks, that is, when
the tx is confirmed, we'd abort the monitoring and conitnue since the
outpoint cannot be double spent and re-appear in mempool again. This is
not true in the rare case of reorg, and we will handle reorg seperately.
2023-04-18 18:28:28 -07:00
yyforyongyu
2fac0af553 contractcourt: refactor spendHtlcOutput for clarity
Also fixes the docs and rename `isSuccessSpend` to `isPreimageSpend`.
2023-04-18 18:28:28 -07:00
yyforyongyu
b765c44539 chainntnfs+chainreg: add interface MempoolWatcher
This commit adds the interface `MempoolWatcher` and uses it in the chain
registry.
2023-04-18 18:28:28 -07:00
yyforyongyu
0e1aaad6d4 chainntnfs+chainreg: add mempool watcher to BtcdNotifier
This commit adds the mempool watcher to btcd notifier to allow the
notifier managing the starting and stopping of the watcher.
2023-04-18 18:28:28 -07:00
yyforyongyu
bf839461b4 chainntnfs+chainreg: add mempool watcher to BitcoindNotifier
This commit adds the mempool watcher to bitcoind notifier to allow the
notifier managing the starting and stopping of the watcher.
2023-04-18 18:28:28 -07:00
yyforyongyu
76ba68091f chainntnfs: patch unit tests for mempool notifier 2023-04-18 18:28:28 -07:00
yyforyongyu
35d1bff321 chainntnfs: add method UnsubscribeEvent to cancel a subscription
This commit adds the method `UnsubscribeEvent` to cancel a single
subscription.
2023-04-18 18:28:27 -07:00
yyforyongyu
318efa4c33 chainntnfs: allow multiple subscriber to the same input
This commit changes the `subscribedInputs` to store a map of subscribers
so multiple subscribers are allowed to receive events from the same
outpoint.
2023-04-18 18:28:27 -07:00
yyforyongyu
208628d7f2 chainntnfs: introduce mempool notifier
This commit adds a mempool notifier which notifies the subscriber the
spending event found in the mempool for a given input.
2023-04-18 18:28:27 -07:00
Olaoluwa Osuntokun
28ab3d5ccb Merge branch 'v0-16-1-branch-rc1-7597' into v0-16-1-branch-rc1 2023-04-18 18:27:36 -07:00
Oliver Gugger
a53b0a483c docs: add release notes 2023-04-18 18:27:36 -07:00
Oliver Gugger
24e1a0ec7d peer: add TODO about initial forwarding policy
The right way to solve the problem of the link not being up to date with
custom user set forwarding policies once the channel is announced would
be to pass in those custom values when the link is created initially.
This requires a bit more of a refactor and is not addressed in this bug
fix.
2023-04-18 18:27:36 -07:00
Oliver Gugger
3c4ba857cc itest: update channel open test to send payment
This commit enhances the custom fee policy channel open test by adding a
second channel and testing forwarding payments through the channel with
the custom forwarding policies.
This was able to reproduce the bug reported in #5796 which was fixed in
a previous commit of this PR.
2023-04-18 18:27:36 -07:00
Oliver Gugger
4cf9d7c982 itest: move lnd_custom_{message => message_test}.go
This recently added file didn't follow the golang naming convention for
tests.
2023-04-18 18:27:36 -07:00
Oliver Gugger
a74793ecbc funding+server: update switch after sending channel update
With this commit we give the funding manager the ability to inform the
switch about custom channel policies, right after we've announced the
channel to the network.
This change is necessary because before #6753 a channel could only be
opened with the default forwarding policies, so the switch automatically
had the "correct" default values. Since #6753 added the ability to
specify forwarding policies at channel open time, we announced those
policies to the network but never updated the switch to inform it about
the changed policies (previously changing the policies was only possible
through the UpdateChannelPolicy RPC which did call the switch).
2023-04-18 18:27:36 -07:00
Oliver Gugger
16f428f580 funding: refactor manager test 2023-04-18 18:27:36 -07:00
Olaoluwa Osuntokun
a49671d076 Merge branch 'v0-16-1-branch-rc1-7604' into v0-16-1-branch-rc1 2023-04-18 18:27:05 -07:00
ziggie
261461deeb docs: update release notes 2023-04-18 18:27:05 -07:00
ziggie
7ab6eb1140 netann: fix logging output 2023-04-18 18:27:05 -07:00
Olaoluwa Osuntokun
70bad093a9 Merge branch 'v0-16-1-branch-rc1-7603' into v0-16-1-branch-rc1 2023-04-18 18:26:44 -07:00
Torakushi
4e402082b3 update release-notes-0.16.1 2023-04-18 18:26:44 -07:00
Torakushi
02be618935 funding: use p2tr by default for batch_open_channel
In LND v0.15.1, batch_open_channel used p2tr by default
for change output. However, in a later version, a breaking
change has been fixed in FundPSBT to make the change type
configurable (default to p2wkh). As batch_open_channel
uses FundPsbt, we need to put back p2tr as default for
change output
2023-04-18 18:26:44 -07:00
Olaoluwa Osuntokun
239fda1894 Merge branch 'v0-16-1-branch-rc1-7473' into v0-16-1-branch-rc1 2023-04-18 18:24:42 -07:00
Emilio Ziniades
32b117b9df lnrpc: test witness type mapping 2023-04-18 18:24:42 -07:00
Emilio Ziniades
43660c2c31 input: note to update witness type protobuf 2023-04-18 18:24:42 -07:00
Emilio Ziniades
aca89c38aa lnrpc: add allWitnessTypes map
Refactor `PendingSweeps` to use `allWitnessTypes` map, and
return an error from `PendingSweeps` if an unknown witness
type is used, instead of logging a warning.
2023-04-18 18:24:42 -07:00
Emilio Ziniades
44dcfec947 lnrpc: update and regenerate witness type proto 2023-04-18 18:24:42 -07:00
Olaoluwa Osuntokun
cf88d105f3 Merge branch 'v0-16-1-branch-rc1-7464' into v0-16-1-branch-rc1 2023-04-18 18:24:01 -07:00
Oliver Gugger
91448274fa docs: add release notes 2023-04-18 18:24:01 -07:00
Oliver Gugger
2509000878 channeldb: use input.GenMultiSigScript 2023-04-18 18:24:01 -07:00
Oliver Gugger
7401de3348 input: set initial script allocation size
The default allocation of 500 bytes for the script that is
used in NewScriptBuilder is way too much for most of our scripts.
With the new functional option we can tune the allocation to exactly
what we need.
2023-04-18 18:24:01 -07:00
Oliver Gugger
020d79f18e input: add script size unit and benchmark tests 2023-04-18 18:24:01 -07:00
Oliver Gugger
3a4ab10806 mod: bump btcd version 2023-04-18 18:24:01 -07:00
Olaoluwa Osuntokun
6c8932a4e1 Merge branch 'v0-16-1-branch-rc1-7593' into v0-16-1-branch-rc1 2023-04-18 18:23:25 -07:00
Oliver Gugger
a7815b29f5 docs: update remote signing docs
With this commit we update the docs according to the latest changes that
were necessary to support loop and pool (which requires all 255
internally used accounts to be imported at wallet creation time).

Fixes #7567.
2023-04-18 18:23:25 -07:00
Olaoluwa Osuntokun
b129e10da3 Merge branch 'v0-16-1-branch-rc1-7588' into v0-16-1-branch-rc1 2023-04-18 18:23:03 -07:00
Olaoluwa Osuntokun
d5be710b95 config: fix bug in walletrpc interaction due to mismatched coin type
In this commit, we fix a bug that would cause the walletrpc on the
simnet chain to not be able to respond to all RPC calls. The issue is
that for the SimNet backend, within chainparams.go:
6e0a67d05b/chainreg/chainparams.go (L45-L51),
we set a new CoinType for Simnet in order to match the RegTest value.

Later on, when we go to verify the on disk accounts against the
in-memory cointype, we fall through to an error case as the in-memory
cointype is 115, while the on disk cointype is 1.

To fix this, when we know we're doing simnet mode, we'll override the
cointype similar to the way we did/do for LTC.

Fixes https://github.com/lightningnetwork/lnd/issues/6807.
2023-04-18 18:23:03 -07:00
Olaoluwa Osuntokun
350f4293c7 Merge branch 'v0-16-1-branch-rc1-7513' into v0-16-1-branch-rc1 2023-04-18 18:22:32 -07:00
Oliver Gugger
c95205a94f docs: add release notes 2023-04-18 18:22:32 -07:00
Olaoluwa Osuntokun
2ded805858 Merge branch 'v0-16-1-branch-rc1-7563' into v0-16-1-branch-rc1 2023-04-18 18:21:49 -07:00
yyforyongyu
0b8ac4870d lnutils: add unit test for SyncMap 2023-04-18 18:21:49 -07:00
yyforyongyu
3d167b2687 lnutils: add methods ForEach, Len and LoadOrStore to SyncMap 2023-04-18 18:21:49 -07:00
Olaoluwa Osuntokun
86fb0d7b51 Merge branch 'v0-16-1-branch-rc1-7442' into v0-16-1-branch-rc1 2023-04-18 18:21:24 -07:00
84adam
2115e338ca docs: add notes on contents of Postgres DB as Key-Value store to Postgres.md 2023-04-18 18:21:24 -07:00
Olaoluwa Osuntokun
eba78e6786 Merge branch 'v0-16-1-branch-rc1-7582' into v0-16-1-branch-rc1 2023-04-18 18:20:58 -07:00
Olaoluwa Osuntokun
39cc227d0d build: update build system to Go 1.20.3 2023-04-18 18:20:58 -07:00
Olaoluwa Osuntokun
36b7dc6c17 Merge branch 'v0-16-1-branch-rc1-6903' into v0-16-1-branch-rc1 2023-04-18 18:19:16 -07:00
Slyghtning
326c4f2c55 docs: update release notes 2023-04-18 18:19:16 -07:00
Slyghtning
a1cd4eafbd funding unit: fundmax sanity check for new channel commitment types. 2023-04-18 18:19:16 -07:00
Slyghtning
c5f48e6079 itest: respect the reserved wallet balance when using fundmax 2023-04-18 18:19:16 -07:00
Bjarne Magnussen
ac7a391732 chanfunding: allow to set a reserved amount not used for funding 2023-04-18 18:19:16 -07:00
Bjarne Magnussen
5c3b1724ab lntest/itest: adds tests for fundmax flag of cli:openchannel 2023-04-18 18:19:15 -07:00
Slyghtning
c1a9d15a82 lncli: fundmax flag for openchannel 2023-04-18 18:19:15 -07:00
Slyghtning
238ef0d2eb lnd+lnwallet: fundmax flag for openchannel 2023-04-18 18:19:15 -07:00
Bjarne Magnussen
26b23e2af0 lnd: handles the FundMax field inside parseOpenChannelReq
Adds handling of the `FundMax` field when parsing an
`OpenChannelRequest` with `rpcServer.parseOpenChannelReq`.
2023-04-18 18:19:15 -07:00
Bjarne Magnussen
444bbfa9f7 lnrpc: adds a field FundMax to OpenChannelRequest 2023-04-18 18:19:15 -07:00
Bjarne Magnussen
d65789950c chanfunding: adds ability to fund up to some maximum amount
Allows to define a maximum amount to provision a channel
opening with using a new field `FundUpToMaxAmt` on the
`Request` struct. Also adds a new coin select function
`CoinSelectUpToAmount` to select coins up to a maximum
amount respecting a minimum amount.
2023-04-18 18:19:15 -07:00
rockstardev
c855d83a4b Updating to bullseye for arm 2023-04-13 00:14:07 -05:00
rockstardev
90231dd41c New golang only available with buster docker images 2023-04-12 23:24:40 -05:00
rockstardev
1b4bbca8ad Updating loop to 0.22 2023-04-12 23:13:20 -05:00
rockstardev
21703127a4 Updating builder docker images for new golang version 2023-04-12 23:13:08 -05:00
rockstardev
4c434438e3 Adding BtcPayServer related files and resources 2023-04-12 22:56:21 -05:00
d11n
3f80670831
Merge pull request #6 from sgiammy/feature/signet-support-entrypoint
accept 'signet' as LND_ENVIRONMENT variable
2022-11-07 14:49:39 +01:00
rockstardev
1c4bd230e1
Cleaning up README, adding new version 2022-11-04 10:48:01 -05:00
rockstardev
f52aff64f7
Merge branch 'version/0.15.4-beta-loop-0.20.2' 2022-11-04 10:36:33 -05:00
rockstardev
3f25db755c
Merge branch 'version/0.15.4-beta' 2022-11-04 10:09:39 -05:00
rockstardev
8d7079d997
Adding BtcPayServer related files and resources 2022-11-04 10:53:46 +01:00
rockstardev
9c2807eba4
Adding BtcPayServer related files and resources 2022-11-01 21:54:18 +09:00
Oliver Gugger
96fe51e2e5
Merge pull request #7098 from lightningnetwork/btcd-bump-23-3
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
mod+build: bump btcd version to v0.23.3 and bump lnd version to v0.15.4-beta
2022-11-01 13:44:01 +01:00
Oliver Gugger
c8a3fbe265
funding: fix linter error 2022-11-01 13:34:01 +01:00
Oliver Gugger
64f20b6b5b
build: bump version to v0.15.4-beta 2022-11-01 13:20:04 +01:00
Oliver Gugger
77cd2bf5e4
docs: add release notes for 0.15.4-beta 2022-11-01 13:19:40 +01:00
Oliver Gugger
d65833fca4
mod: bump btcd to v0.23.3 2022-11-01 13:18:15 +01:00
Olaoluwa Osuntokun
b4e7131bdb
build: bump version to v0.15.3-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-10-17 10:52:17 -07:00
Olaoluwa Osuntokun
f674960e4e
Merge pull request #7017 from Roasbeef/v0-15-3-branch
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
release: create release branch for v0.15.3
2022-10-14 15:29:50 -04:00
Olaoluwa Osuntokun
34cd2f5d7c
build: bump version to v0.15.3-beta.rc1 2022-10-14 15:28:48 -04:00
Oliver Gugger
4c6f9eca5a docs: update remote signing update hint to v0.15.3-beta [skip ci]
This commit bumps the recommended version to upgrade to for remote
signing setups.
2022-10-13 12:57:35 -04:00
eugene
69b7d9666d funding: ignore maxWaitNumBlocksFundingConf for zero conf channels
This is so that if the funding transaction hasn't been confirmed
in 2016 blocks, the channel isn't marked as closed by the responder.
2022-10-13 12:57:35 -04:00
rockstardev
77dbf5d22e
Cleaning up README, adding 0.15.2-beta version 2022-10-12 15:47:39 -05:00
rockstardev
0a6f48ae0b
Merge branch 'version/0.15.2-beta' 2022-10-12 15:30:10 -05:00
rockstardev
cd045c0c65
Cleaning up README, adding new version 2022-10-12 15:14:32 -05:00
rockstardev
700c66ea86
Merge branch 'version/0.15.0-beta'
# Conflicts:
#	.circleci/config.yml
#	Makefile
#	build/version.go
#	chainreg/no_chain_backend.go
#	channeldb/graph_test.go
#	config_builder.go
#	contractcourt/briefcase.go
#	discovery/gossiper.go
#	docs/INSTALL.md
#	docs/release-notes/release-notes-0.14.2.md
#	go.mod
#	go.sum
#	htlcswitch/decayedlog_test.go
#	lnrpc/lightning.pb.go
#	lnrpc/lightning.proto
#	lnrpc/lightning.swagger.json
#	lnrpc/routerrpc/router.pb.go
#	lnrpc/rpc_utils.go
#	lnrpc/signrpc/signer_server.go
#	lnrpc/walletrpc/walletkit.pb.go
#	lnrpc/walletrpc/walletkit_server.go
#	lntest/harness_net.go
#	lntest/harness_node.go
#	lntest/itest/lnd_channel_force_close_test.go
#	lntest/itest/lnd_channel_policy_test.go
#	lntest/itest/lnd_open_channel_test.go
#	lntest/itest/lnd_psbt_test.go
#	lntest/itest/lnd_remote_signer_test.go
#	lnwallet/btcwallet/btcwallet.go
#	lnwallet/btcwallet/psbt.go
#	lnwallet/btcwallet/psbt_test.go
#	lnwallet/btcwallet/signer.go
#	lnwallet/btcwallet/signer_test.go
#	lnwallet/chainfee/estimator_test.go
#	lnwallet/interface.go
#	lnwallet/rpcwallet/healthcheck.go
#	lnwallet/rpcwallet/rpcwallet.go
#	log.go
#	macaroons/constraints.go
#	routing/missioncontrol_state_test.go
#	rpcserver.go
#	tools.go
2022-10-12 15:13:06 -05:00
Olaoluwa Osuntokun
004e2a1066 docs/release-notes: fix release notes for zero conf safety fix 2022-10-10 19:13:22 -07:00
Olaoluwa Osuntokun
110d29438a Merge branch 'v0-15-3-branch-6957' into v0-15-3-branch 2022-10-10 19:12:45 -07:00
Olaoluwa Osuntokun
8c6bc4d9b2 lnwallet/chancloser: fix loop variable shadowing in TestMaxFeeBailOut 2022-10-10 19:12:34 -07:00
Olaoluwa Osuntokun
1b95bfe171 lnwallet/chancloser: properly compute initial fee of cop close txn
In this commit, we modify the way we compute the starting ideal fee for
the co-op close transaction. Before thsi commit, channel.CalcFee was
used, which'll compute the fee based on the commitment transaction
itself, rathern than the co-op close transaction. As the co-op close
transaction is potentailly bigger (two P2TR outputs) than the commitment
transaction, this can cause us to under estimate the fee, which can
result in the fee rate being too low to propagate.

To remedy this, we now compute a fee estimate from scratch, based on the
delivery fees of the two parties.

We also add a bug fix in the chancloser unit tests that wasn't caught
due to loop variable shadowing.

The wallet import itest has been updated as well, since we'll now pay
600 extra saothis to close the channel, since we're accounting for the
added weight of the P2TR outputs.

Fixes #6953
2022-10-10 19:12:32 -07:00
Olaoluwa Osuntokun
2fe1da8109 Merge branch 'v0-15-3-branch-6966' into v0-15-3-branch 2022-10-10 19:10:01 -07:00
Oliver Gugger
a18a559a4b docs: add release notes [skip ci] 2022-10-10 19:09:50 -07:00
Oliver Gugger
27b60143cb docs: describe remote signing upgrade process
This commit adds a short guide that explains how a remote signing node
setup should be migrated from lnd v0.14.x-beta to lnd v0.15.x-beta and
adds a note to all 0.15.x release notes.
2022-10-10 19:08:49 -07:00
Oliver Gugger
cfe30ed674 cmd/lncli: add p2tr address type to account import 2022-10-10 19:07:52 -07:00
Olaoluwa Osuntokun
2ec4e5bdbd Merge branch 'v0-15-3-branch-6914' into v0-15-3-branch 2022-10-10 19:07:15 -07:00
positiveblue
714210492e docs: add release notes for hop hint selection refactor 2022-10-10 19:06:24 -07:00
positiveblue
4d0cff73ea aliasmgr: cache peer alias in memory 2022-10-10 19:05:40 -07:00
positiveblue
102d4f8d48 invoicesrpc: unit tests for invoice hop hints 2022-10-10 19:05:40 -07:00
positiveblue
9b40f5dbfd invoicesrpc: refactor addinvocie hop hint selection
In order to reduce the number of calls to the db we try to process as
few channels as we can + try to not do extra work for each of them.

- First fetch all the channels. Then, filter all the public ones and
  sort the potential candidates by remote balance.

- Filter out each potential candidate as soon as possible.

- Only check the alias if the channel supports scid aliases.

- Because we sort the channels by remote balance, we will hit the
  target amount, if possible, as soon as we can.

We do not want to leak information about our remote balances, so we
shuffle the hop hints (the forced ones go always first) so the invoice
receiver does not know which channels have more balance than others.
2022-10-10 19:05:39 -07:00
positiveblue
55b7bc6a42 style: format invoicesrpc/addinvoice.go 2022-10-10 19:04:37 -07:00
Olaoluwa Osuntokun
dce4f282ac Merge branch 'v0-15-3-branch-6941' into v0-15-3-branch 2022-10-10 19:03:26 -07:00
Olaoluwa Osuntokun
48c167b860 build: update to latest version of btcwallet w/ taproot estimation fix
Fixes https://github.com/lightningnetwork/lnd/issues/6873
2022-10-10 19:02:02 -07:00
Olaoluwa Osuntokun
f10eff4495 Merge branch 'v0-15-3-branch-6892' into v0-15-3-branch 2022-10-10 18:59:00 -07:00
eugene
33ecc9d177 release-notes: update for 0.15.2 2022-10-10 18:58:45 -07:00
eugene
3897f595a5 server.go: add peerChan to peerConnectedListeners in NotifyWhenOnline
This fixes a bug where a caller would:
- call NotifyWhenOnline and pass in a channel
- the server's mutex is held and the pubStr is checked in peersByPub
- the peer object is in the peersByPub map
- the peer object has its quit channel closed
- QuitSignal is called in the select statement, and the function
  returns
- the caller is still waiting for the channel to be sent on forever
  since it was never sent on or added to the peerConnectedListeners
  slice.

This patch fixes the above bug by adding the channel to the
peerConnectedListeners slice if the QuitSignal select case is called.
2022-10-10 18:57:55 -07:00
Olaoluwa Osuntokun
80a7ff8963 Merge branch 'v0-15-3-branch-6926' into v0-15-3-branch 2022-10-10 18:56:19 -07:00
Oliver Gugger
7a859109d2 docs: add release notes 2022-10-10 18:56:07 -07:00
Oliver Gugger
b344d9fd69 lnrpc: add additional REST binding for QueryRoutes
Lists with non-primitive members aren't supported in the query string of
a GET request with the current version of the grpc-gateway library. To
allow route_hints to be set through REST, we also offer a POST endpoint
for that call where the encoding of the request parameter can be
specified as JSON.
2022-10-10 18:54:48 -07:00
Olaoluwa Osuntokun
dd7566dab5 Merge branch 'v0-15-3-branch-6899' into v0-15-3-branch 2022-10-10 18:53:49 -07:00
Evan Kaloudis
d71639220c lnrpc/gen_protos.sh: remove js build tag 2022-10-10 18:53:48 -07:00
rockstardev
a5d3f08cca
Removing experimental features, no longer needed 2022-10-10 16:36:09 +09:00
rockstardev
276ce611e6
Updating circleci image for multiarch task
Previous one got depricated
https://circleci.com/blog/ubuntu-14-16-image-deprecation/
2022-10-10 16:36:09 +09:00
rockstardev
09386f1433
Adding BtcPayServer related files and resources 2022-10-10 16:36:09 +09:00
Olaoluwa Osuntokun
08a957ff45
Merge pull request #7005 from Roasbeef/v0-15-2-branch
release: create v0.15.2 hot fix branch to fix wire parsing issue
2022-10-09 19:34:33 -07:00
Olaoluwa Osuntokun
aff2ed3a6a
build: bump version to v0.15.2
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-10-09 18:45:32 -07:00
Olaoluwa Osuntokun
d65d3dd0cd
docs/release-notes: shift prior 0.15.2 release to 0.15.3
We also add an entry for the _new_ 0.15.2 hot fix release.
2022-10-09 18:44:58 -07:00
Olaoluwa Osuntokun
a502c386cd
build: update to version of btcd with wire parsing bug fix
Fixes https://github.com/lightningnetwork/lnd/issues/7002
2022-10-09 18:43:48 -07:00
Olaoluwa Osuntokun
fd1a95bf32
build: bump version to v0.15.1-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-08-30 13:17:47 -07:00
Olaoluwa Osuntokun
e5e20a71be Merge branch 'v0.15.1-beta-6847' into v0.15.1-branch-rc2
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-08-22 18:05:29 -05:00
Olaoluwa Osuntokun
29ac0e171c build: bump version to v0.15.1-beta.rc2 2022-08-22 18:05:11 -05:00
Elle Mouton
7324256f42 rpcserver+docs: add default case to addr type switch
This commit adds a default case to the address type switch statement in
the NewAddress rpc server function. This catches any invalid address
types and returns an error.
2022-08-22 18:03:42 -05:00
Olaoluwa Osuntokun
cabeef2128
Merge pull request #6827 from Roasbeef/v0.15.1-branch-rc1
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
multi: create v0.15.1 rc1 release branch
2022-08-15 14:19:58 -07:00
Olaoluwa Osuntokun
b9ae910d39 Merge branch 'v0.15.1-beta-6588' into v0.15.1-branch-rc1 2022-08-15 11:59:45 -07:00
Carsten Otto
b4177b5b9d peer: add pubkey to log messages 2022-08-15 11:59:27 -07:00
Olaoluwa Osuntokun
5e3c70600b Merge branch 'v0.15.1-beta-6510' into v0.15.1-branch-rc1 2022-08-15 11:58:24 -07:00
ErikEk
63012b84da doc: release notes 2022-08-15 11:57:38 -07:00
ErikEk
92c3769c2d neutrinorpc: add getblockhash command 2022-08-15 11:56:45 -07:00
ErikEk
1a72fa7be6 neutrinorpc: add getblockhash functionality 2022-08-15 11:56:45 -07:00
Olaoluwa Osuntokun
e682abcf8f
build: bump version to v0.15.1-beta.rc1 2022-08-12 17:12:56 -07:00
Olaoluwa Osuntokun
9ac8bd4097 Merge branch 'v0.15.1-beta-6826' into v0.15.1-branch-rc1 2022-08-12 17:12:20 -07:00
Olaoluwa Osuntokun
037636a702 chainreg: update tapoort node awareness to account for bitcoind 19+
Bitcoind 23 will use the new `getdeploymentinfo` while versions after 19
(but below 23) will use the `UnifiedSoftForks` field instead of the
`SoftForks UnifiedSoftForks` field.

With this PR the taproot gating logic has been tested on bitcoind
versions: 21, 22, and 23. 21 is when the taproot logic was first added.
2022-08-12 17:12:20 -07:00
Olaoluwa Osuntokun
92a657e7f0 Merge branch 'v0.15.1-beta-6664' into v0.15.1-branch-rc1 2022-08-12 17:12:03 -07:00
eugene
43b08b75e7 release-notes: update for 0.15.1 2022-08-12 17:12:03 -07:00
eugene
414edeb5bd funding: defer sending channel_update until received funding_locked
This is required by BOLT#07 as otherwise the counter-party will
discard the channel_update as they may not consider the channel
"ready" or reorg-safe. Most other implementations besides eclair
have work-arounds for this, but it is nice to be spec-compliant.
2022-08-12 17:12:03 -07:00
Olaoluwa Osuntokun
0d8bae8004 Merge branch 'v0.15.1-beta-6820' into v0.15.1-branch-rc1 2022-08-12 17:11:43 -07:00
Olaoluwa Osuntokun
259f104a48 build: update to latest versions of btec, btcutil, and btcutil/psbt
Fixes #6668
2022-08-12 17:11:43 -07:00
Olaoluwa Osuntokun
1294c3d03f Merge branch 'v0.15.1-beta-6716' into v0.15.1-branch-rc1 2022-08-12 17:11:19 -07:00
eugene
197e3b7c26 release-notes: update for 0.15.1 2022-08-12 17:11:19 -07:00
eugene
bf7c417216 lntest: update zero-conf tests to account for zeroconfacceptor 2022-08-12 17:11:19 -07:00
eugene
5003af9c59 chanacceptor+lnrpc: update the commitmentTypes, send zero-conf to client
This updates the RPCAcceptor to send the correct commitment type
even if the zero-conf or scid-alias channel types are set. This also
adds two bools to the ChannelAcceptRequest struct that denotes whether
the funder set the zero-conf and scid-alias channel types.
2022-08-12 17:11:19 -07:00
eugene
10d4953b31 multi: add zeroconfacceptor that default rejects if no rpc acceptors
This is a safety mechanism so that zero-conf channels are not accepted
by default if no rpc acceptor exists.
2022-08-12 17:11:19 -07:00
Olaoluwa Osuntokun
51fd540c36 Merge branch 'v0.15.1-beta-6810' into v0.15.1-branch-rc1 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
973265483d docs/release-notes: add release notes entry 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
2e2357449f lnwallet/chanfunding: assumes all change outputs are P2TR 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
7bf83b13a8 lnwallet: use P2TR addresses for change outputs for funding coin select 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
62a52cf56c rpc: use P2TR addresses when sending funds back to wallet (anchor reserve) 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
090f30966e sweep: change outputs are now P2TR 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
13f82ba388 watchtower: uses P2TR for sweep, delivery, and reward addresses
In this commit, we modify the watch tower to use P2TR addrs for just
about anything sweep related.

One eye sore in this diff are the changes to
`backup_task_internal_test.go`. All the values are hard coded, and now
either differ by a value of 48, or needed to be modified to account for
the new assumptions propagated to rewards values and fees.
2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
98c69a3988 contractcourt: the breach arb now uses P2TR outputs for sweep addrs 2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
bc18282e1f server: default sweep addrs to P2TR
This change covers sweep addresses for: the breach arbitrator, and watch
tower clients.
2022-08-12 17:10:53 -07:00
Olaoluwa Osuntokun
f44464e592 Merge branch 'v0.15.1-beta-6633' into v0.15.1-branch-rc1 2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
21668be1f6 docs/release-notes: add release notes entry 2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
637dd0f902 lntest/itest: add new itest to cover taproot co-op close 2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
a210475d11 feature+lncfg: add config option to turn of anysegwit 2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
a3951d4774 peer: send taproot addrs during co-op close based on new feature bit
If the ShutdownAnySegwitOptional option is active, then we can safely
send these newer addresses.
2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
41db3ea19b funding: send taproot addrs as upfront shutdown if ShutdownAnySegwitOptional is active 2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
436bf51411 lnwallet/chanclose: update ProcessCloseMsg to check co-op close addrs
We only want to allow p2wkh, p2tr, and p2wsh addresses, so we'll utilize
the newly public wallet function to restrict this.
2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
dc87d6016f lnwallet: export ValidateUpfrontShutdown and restrict allowed addrs
In this commit, we catch up our logic with the latest version of the
spec that removed support for normal p2kh and p2sh addresses for co-op
closes, in order to make dust calculations more uniform.
2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
6a00952dcc lnwire+feature: add awareness of option_shutdown_anysegwit
In this commit, we add awareness of the option_shutdown_anysegwit that
permits both sides to send newer segwit based addresses. This'll
eventually enable us to send taproot addresses for co-op close.
2022-08-12 17:10:21 -07:00
Olaoluwa Osuntokun
31b7baa4f3 Merge branch 'v0.15.1-beta-6734' into v0.15.1-branch-rc1 2022-08-12 17:09:53 -07:00
eugene
05f05e6e79 release-notes: update for 0.15.1 2022-08-12 17:09:53 -07:00
eugene
44ad0165e5 rpc+cli: add general ListAliases function to dump all aliases 2022-08-12 17:09:53 -07:00
eugene
1bee0bd1fc rpc: add zero-conf, alias information to {list,closed}channels 2022-08-12 17:09:53 -07:00
Olaoluwa Osuntokun
9c4209bb4b Merge branch 'v0.15.1-beta-6816' into v0.15.1-branch-rc1 2022-08-12 17:09:38 -07:00
eugene
3ada219762 docs: add documentation for zero-conf channels
This short doc goes into how to open zero-conf channels as either
the funder or fundee.
2022-08-12 17:09:38 -07:00
eugene
a91770553f funding: remove TODO 2022-08-12 17:09:38 -07:00
Olaoluwa Osuntokun
72754ba6b1 Merge branch 'v0.15.1-beta-6740' into v0.15.1-branch-rc1 2022-08-12 17:09:25 -07:00
eugene
f54dfe30aa release-notes: update for 0.15.1 2022-08-12 17:09:25 -07:00
eugene
ed1fdd264c sweep: account for all script types in craftSweepTx
With this change, transactions created via craftSweepTx will be
standard. Previously, p2wsh/p2pkh scripts passed in via SendCoins would
be weighted as p2wpkh scripts. With a feerate of 1 sat/vbyte,
transactions returned would be non-standard. Luckily, the critical
sweeper subsystem only used p2wpkh scripts so this only affected
callers from the rpcserver.

Also added is an integration test that fails if SendCoins manages
to generate a non-standard transaction. All script types are now
accounted for in getWeightEstimate, which now errors if an unknown
script type is passed in.
2022-08-12 17:09:25 -07:00
Olaoluwa Osuntokun
7357df9202 Merge branch 'v0.15.1-beta-6770' into v0.15.1-branch-rc1 2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
f9ef5c6ffe docs/release-notes: add entry for 0.15.1 2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
6201b2d7f0 multi: thread through the new max fee field for co-op close
In this commit, we parse the new max fee field, and pass it through the
switch, all the way to the peer where it's ultimately passed into the
chan closer state machine.
2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
ab14e29757 lnrpc: add a new max_fee field to the CloseChannel RPC call
In this commit, we add a new max_fee field that we'll use to decide when
to bail out of a co-op close dance as the initiator.
2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
b6ea634ba9 lnwallet/chancloser: add tests for the new max fee behavior 2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
2fb304b6f4 lnwallet/chancloser: remove raw state machine pointer, add channel interface
In this commit, we remove the raw channel state machine pointer from the
chan closer and instead replace that with an interface that captures
*just* the methods we need in order to do the co-op close dance.

This is a preparatory refactoring for some upcoming unit tests.
2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
e0d8f461a1 lnwallet: add new AbsoluteThawHeight method
This lets callers get the thaw height without needing to first obtain a
snapshot of the channel state.
2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
9ae013ca46 lnwallet/chancloser: remove the commit fee clamp, introduce max fee
In this commit, we stop clamping the ideal fee rate to the commitment
fee of the channel. This catches us up to this PR of the spec:
https://github.com/lightning/bolts/pull/847.

We also do away with the old 3x ideal fee "max fee", and replace that
with an explicit max fee. This new max fee will either be the default
multiplier of the ideal fee, or a new user specified max fee value.
2022-08-12 17:08:47 -07:00
Olaoluwa Osuntokun
170c9fd8c3 Merge branch 'v0.15.1-beta-6798' into v0.15.1-branch-rc1 2022-08-12 17:07:51 -07:00
Olaoluwa Osuntokun
deeaa0c9c7 chainreg: shutdown if backend node doesn't support taproot
In this commit, we add a check during normal node construction to see if
the backend node supports Taproot. If it doesn't, then we want to
shutdown and force the user to take note.

To check if the node supports Taproot, we'll first try the normal
getblockchaininfo call. If this works, cool, then we can rely on the
value. If it doesn't, then we'll fall back to the getdeploymentinfo call
which was added in a recent version of bitcoind [1]. Newer versions of
bitcoind might also have this call, and the getblockchaininfo call, but
not actually populate the softforks field [2]. In this case, we'll fall
back, and we also account for the case when the getblockchaininfo RPC is
removed all together.

[1]: https://github.com/bitcoin/bitcoin/pull/23508
[2]: https://github.com/bitcoin/bitcoin/pull/25114

Fixes #6773
2022-08-12 17:07:51 -07:00
Olaoluwa Osuntokun
345e66153b Merge branch 'v0.15.1-beta-6809' into v0.15.1-branch-rc1 2022-08-12 17:07:39 -07:00
positiveblue
8ad95972af docs: Add release notes for feature bit fix (#6809) 2022-08-12 17:07:39 -07:00
positiveblue
f96866915b feature: remove ScidAliasOptional dependency on ExplicitChannelTypeOptional
The [spec](https://github.com/lightning/bolts/blob/master/09-features.md)
does not specify a dependency between `ScidAliasOptional` (47) and
`ExplicitChannelTypeOptional` (45).

This bug lead to some connectivity issues with peers not setting the
45 feature bit while setting the 47.

The issue [6802](https://github.com/lightningnetwork/lnd/issues/6802) is
an example of this.
2022-08-12 17:07:39 -07:00
Olaoluwa Osuntokun
d9d0e470ad Merge branch 'v0.15.1-beta-6736' into v0.15.1-branch-rc1 2022-08-12 17:07:20 -07:00
bitromortac
5c93c2c677 config: allow independent rpccookie config
The bitcoind .cookie contains an autogenerated user (__cookie__) and
password (random string), which can be used instead of the rpc user name
and password. This commit allows for running against bitcoind without
having to access bitcoin.conf like in the case for pure
user/password/zmq configuration.
2022-08-12 17:07:08 -07:00
Olaoluwa Osuntokun
91329e7970 Merge branch 'v0.15.1-beta-6469' into v0.15.1-branch-rc1 2022-08-12 17:06:11 -07:00
yyforyongyu
f2c767e79a docs: add release note for optional migration 2022-08-12 17:05:59 -07:00
yyforyongyu
c09f1875aa channeldb: skip dry run mode for optional migrations 2022-08-12 17:05:24 -07:00
yyforyongyu
2a6ac8a117 migration30: validate migration results before deleting old buckets
This commit adds a new method `validateMigration` to be used prior to
the deletion of the old buckets to be extraly cautious.
2022-08-12 17:05:24 -07:00
yyforyongyu
a5755d4568 migration30: cover the case where v0.15.0 is active
This commit changes how we locate the next migration height by including
the scenario where `lnd@v0.15.0` is active. In the new version, we will
see a mixed of new and old logs under the same open channel bucket.
Hence, we need to alter how we locate the next un-migrated height.
2022-08-12 17:05:24 -07:00
yyforyongyu
626a8b3504 multi: add the flag prune-revocation to perform the optional migration 2022-08-12 17:05:24 -07:00
yyforyongyu
65a2f3ac81 channeldb: add optional meta and migration30
This commit enables the db to run optional migrations that are specified
by config flags. To achieve this, an optional meta is introduced to
manage the optional migrations. We distinguish the two types of
migrations here so it's easier to manage them for the concern a future
migration can cause trouble for us to determine the db version if we
don't.
2022-08-12 17:05:24 -07:00
yyforyongyu
e84fa208ff migration30: add benchmark test 2022-08-12 17:05:24 -07:00
yyforyongyu
45903c2f5e migration30+migtest: add unit tests for migration 2022-08-12 17:05:24 -07:00
yyforyongyu
02879f08c0 migration30: add migration to convert old revocation logs
This commit adds the migration that's used to convert the old revocation
logs into the new format. The migration is fault-tolerant, meaning the
process can be interrupted and the migration will pick up what's left
when running again. We also cap how many records to be processed in each
db transaction to prevent OOM.
2022-08-12 17:05:24 -07:00
yyforyongyu
120dc4ae77 migration30: add unit tests for iterator 2022-08-12 17:05:24 -07:00
yyforyongyu
955ef2e10e migration30: add supporting functions to help with unit tests
This commit adds supporting functions that will be used in the unit
test. The testing data are also added as hard-coded. We choose to copy
the most of the testing data from our itest results such that a) they
are "real" data that can be used to calculate scripts and b) we preserve
the result generated by the current code so a future change won't affect
our test.
2022-08-12 17:05:24 -07:00
yyforyongyu
7b46d1dc1d migration30: add iterator to assist migration
This commit adds several utility functions to assist the migration. In
particular, an updateLocator is added to gives us the next un-migration
position in our buckets. This locator helps us to continue the job
in case of an interrupted migration. It also serves as an indicator on
whether the migration is finished or not.
2022-08-12 17:05:24 -07:00
yyforyongyu
658515c9ce migration30: add related revocation log and lnwallet code
This commit adds relevant code from the revocation_log.go and the
package lnwallet. The code is needed to migrate the data, and we choose
to copy the code instead of importing to preserve the version such that
a future change won't affect current migration. An alternative would be
tagging each of the packages imported.
2022-08-12 17:05:24 -07:00
Olaoluwa Osuntokun
c8935e61bc Merge branch 'v0.15.1-beta-6748' into v0.15.1-branch-rc1 2022-08-12 17:04:56 -07:00
Martin Habovštiak
c4dde72aa3 doc: Deprecation reason of settled on Invoice
This documents how to deal with `settled` being deprecated. It took me quite a bit of digging without such documentation.

[skip ci]
2022-08-12 17:04:56 -07:00
Olaoluwa Osuntokun
d6fd8d1ba1 Merge branch 'v0.15.1-beta-6754' into v0.15.1-branch-rc1 2022-08-12 17:04:09 -07:00
Elle Mouton
8a17009afa multi: registration complete MW interceptor msg
In this commit, we change the flow of the rpc middleware registration
a bit. In order to allow a client to add rpc middleware interceptors in
a deterministic order, we now make the server send a "registration
complete" message to the client after compeleting the registration
process so that the client knows when it can go ahead and register the
next client.
2022-08-12 17:04:09 -07:00
Olaoluwa Osuntokun
95a6425189 Merge branch 'v0.15.1-beta-6763' into v0.15.1-branch-rc1 2022-08-12 17:03:57 -07:00
Thebora Kompanioni
c327a35e4e fix: go version in ARMv6 section of INSTALL.md 2022-08-12 17:03:57 -07:00
Olaoluwa Osuntokun
510ca08e64 Merge branch 'v0.15.1-beta-6741' into v0.15.1-branch-rc1 2022-08-12 17:03:44 -07:00
Matt Morehouse
7881f0a510 doc: update release notes 2022-08-12 17:03:43 -07:00
Matt Morehouse
2c4cf9379f itest: fix sign_psbt failure
Ensure the wallet has synced the blockchain before attempting to spend
funds.

Prior to this fix, I get the following error:
  rpc error: code = Unknown desc = wallet couldn't fund PSBT: error
      creating funding TX: insufficient funds available to construct
      transaction
2022-08-12 17:03:43 -07:00
Olaoluwa Osuntokun
2275d75f07 Merge branch 'v0.15.1-beta-6742' into v0.15.1-branch-rc1 2022-08-12 17:03:01 -07:00
Symphonic3
ac7d8e5d13 Fix typo in abandonchannel description
i_know_what_im_doing --> i_know_what_i_am_doing
2022-08-12 17:03:01 -07:00
Olaoluwa Osuntokun
6e59bd811a Merge branch 'v0.15.1-beta-6739' into v0.15.1-branch-rc1 2022-08-12 17:02:47 -07:00
Elle Mouton
74a8cb09e5 rpcperms: re-init mw lookup map after removal of one
After removing a registered middlware from the slice, we need to update
the index lookup map with the updated index for each middleware.
2022-08-12 17:02:47 -07:00
Olaoluwa Osuntokun
62dcb3ca34 Merge branch 'v0.15.1-beta-6545' into v0.15.1-branch-rc1 2022-08-12 17:02:31 -07:00
yyforyongyu
c9461d3925 docs: add release note for skip_temp_err 2022-08-12 17:02:31 -07:00
yyforyongyu
31ba12d553 routerrpc+cmd: use skip_temp_err when sending to route 2022-08-12 17:02:31 -07:00
yyforyongyu
ec8506e923 routerrpc: add new field skip_temp_err in SendToRouteRequest 2022-08-12 17:02:31 -07:00
yyforyongyu
b4df816530 routing: fix unit test for SendToRoute
This commit removes the old multi shards test for `SendToRoute` as the
method doesn't support sending MPP. The original test passed due to a
flawed mocking method, where the mockers bypassed the public interfaces
to maintain their internal state, which caused a non-exsiting situation
that a temp error wouldn't fail the payment. A new unit test is added to
demonstrate the actual case.
2022-08-12 17:02:31 -07:00
yyforyongyu
350ddfb1c7 routing: add unit test for SendToRouteSkipTempErr 2022-08-12 17:02:31 -07:00
yyforyongyu
1ad08d1b44 routing: add SendToRouteSkipTempErr to skip temp error failure
This commit adds a new method `SendToRouteSkipTempErr` that skips
failing the payment unless a terminal error occurred. This is
accomplished by demoting the original `SendToRoute` to a private method
and creating two new methods on top of it to minimize code change.
2022-08-12 17:02:31 -07:00
Carsten Otto
eb95fc9579 router: fix typos 2022-08-12 17:02:31 -07:00
Olaoluwa Osuntokun
07a0a22531 Merge branch 'v0.15.1-beta-6722' into v0.15.1-branch-rc1 2022-08-12 17:00:50 -07:00
ErikEk
23f7923d2b doc: release notes 2022-08-12 17:00:50 -07:00
ErikEk
cacf83e0ec itest: cover sign and verify msg 2022-08-12 17:00:50 -07:00
ErikEk
d32427eb06 signrpc: add schnorr sig to sign and validate msg 2022-08-12 17:00:50 -07:00
Olaoluwa Osuntokun
bb5199936c Merge branch 'v0.15.1-beta-6718' into v0.15.1-branch-rc1 2022-08-12 17:00:38 -07:00
Slyghtning
a70fe7e41e lncli: chan_point option for abandonchannel [skip ci] 2022-08-12 17:00:38 -07:00
Olaoluwa Osuntokun
01be76c631 Merge branch 'v0.15.1-beta-6630' into v0.15.1-branch-rc1 2022-08-12 17:00:13 -07:00
Oliver Gugger
b9d15055a6 docs: update release notes 2022-08-12 17:00:13 -07:00
Oliver Gugger
94204f529a itest: add integration test for error interception 2022-08-12 17:00:13 -07:00
Oliver Gugger
0412784cb4 itest: add integration test for request replacement 2022-08-12 17:00:13 -07:00
Oliver Gugger
f0b762cbf8 rpcperms: intercept errors too 2022-08-12 17:00:13 -07:00
Oliver Gugger
bbb1781e1d lnrpc: add is_error to intercept message 2022-08-12 17:00:13 -07:00
Oliver Gugger
179d1b8db5 lnrpc: describe request replacement in API docs
This commit updates the comments in the proto file to mention the new
behavior of also being able to replace request messages.
2022-08-12 17:00:13 -07:00
Oliver Gugger
45c499a022 rpcperms: allow requests to be replaced as well
With this commit we allow a replacement message to be sent by the
middleware for a request type as well as the response type. This allows
an incoming RPC request to be modified before it is forwarded to lnd.
2022-08-12 17:00:13 -07:00
Oliver Gugger
83defb449a rpcperms: add replaceProtoMsg
Because of the way the gRPC Receive() method is designed, we need a way
to replace a proto message with the content of another one without
replacing the original instance itself (e.g. overwrite all values in the
existing struct instance).
2022-08-12 17:00:13 -07:00
Oliver Gugger
b08d1b2a4f lnrpc: enable RPC middleware in REST WebSockets
If we don't flag the /v1/middleware call as request streaming, it can't
be used properly with REST WebSockets because the proxy would close the
connection after the first request message.
2022-08-12 17:00:13 -07:00
Olaoluwa Osuntokun
cc8ccabec4 Merge branch 'v0.15.1-beta-6714' into v0.15.1-branch-rc1 2022-08-12 16:59:53 -07:00
Oliver Gugger
5e8a073203 docs: add release notes 2022-08-12 16:59:53 -07:00
Oliver Gugger
5a038a9de1 itest: fix timeout in sign_psbt test 2022-08-12 16:59:53 -07:00
Oliver Gugger
d7dcbbf9d8 lnwallet: don't create BIP044 key scope by default
With a change in #6379 we made sure that all default scopes are added to
the the wallet. Unfortunately this included the BIP044 key scope that
our wallet doesn't really use. This breaks the remote signing setup
because we don't export the account of the BIP044 scope and therefore
run into an issue on the watch-only side when attempting to create the
wallet.
2022-08-12 16:59:53 -07:00
Olaoluwa Osuntokun
db32955f54 Merge branch 'v0.15.1-beta-6724' into v0.15.1-branch-rc1 2022-08-12 16:59:15 -07:00
Elle Mouton
7778d987f4 lncli: add ignore_pair flag to queryroutes 2022-08-12 16:59:15 -07:00
Olaoluwa Osuntokun
a936eeee9a Merge branch 'v0.15.1-beta-6712' into v0.15.1-branch-rc1 2022-08-12 16:58:53 -07:00
Olaoluwa Osuntokun
bedebc5caa lntest: keep all failed payments by default for HarnessNode
In this commit, we fix a detected flake: we go to make a payment, and
then want to assert that 2 attempts we required. The existing logic
assumes that the success and the payment will still be on disk. With a
recent PR, we now delete failed payments by default, but after the fact,
in a non-atomic fashion.

We fix this issue simply by having all the nodes keep around failed
payments for the sake of all the old itests that assumed this
information would always be on disk.

Introduced in: https://github.com/lightningnetwork/lnd/pull/6438.

Fixes https://github.com/lightningnetwork/lnd/issues/6711.
2022-08-12 16:58:53 -07:00
Olaoluwa Osuntokun
907e1084fc Merge branch 'v0.15.1-beta-6709' into v0.15.1-branch-rc1 2022-08-12 16:58:27 -07:00
Elle Mouton
3968f2a50f rpcperms: enforce order of interceptors
In this commit, we let the registered middleware interceptors be stored
in a slice rather than a map so that the order in which the interceptors
are executed is guarenteed to be the same as the order in which they
were registered.
2022-08-12 16:58:27 -07:00
Olaoluwa Osuntokun
45751da711 Merge branch 'v0.15.1-beta-5955' into v0.15.1-branch-rc1 2022-08-12 16:58:16 -07:00
eugene
c8395475c8 funding: revert earlier change for LDK compatibility
This removes the requirement that the zero-conf channel acceptor
flow use anchors. Also adds a fail-early check for minimum depth
zero in the non zero conf case. It would fail later, but it makes
more sense to fail immediately when receiving AcceptChannel.
2022-08-12 16:58:16 -07:00
eugene
78d7545e4d release-notes: update for 0.15.0 2022-08-12 16:58:16 -07:00
eugene
a226894cda sample-lnd: showing how to enable scid-alias, zero-conf feature bits 2022-08-12 16:58:16 -07:00
eugene
3b66147164 itest: zero-conf, scid-alias channel-type integration tests 2022-08-12 16:58:16 -07:00
eugene
ffb7f1d017 multi: add zero-conf, scid-alias channel-types to rpc
This allows the open channel rpcs to use the zero-conf or scid-alias
channel types.
2022-08-12 16:58:16 -07:00
eugene
e0221e593f server+netann+peer: put peer's alias in Update, proper config for link
This commit modifies the netann subsystem to use the peer's alias
for ChannelUpdates where appropriate (i.e. in case we are sending
the alias to the peer). It also modifies the loadActiveChannels
function in the peer package to handle upgrading a channel when the
scid-alias feature bit is turned on.
2022-08-12 16:58:16 -07:00
eugene
fff6f6b07c chanbackup: handle Single creation for zero-conf channels
The SCB function NewSingle is now zero-conf aware. Since the confirmed
short channel id may be unknown, it may use the broadcast height.
2022-08-12 16:58:16 -07:00
eugene
ea4be6069b contractcourt: set proper height hint for zero-conf channels
The contractcourt's chain watcher is now zero-conf aware and will use
an appropriate heightHint when scanning the chain.
2022-08-12 16:58:16 -07:00
eugene
adea487638 rpcserver+invoicesrpc: alias-aware AddInvoice,AddHoldInvoice rpc
AddInvoice,AddHoldInvoice now issue invoices that include our
peer's aliases. Some extra sanity checks are included to ensure we
don't leak our confirmed SCID for a private channel.
2022-08-12 16:58:16 -07:00
eugene
7ec5d09ef1 server+funding: allow scid-alias, zero-conf chantypes, scid-alias
feature-bit channels

This allows opening zero-conf chan-type, scid-alias chan-type, and
scid-alias feature-bit channels. scid-alias chan-type channels are
required to be private. Two paths are available for opening a zero-conf
channel:

* explicit chan-type negotiation
* LDK carve-out where chan-types are not used, LND is on the
  receiving end, and a ChannelAcceptor is used to enable zero-conf

When a zero-conf channel is negotiated, the funding manager:
* sends a FundingLocked with an alias
* waits for a FundingLocked from the remote peer
* calls addToRouterGraph to persist the channel using our alias in
  the graph. The peer's alias is used to send them a ChannelUpdate.
* wait for six confirmations. If public, the alias edge in the
  graph is deleted and replaced (not atomically) with the confirmed
  edge. Our policy is also read-and-replaced, but the counterparty's
  policy won't exist until they send it to us.

When a scid-alias-feature channel is negotiated, the funding manager:
* sends a FundingLocked with an alias:
* calls addToRouterGraph, sends ChannelUpdate with the confirmed SCID
  since it exists.
* when six confirmations occurs, the edge is deleted and re-inserted
  since the peer may have sent us an alias ChannelUpdate that we are
  storing in the graph.

Since it is possible for a user to toggle the scid-alias-feature-bit
to on while channels exist in the funding manager, care has been taken
to ensure that an alias is ALWAYS sent in the funding_locked message
if this happens.
2022-08-12 16:58:16 -07:00
eugene
37c68c1f19 server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.

Introduces are two maps:

* aliasToReal:
  This is an N->1 mapping for a channel. The keys are the set of
  aliases and the value is the confirmed, on-chain SCID.

* baseIndex:
  This is also an N->1 mapping for a channel. The keys are the set
  of aliases and the value is the "base" SCID (whatever is in the
  OpenChannel.ShortChannelID field). There is also a base->base
  mapping, so not all keys are aliases.

The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.

* getLinkByMapping
  This function is introduced to adhere to the spec requirements that
  using the confirmed SCID of a private, scid-alias-feature-bit
  channel does not work. Lnd implements a stricter version of the spec
  and disallows this behavior if the feature-bit was negotiated, rather
  than just the channel type. The old, privacy-leak behavior is
  preserved.

The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-08-12 16:58:16 -07:00
eugene
d242b86232 server+routing: pass isAlias to router
This allows the router to determine what is and isn't an alias from
lnd's definition of an alias. Any ChannelAnnouncement that has an
alias ShortChannelID field is not verified on-chain. To prevent a
DoS vector from existing, the gossiper ensures that only the local
lnd node can send its ChannelAnnouncements to the router with an
alias ShortChannelID.
2022-08-12 16:58:16 -07:00
eugene
550f8f0d5a server+discovery: alias-handling in gossiper
An OptionalMsgField has been added that allows outside subsystems
to provide a short channel id we should insert into a ChannelUpdate
that we then sign and send to our peer.

When the gossiper receives a ChannelUpdate, it will query the
alias manager by the passed-in FindBaseByAlias function to determine
if the short channel id in the ChannelUpdate points to a known
channel. If this lookup returns an error, we'll fallback to using
the original id in the ChannelUpdate when querying the router.
The lookup and potential fallback must occur in order to properly
lock the multimutex, query the correct router channels, and rate
limit the correct short channel id. An unfortunate side effect of
receiving ChannelUpdates from our peer that reference on of our
aliases rather than the real SCID is that we must store this policy.
Yet it is not broadcast-able. Care has been taken to ensure the
gossiper does not broadcast *any* ChannelUpdate with an alias SCID.

The cachedNetworkMsg uses the new processedNetworkMsg struct. This
is necessary so that delete-and-reinsert in the funding manager
doesn't process a ChannelUpdate twice and end up in a deadlock since
the err chan is no longer being used.
2022-08-12 16:58:16 -07:00
eugene
d7d84a1f7e aliasmgr: new data store containing our, peer's aliases
This introduces the a store for managing all things alias-related.

There are two maps:

* baseToSet:
  This stores the "base" short channel id as the key. The value is
  the set of all aliases issued for this channel. The "base" SCID is
  whatever is stored in the OpenChannel's ShortChannelID member. For
  everything other than zero-conf channels, this is the confirmed SCID.
  For zero-conf channels, this is the very first alias assigned. This is
  used mostly by the Switch to retrieve a set of aliases and determine
  if it is safe to forward.

* aliasToBase:
  This stores the reverse mapping of baseToSet. Each key is an alias
  SCID and the value is the "base" SCID. This is exclusively used by
  the gossiper to determine if an alias in a ChannelUpdate our peer
  sends actually references a channel we know of.

The functions make use of the above two maps:

* AddLocalAlias:
  This persists the {alias, base} pair in the database. The baseToSet
  map is populated. The aliasToBase is optionally populated depending on
  where this function is called from. Upgrade cases, where the
  scid-alias feature bit is toggled and channels already exist, will
  not persist to the gossip map. This is mainly to simplify the tangle
  of logic that would otherwise occur.

* GetAliases:
  This fetches the set of aliases by using the passed-in base SCID. This
  is used in the Switch and other places where the alias set is needed.

* FindBaseSCID:
  This fetches the base given an alias. This is used in the gossiper to
  determine validity of a peer's ChannelUpdate that contains an alias.

* DeleteSixConfs:
  This removes the aliasToBase map entry for the given "base". This is
  used when the gossiper mappings are no longer needed, i.e. when the
  channel has six confirmations and is public.

* PutPeerAlias:
  Stores the peer's alias.

* GetPeerAlias:
  Fetches the peer's alias.

* RequestAlias:
  Generates an alias for us in the range 16000000:0:0 and
  16250000:16777215:65535
2022-08-12 16:58:16 -07:00
eugene
888fbc6be3 lnwallet: extend Reservation with alias chan-type, feature-bit flags
This extends the Reservation arguments to include whether a pending
channel open has negotiated the zero-conf channel type, the scid-alias
channel type, and/or the scid-alias feature bit. The result of those
negotiates are stored in the OpenChannel's ChanType. The arguments to
NewChannelReservation have also been simplified.
2022-08-12 16:58:16 -07:00
eugene
5d2b686f0b channeldb: BigSize migration, store zero-conf, scid-alias bits
This introduces a BigSize migration that is used to expand the width
of the ChannelStatus and ChannelType fields. Three channel "types"
are added - ZeroConfBit, ScidAliasChanBit, and ScidAliasFeatureBit.
ScidAliasChanBit denotes that the scid-alias channel type was
negotiated for the channel. ScidAliasFeatureBit denotes that the
scid-alias feature bit was negotiated during the *lifetime* of the
channel. Several helper functions on the OpenChannel struct are
exposed to aid callers from different packages.

The RefreshShortChanID has been renamed to Refresh.

A new function BroadcastHeight is used to guard access to the
mutable FundingBroadcastHeight member. This prevents data races.
2022-08-12 16:58:16 -07:00
eugene
23b6460201 lnwire: add alias to FundingLocked in TLV
This adds an optional short channel id field to the FundingLocked
message that is sent/received as a TLV segment inside the
ExtraOpaqueData field.
2022-08-12 16:58:16 -07:00
eugene
c815fb8de7 server+lncfg: protocol flag to enable scid-alias, zero-conf feature bits
This allows the zero-conf and scid-alias feature bits to be toggled
using the config. The feature bits are off by default to protect users
from accidentally incurring the risk of a zero-conf channel.
2022-08-12 16:58:16 -07:00
eugene
113de58d77 lnwire+feature: new zero-conf, scid-alias feature bit + chantypes
This defines the zero-conf feature bit, the scid-alias feature bit,
the zero-conf channel type, and the scid-alias channel type. It also
defines the dependency "tree" that exists for the feature bits.

The scid-alias feature bit signals that the node requires an alias
short channel id to be sent in funding_locked. The scid-alias channel
type requires that the channel is private, in addition to some other
forwarding-related privacy measures.
2022-08-12 16:58:16 -07:00
Olaoluwa Osuntokun
e5870319be Merge branch 'v0.15.1-beta-6705' into v0.15.1-branch-rc1 2022-08-12 16:57:56 -07:00
Slyghtning
270971c475 lncli: chan_point option for updatechanstatus 2022-08-12 16:57:56 -07:00
Olaoluwa Osuntokun
5c8e8ae7be Merge branch 'v0.15.1-beta-6698' into v0.15.1-branch-rc1 2022-08-12 16:57:44 -07:00
Slyghtning
c25641b624 lncli: Fix batchopenchannel help text [skip ci] 2022-08-12 16:57:44 -07:00
Olaoluwa Osuntokun
d4cf0f1bdc Merge branch 'v0.15.1-beta-6636' into v0.15.1-branch-rc1 2022-08-12 16:57:31 -07:00
Tommy Volk
43e6a20d37 gitrelease-notes: update release notes for 0.15.1 2022-08-12 16:57:31 -07:00
Tommy Volk
60017f87f4 multi: migrate assert.NoError to require.NoError 2022-08-12 16:57:31 -07:00
Olaoluwa Osuntokun
f14a02c356 Merge branch 'v0.15.1-beta-6438' into v0.15.1-branch-rc1 2022-08-12 16:57:03 -07:00
Tommy Volk
fc2c90275c gitrelease-notes: update release notes for 0.15.1 2022-08-12 16:57:03 -07:00
Tommy Volk
064e0c6273 channeldb+routing: htlcs are pruned on settle 2022-08-12 16:57:03 -07:00
Tommy Volk
0a1289d606 multi: add keep-failed-payment-attempts flag 2022-08-12 16:57:03 -07:00
Olaoluwa Osuntokun
0d98121f12 Merge branch 'v0.15.1-beta-6685' into v0.15.1-branch-rc1 2022-08-12 16:56:20 -07:00
Oliver Gugger
b8e5b9b5e5 docs: fix formatting and phrasing [skip ci] 2022-08-12 16:56:10 -07:00
Oliver Gugger
4d2c9928dd docs: remove duplicate headings 2022-08-12 16:56:09 -07:00
Oliver Gugger
d1b33e0fbf docs: move 0.15.1 release notes item 2022-08-12 16:54:57 -07:00
Olaoluwa Osuntokun
d4cdc01073 Merge branch 'v0.15.1-beta-6642' into v0.15.1-branch-rc1 2022-08-12 16:53:46 -07:00
eugene
d707b239f7 release-notes: update for 0.15.1 2022-08-12 16:53:32 -07:00
eugene
3171d17edf htlcswitch: add linkStopIndex to cleanly shutdown ChannelLink
With this, extra calls to RemoveLink will wait for the link to
fully stop. This is accomplished by a map that stores a single stop
channel that callers to RemoveLink will listen on. This map is not
consulted when the Switch is shutting down and calls Stop on each
individual link. Though that could be added in the future, it is
not necessary.
2022-08-12 16:51:55 -07:00
Olaoluwa Osuntokun
e28de57075 Merge branch 'v0.15.1-beta-6687' into v0.15.1-branch-rc1 2022-08-12 16:51:33 -07:00
Oliver Gugger
7279732c92 docs: add release notes 2022-08-12 16:51:22 -07:00
Oliver Gugger
f273d11a3b itest: add test for FundPsbt->SignPsbt|FinalizePsbt flow 2022-08-12 16:50:34 -07:00
Oliver Gugger
d88e58c34f lnwallet: fix bug in SignPsbt with np2wkh addresses
Fixes #6626.
If either of the two fields FinalScriptSig or FinalScriptWitness is set
on an input of a PSBT then that results in most of the fields of that
input not to be serialized in the packet anymore, since the input is
considered to be complete.
But because a signer isn't supposed to set any of the Final* fields,
this was wrong from the beginning. Only the finalizer will set those
fields.
2022-08-12 16:50:34 -07:00
Olaoluwa Osuntokun
492ed23d70 Merge branch 'v0.15.1-beta-6592' into v0.15.1-branch-rc1 2022-08-12 16:50:21 -07:00
priyanshiiit
4a0ae8cd61 docs: adds wallet reserve rpc & field in wallet balance 2022-08-12 16:49:19 -07:00
priyanshiiit
51a2fb5c33 lntest: adds check for reserve 2022-08-12 16:48:38 -07:00
priyanshiiit
de09d56369 lnrpc+lncli: adds required reserve rpc & cli 2022-08-12 16:48:38 -07:00
priyanshiiit
8f4dd85773 lnrpc+lnd: adds required reserve in walletbalance rpc 2022-08-12 16:48:38 -07:00
priyanshiiit
212832e8de lnwallet: adds RequiredReserve method 2022-08-12 16:48:38 -07:00
priyanshiiit
e07c6c2681 lnwallet: exports fields related to AnchorChans 2022-08-12 16:48:38 -07:00
Olaoluwa Osuntokun
3e889a5069 Merge branch 'v0.15.1-beta-6680' into v0.15.1-branch-rc1 2022-08-12 16:44:38 -07:00
Oliver Gugger
e1fb7dd4ca docs: add release notes 2022-08-12 16:44:38 -07:00
Oliver Gugger
2c5ac5554e itest: add itest for p2tr via ComputeInputScript 2022-08-12 16:44:38 -07:00
Oliver Gugger
e45a2b9f12 itest: fix incorrect naming 2022-08-12 16:44:38 -07:00
Oliver Gugger
d1ea22dde3 itest: rename too specific variables 2022-08-12 16:44:38 -07:00
Oliver Gugger
90a0df6d90 signer: fix comment about p2tr in ComputeInputScript 2022-08-12 16:44:38 -07:00
Oliver Gugger
e59c410282 signrpc: fix p2tr support in ComputeInputScript 2022-08-12 16:44:38 -07:00
Olaoluwa Osuntokun
ebe0fb155d Merge branch 'v0.15.1-beta-6655' into v0.15.1-branch-rc1 2022-08-12 16:44:10 -07:00
eugene
aaf2a0238e release-notes: update for 0.15.1 2022-08-12 16:44:10 -07:00
eugene
acf35c4e6c itest: update switch delivery tests with more robust reconnect logic 2022-08-12 16:44:10 -07:00
eugene
6f07a7e9e9 server.go: replace call to removePeer with Disconnect in DisconnectPeer
Without this, calls to DisconnectPeer would bypass the
peerTerminationWatcher and allow subsequent connect requests to
go through before the peer's links were fully shut down. This could
lead to force closes.
2022-08-12 16:44:10 -07:00
Olaoluwa Osuntokun
80cd2b1b7e Merge branch 'v0.15.1-beta-6577' into v0.15.1-branch-rc1 2022-08-12 16:43:42 -07:00
ziggie
d588c04997 docs: update release note 2022-08-12 16:43:12 -07:00
ziggie
1502ce73ea cmd/lncli: make hop hint inclusion opt-in for addholdinvoice 2022-08-12 16:42:23 -07:00
Olaoluwa Osuntokun
71d754890e Merge branch 'v0.15.1-beta-6676' into v0.15.1-branch-rc1 2022-08-12 16:41:47 -07:00
Oliver Gugger
231c4b86a1 doc: add release notes 2022-08-12 16:41:47 -07:00
Oliver Gugger
4383f20477 .gitignore: add release build directory to ignore list
Fixes #6672.
A new metadata tag called build.vcs.modified was added in Go 1.18.x that
indicates whether there were any untracked files present during the
build or not.
Because the `make release` command creates a directory in which the
output packages are created, and because that directory was not added
to git and also not ignored by it, the build.vcs.modified flag was
different to the docker build which resulted in a different digest of
the resulting binary.
2022-08-12 16:41:47 -07:00
Olaoluwa Osuntokun
49465b8e32 Merge branch 'v0.15.1-beta-6682' into v0.15.1-branch-rc1 2022-08-12 16:41:27 -07:00
ErikEk
b393e37e19 dep: urfave/cli update 2022-08-12 16:41:27 -07:00
Olaoluwa Osuntokun
8cbb3ab598 Merge branch 'v0.15.1-beta-6673' into v0.15.1-branch-rc1 2022-08-12 16:41:00 -07:00
yyforyongyu
f53522001b channeldb: fix data race in TestSerializeHTLCEntries 2022-08-12 16:41:00 -07:00
Olaoluwa Osuntokun
d532c60d99 Merge branch 'v0.15.1-beta-6321' into v0.15.1-branch-rc1 2022-08-12 16:40:40 -07:00
priyanshiiit
c7387534ea docs: add previous outpoints to listchaintxns 2022-08-12 16:40:40 -07:00
priyanshiiit
3b05e5607f lntest: adds test for previous outpoints 2022-08-12 16:40:40 -07:00
priyanshiiit
ddc54387ba lnrpc: add previous_outpoints to listchaintxns 2022-08-12 16:40:40 -07:00
priyanshiiit
bd32b648f4 lnwallet: add previous_outpoints to ListTransactionDetails 2022-08-12 16:40:40 -07:00
Olaoluwa Osuntokun
12afc2f447 Merge branch 'v0.15.1-beta-6559' into v0.15.1-branch-rc1 2022-08-12 16:39:00 -07:00
ErikEk
47ba871d82 doc: release note 2022-08-12 16:36:33 -07:00
ErikEk
3f3bc404c2 doc: subscribe/cancel/lookup invoices rest 2022-08-12 16:35:40 -07:00
Olaoluwa Osuntokun
ffd9226c82 Merge branch 'v0.15.1-beta-6576' into v0.15.1-branch-rc1 2022-08-12 16:35:02 -07:00
Elle Mouton
bdad44761e docs/release-notes: add note for 6576 2022-08-12 16:35:02 -07:00
Elle Mouton
8dd4571442 cmd/lncli: add payment_addr flag to buildroute 2022-08-12 16:35:02 -07:00
rockstardev
ca4d531435
Removing experimental features, no longer needed 2022-07-25 18:58:05 -05:00
rockstardev
acd72a7fe5
Updating circleci image for multiarch task
Previous one got depricated
https://circleci.com/blog/ubuntu-14-16-image-deprecation/
2022-07-25 18:49:44 -05:00
rockstardev
b0473a9034
Adding BtcPayServer related files and resources 2022-07-25 17:59:45 -05:00
sgiammy
713b79680f accept 'signet' as LND_ENVIRONMENT variable 2022-03-18 13:36:32 +00:00
rockstardev
48e3fa8eed
Cleaning up README, adding new versions 2022-02-07 01:11:40 -06:00
rockstardev
6a5c491ee6
Merge branch 'version/0.14.2-beta'
# Conflicts:
#	Makefile
2022-02-07 01:10:24 -06:00
rockstardev
722219aaf8
Adding BtcPayServer related files and resources 2022-02-07 00:36:59 -06:00
Olaoluwa Osuntokun
1e511be523
build: bump version to v0.14.2-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-02-03 12:20:47 -08:00
Olaoluwa Osuntokun
8c0d61c7e2
build: bump version to v0.14.2-beta.rc2
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-02-03 12:19:40 -08:00
Olaoluwa Osuntokun
5446478ec0 lnwallet: increase legacy fee limit threshold to 1k sats
In this commit, we increase the legacy fee limit threshold (the amount
below which we'll allow 100% of funds to go to fees for the non-v2 RPC
calls) from 50 sats to 1k sats.
2022-02-03 12:19:01 -08:00
Olaoluwa Osuntokun
d4b621b0be Merge branch 'v0.14.2-beta-6226' into v0-14-2-branch-rc1 2022-02-02 12:55:37 -08:00
Oliver Gugger
11c57040aa lncli: use amount based default routing fee 2022-02-02 12:55:16 -08:00
Oliver Gugger
4754e87ce6 lnrpc: use amount based default routing fee 2022-02-02 12:54:15 -08:00
Oliver Gugger
2295ae34ee lnwallet: introduce default routing fee calculation 2022-02-02 12:54:15 -08:00
Olaoluwa Osuntokun
25081770b6
build: bump version to v0.14.2-beta.rc1
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2022-01-26 11:20:10 -08:00
Olaoluwa Osuntokun
824c2a70fc
Merge pull request #6201 from Roasbeef/v0.14.2-branch-rc1
multi: create v0.14.2-beta-rc1 branch
2022-01-26 11:13:46 -08:00
Olaoluwa Osuntokun
9448ca93ea
channeldb: fix unit test API usage after graph cache speedups 2022-01-25 18:18:37 -08:00
Olaoluwa Osuntokun
09b1ae99e6
Merge branch 'v0.14.2-beta-6200' into v0.14.2-branch-rc1 2022-01-25 17:56:22 -08:00
Olaoluwa Osuntokun
8f12fe3daa docs/release-notes: add entry for fee rate bug fix and rpc change 2022-01-25 17:52:24 -08:00
Andras Banki-Horvath
4be12bcd2c itest: add test for the channel policy fee rate round down bug 2022-01-25 17:52:24 -08:00
ErikEk
ed3defc412 lnrpc: fix the existing routing fee inaccuracy
When updating the channel routing policy, we encounter an inaccurate
precision error when calculating the routing fee. The issue stems from
the way the IEEE 754 standard works.

The solution here is to add a uint64 parameter (as mentioned in the
issue) and keep the float64 fee_rate parameter but rounding the product
of the base and fee rate.
2022-01-25 17:52:22 -08:00
Olaoluwa Osuntokun
4b9a23b251 Merge branch 'v0.14.2-beta-6158' into v0.14.2-branch-rc1 2022-01-25 17:49:22 -08:00
eugene
5dbff49d96 docs/release-notes: update notes for 0.14.2 2022-01-25 17:49:08 -08:00
eugene
de4332a6a9 server+contractcourt: hand-off BreachCloseInfo to channel arbitrator
This also changes the chain_watcher and breacharbiter handoff. The
new logic ensures that the channel is only marked as pending closed
when the channel arbitrator has persisted the resolutions and commit
set.
2022-01-25 17:48:41 -08:00
eugene
324c578f77 contractcourt: create breachResolver if BreachResolution present
Also transitions to the proper state based on if this is a legacy
breach in the channel arbitrator or a modern breach with a resolver.
2022-01-25 17:48:02 -08:00
eugene
9b4ab45c5a contractcourt: handle writing BreachResolution in arbitrator log 2022-01-25 17:48:02 -08:00
eugene
3e301785a4 server+contractcourt: add breachResolver that subscribes to breacharbiter
Introduces a breachResolver that subscribes to the breacharbiter to
determine if the final justice transaction has confirmed and can
clean itself up.
2022-01-25 17:48:02 -08:00
Olaoluwa Osuntokun
4f85ff8b69 Merge branch 'v0.14.2-beta-6185' into v0.14.2-branch-rc1 2022-01-25 17:46:56 -08:00
Daniel McNally
99b1347789 rpcperms: set CustomCaveatCondition on middleware req
This sets the `CustomCaveatCondition` value on rpc middleware requests
if one exists. Previously, this value was always blank even if the
macaroon had a value set for its custom caveat condition.
2022-01-25 17:46:56 -08:00
Daniel McNally
a619a9bb04 macaroons: add GetCustomCaveatCondition func
This adds a `GetCustomCaveatCondition` function that returns the custom
caveat condition for a given macaroon and caveat name. Previously there
was no function for getting the custom caveat condition from a macaroon,
only for setting one.
2022-01-25 17:46:56 -08:00
Olaoluwa Osuntokun
a7676e83f4 Merge branch 'v0.14.2-beta-6111' into v0.14.2-branch-rc1 2022-01-25 17:45:13 -08:00
Joost Jager
c6439b907b channeldb: speed up graph cache loading
Use the optimized ForEachChannel method to reduce the graph cache
loading time.
2022-01-25 17:44:43 -08:00
Joost Jager
07a9130734 channeldb: reallocate node in ForEachNodeCacheable
Allows cacheableNode to be used outside of the callback. This is a
preparation for optimization of the graph cache population.
2022-01-25 17:44:09 -08:00
Joost Jager
543eff9d24 channeldb: optimize ForEachChannel
In this commit, we modify the implementation of ForEachChannel to
utilize the new kvdb method ForAll. This greatly reduces the number of
round-trips to the database needed to iterate over all channels
in the graph.
2022-01-25 17:44:09 -08:00
Joost Jager
8a7afd17fb channeldb: extract deserializeChanEdgePolicyRaw
Allows for pure deserialization without depending on a database connection.
2022-01-25 17:44:09 -08:00
Joost Jager
a95acb393b channeldb: extract AddNodeFeatures
Preparation for efficient graph cache loading where we don't iterate
over the channels of each node in the network individually.
2022-01-25 17:44:09 -08:00
Joost Jager
ab79c7bcaa kvdb: add ForAll
A new method to allow efficient range queries for backends that support
it.
2022-01-25 17:44:09 -08:00
Joost Jager
d6c1b7129d routing: remove unused ForEachChannel 2022-01-25 17:44:09 -08:00
Joost Jager
2d2bb75d85 kvdb/postgres: use readonly db transaction if possible 2022-01-25 17:44:09 -08:00
Olaoluwa Osuntokun
592c5363c4 Merge branch 'v0.14.2-beta-6180' into v0.14.2-branch-rc1 2022-01-25 17:43:18 -08:00
Andras Banki-Horvath
695baa1b45 docs: update release notes 0.14.2 2022-01-25 17:43:18 -08:00
Andras Banki-Horvath
5dca6dce00 lncli: add force flag to 2022-01-25 17:43:18 -08:00
Andras Banki-Horvath
5915f546a3 routing: add option to force import MC pair history
This commit adds the `force` flag to the `XImportMissionControl` RPC
which allows skipping rules around the pair import except for what is
mandatory to make values meaningful. This can be useful for when clients
would like to forcibly override MC state in order to manipulate routing
results.
2022-01-25 17:43:18 -08:00
Olaoluwa Osuntokun
7d5841e95e Merge branch 'v0.14.2-beta-6159' into v0.14.2-branch-rc1 2022-01-25 17:42:51 -08:00
Olaoluwa Osuntokun
6476f1601c docs/release-notes: add entry for historical chan bucket check 2022-01-25 17:42:51 -08:00
Olaoluwa Osuntokun
1d16c44db9 contractcourt: catch error when no historical bucket exists
For older nodes, this bucket was never created, so we'll get an error if
we try and query it. In this commit, we catch this error like we do when
a given channel doesn't have the information (but the bucket actually
exists).

Fixes #6155
2022-01-25 17:42:51 -08:00
Olaoluwa Osuntokun
0a9153593c Merge branch 'v0.14.2-beta-6144' into v0.14.2-branch-rc1 2022-01-25 17:42:33 -08:00
Olaoluwa Osuntokun
8c284fd150 docs/release-notes: add entry for peer defer fix 2022-01-25 17:42:33 -08:00
Olaoluwa Osuntokun
785b4118f8 lnwire+peer: clamp pong bytes, make ping handler more effcieint
This was not properly enforced and would be a spec violation on the
peer's end. Also re-use a pong buffer to save on heap allocations if
there are a lot of peers. The pong buffer is only read from, so this
is concurrent safe.
2022-01-25 17:42:33 -08:00
Olaoluwa Osuntokun
f206992cfc peer: always defer clean up of the block epoch client used for ping headers
In this commit, we fix an inadvertent memory leak by ensuring we always
use `defer` to clean up the allocated objects/memory we use to be
notified of new blocks to update what we send within the set of ping
headers.

A further optimization here would be using a single global block epoch
housed within the server, that all peer `pingHandler` goroutines use
directly.

Fixes #6143.
2022-01-25 17:42:33 -08:00
Olaoluwa Osuntokun
b59470e351 Merge branch 'v0.14.2-beta-6146' into v0.14.2-branch-rc1 2022-01-25 17:42:18 -08:00
yyforyongyu
50bddcab38 docs: add release note for closing txid 2022-01-25 17:42:18 -08:00
yyforyongyu
981464846a rpcserver: add closing txid in WaitingCloseChannel 2022-01-25 17:42:18 -08:00
yyforyongyu
ea595cbee1 rpcserver: split PendingChannels into three sections
This commit refactors the method PendingChannels for maintenance
purpose.
2022-01-25 17:42:18 -08:00
Olaoluwa Osuntokun
ade8514afe Merge branch 'v0.14.2-beta-6140' into v0.14.2-branch-rc1 2022-01-25 17:41:56 -08:00
Joost Jager
384962c272 htlcswitch: fix duplicate close
The decayed log database opening and closing is managed at a higher
level in config_builder.go.
2022-01-25 17:41:56 -08:00
Olaoluwa Osuntokun
6b36326259 Merge branch 'v0.14.2-beta-6006' into v0.14.2-branch-rc1 2022-01-25 17:41:14 -08:00
Oliver Gugger
1052aabfeb docs: update remote signing doc and release notes 2022-01-25 17:41:02 -08:00
Oliver Gugger
b597690741 multi: add migrate-wallet-to-watch-only flag
To enable converting an existing wallet with private key material into a
watch-only wallet on first startup with remote signing enabled, we add a
new flag. Since the conversion is a destructive process, this shouldn't
happen automatically just because remote signing is enabled.
2022-01-25 17:40:15 -08:00
Oliver Gugger
52f313593e lnwallet: initialize first 255 accounts
This fixes lightninglabs/loop#437 by adding all accounts that are used
in liquidity products such as Loop or Pool. Since both of these products
use key families below 255, we can get by with that number.
The alternative to creating way too many accounts (which increases the
default wallet size by ~250kB) would be to hard code the exact accounts
used by Loop (99) and Pool (210). But that sounds like a bad idea given
that there could always be more accounts being added to those (or other)
products. By making sure the first 255 accounts exist, we have a lot
more flexibility in those products for choosing key families.
2022-01-25 17:40:15 -08:00
Oliver Gugger
cc7d5e57eb multi: add nochainbackend option 2022-01-25 17:40:15 -08:00
Oliver Gugger
c538d3d307 multi: add health check for remote signer 2022-01-25 17:40:15 -08:00
Oliver Gugger
cd2012719b multi: make remote signer RPC timeout configurable 2022-01-25 17:40:15 -08:00
Oliver Gugger
a34ac85c50 rpcwallet: add critical log to remote signer errors 2022-01-25 17:40:15 -08:00
Oliver Gugger
0a2e56245f config_builder+rpcwallet: simplify RPC signing
With the remote signing instance now not needing to know anything about
addresses or current derivation indices, we don't need to forward any
such calls to that instance and can simplify the RPCKeyRing
considerably.
2022-01-25 17:40:15 -08:00
Oliver Gugger
248c6fc723 walletrpc+itest: add SignPsbt RPC 2022-01-25 17:40:15 -08:00
Oliver Gugger
d868ca3e34 btcwallet: add SignPsbt 2022-01-25 17:40:15 -08:00
Oliver Gugger
286e3742f6 lnd+lnwallet: add logger for btcwallet+rpcwallet 2022-01-25 17:40:15 -08:00
Oliver Gugger
6602efde63 lnwallet: add derivation and prev TX to UTXO 2022-01-25 17:40:15 -08:00
Oliver Gugger
9a54f273c2 btcwallet: add method for deriving key from BIP32 path 2022-01-25 17:40:15 -08:00
Oliver Gugger
5b331cfe27 btcwallet: move PSBT related methods to own file
This is a pure code move commit to extract the FundPsbt and FinalizePsbt
methods into their own file.
2022-01-25 17:40:15 -08:00
Oliver Gugger
5176a2c8d0 lnwallet+lntest+mod: bump btcwallet to export ScriptForOutput 2022-01-25 17:40:15 -08:00
Oliver Gugger
e3e21745d3 signrpc: remove incomplete sentence and TODO
We use SignOutputRaw which expects a witness script being set, even for
P2WKH. There is a special case in SignOutputRaw for the case where the
script is a p2wkh script, then the input script is reconstructed
correctly for the sighash.
2022-01-25 17:40:15 -08:00
Oliver Gugger
a6e931ed5b multi: fix formatting 2022-01-25 17:40:15 -08:00
Olaoluwa Osuntokun
d3714376d2 Merge branch 'v0.14.2-beta-6139' into v0.14.2-branch-rc1 2022-01-25 17:39:05 -08:00
Oliver Gugger
c505c5f946 docs: add release notes 2022-01-25 17:39:05 -08:00
Oliver Gugger
e5f62a0349 lntest: export base node config for re-use 2022-01-25 17:39:05 -08:00
Oliver Gugger
5f5f8573e1 lntest: export ListenerFormat constant 2022-01-25 17:39:05 -08:00
Oliver Gugger
3e99fea7bc lntest: fix colliding variable name
The variable name "bytes" collides with an imported package name, so we
rename it to avoid shadowing.
2022-01-25 17:39:05 -08:00
Olaoluwa Osuntokun
777d2f2f22 Merge branch 'v0.14.2-beta-6052' into v0.14.2-branch-rc1 2022-01-25 17:38:35 -08:00
Oliver Gugger
170684a170 itest: fix RPC middleware itest 2022-01-25 17:38:35 -08:00
yyforyongyu
beb1f06d9f itest: start using harness miner in harness net
This commit replaces the old miner with the new HarnessMiner and cleans
harness_node.go by moving methods into the test_common.go.
2022-01-25 17:38:35 -08:00
yyforyongyu
bc1d70a184 itest: introduce harness miner
This commit adds a new component, harness miner, to the itest. This
newly added component is responsible for checking the mempool and blocks
for the itest.
2022-01-25 17:38:35 -08:00
yyforyongyu
5a17ec3b65 itest: refactor initClientWhenReady to clean up init node 2022-01-25 17:38:35 -08:00
yyforyongyu
880d977346 itest: add method waitTillServerState in harness node 2022-01-25 17:38:35 -08:00
yyforyongyu
5b69e2c626 itest: use node.rpc namespace inside harness net
This commit adds a new struct RPCClients to better handle rpc clients.
A private field, rpc, is added to HarnessNode to prevent direct access
to its clients. Inside RPCClients, all clients are exported in case a
test case need access to a specific client.
2022-01-25 17:38:35 -08:00
yyforyongyu
e6df1522a7 itest: shorten functions inside harness node
This commit refactors the long function start() into smaller pieces and
moves commonly used functions into test_common.go.
2022-01-25 17:38:35 -08:00
Olaoluwa Osuntokun
0ae6c5dcf6 Merge branch 'v0.14.2-beta-5756' into v0.14.2-branch-rc1 2022-01-25 17:33:59 -08:00
yyforyongyu
0db1b7ec11 docs: update release note for itest ctxt fix 2022-01-25 17:33:45 -08:00
yyforyongyu
ea1fec84be makefile: add itest-clean to kill uncleaned processes 2022-01-25 17:32:36 -08:00
yyforyongyu
837569875e itest: replace fakeLogger with v2 logger with Discard 2022-01-25 17:32:36 -08:00
yyforyongyu
1fe306e21c itest: use run context when making rpc requests 2022-01-25 17:32:36 -08:00
yyforyongyu
360638879b itest: rename harness net file and add run context
This commit renames harness.go to harness_net.go. It also adds a run
context which is served as the parent context when creating new
contexts.
2022-01-25 17:32:36 -08:00
yyforyongyu
3000a691e5 itest: manage context within HarnessNode
This commit removes the context as a param needed when calling methods
of HarnessNode. This change moves the context management inside
HarnessNode, aside from saving us a few lines, it makes the context
creation/timeout less error-prone.
2022-01-25 17:32:36 -08:00
yyforyongyu
16526e40a8 itest: use ProcessState and runCtx to control process quit 2022-01-25 17:32:36 -08:00
yyforyongyu
4275e74cd3 itest: add run context to harness node
This commit adds a running context to HarnessNode which replaces all the
background context used and also serves as a way to signal quit when the
test is shutting down.
2022-01-25 17:32:36 -08:00
yyforyongyu
fd92c738e9 itest: add test_common to hold commonly used methods
A new file, test_common.go, is added to hold commonly used functions
across lntest.
2022-01-25 17:32:36 -08:00
Olaoluwa Osuntokun
c2fa9ff229 Merge branch 'v0.14.2-beta-6054' into v0.14.2-branch-rc1 2022-01-25 17:30:17 -08:00
yyforyongyu
8c92e029eb docs: add release note for premature msg fix 2022-01-25 17:28:10 -08:00
eugene
137fe297a6 discovery: use source instead of peer for accurate rejectCache 2022-01-25 17:26:45 -08:00
yyforyongyu
e07ab7aea6 discovery: resend premature messages when new blocks arrive
This commit adds a method to resend premature when new blocks arrive.
Previously when a message has specified a block+delta in the future, we
would ignore the message and never process it again, causing an open
channel never being broadcast under fast blocks generation. This commit
fixes it by saving the future messages and resending them once the
required block height is reached.
2022-01-25 17:26:45 -08:00
yyforyongyu
4f1905cea1 discovery: sync blocks in a dedicated goroutine
This commit moves syncing blocks into a dedicated goroutine to avoid the
race condition where several go channels are ready and the block height
update is pushed after a network message is processed.
2022-01-25 17:26:45 -08:00
yyforyongyu
bbc16ae30f routing+discovery: uniform error codes in routing 2022-01-25 17:26:45 -08:00
yyforyongyu
c808d27fef discovery: transit all inactive syncers when needed 2022-01-25 17:26:45 -08:00
yyforyongyu
c48db1ebeb discovery: shorten mutex locking closure 2022-01-25 17:26:45 -08:00
yyforyongyu
9b51237607 funding: add explicit log to avoid confusion 2022-01-25 17:26:45 -08:00
yyforyongyu
bad0db11b8 funding: add String method for channelOpeningState
The newly added String method can be helpful in reading logs.
2022-01-25 17:26:45 -08:00
yyforyongyu
3d0bd75947 chainntnfs: add more verbose logs for txnotifier 2022-01-25 17:26:45 -08:00
yyforyongyu
92cda1a358 discovery: add verbose network messages related logs 2022-01-25 17:26:45 -08:00
Olaoluwa Osuntokun
eb5f6d5d92 Merge branch 'v0.14.2-beta-6116' into v0.14.2-branch-rc1 2022-01-25 17:25:27 -08:00
Joost Jager
7845fe0bba itest: increase pg database connection limit 2022-01-25 17:25:14 -08:00
yyforyongyu
e39fbcef11 docs: add release note for peer conn fix 2022-01-25 17:23:18 -08:00
yyforyongyu
fc7b5f8b5f server: fix peers not ignored during bootstrapping
This commit fixes the issue where duplicate peers are used both in
making persistent connections and bootstrap connections. When we init
bootstrapping, we need to ignore peers that have connections already
made so far plus peers which we are attempting to make connections with,
hence the persistent peers.
2022-01-25 17:21:40 -08:00
yyforyongyu
a4e87fd2de multi: enhance logging for debugging peer connection 2022-01-25 17:21:40 -08:00
Olaoluwa Osuntokun
c8ba5e2ca3 Merge branch 'v0.14.2-beta-6108' into 0-14-2-branch-rc1 2022-01-25 17:17:48 -08:00
Joost Jager
dc0b0e9b38 kvdb/postgres: fix context cancellation 2022-01-25 17:17:48 -08:00
Joost Jager
94def4508e kvdb/postgres: fix tests 2022-01-25 17:17:48 -08:00
Olaoluwa Osuntokun
9f53786bdb docs/release-notes: add entry for chan type fix 2022-01-25 17:16:12 -08:00
Olaoluwa Osuntokun
ba46b98c3c funding: always send a channel type in explicit mode
In this commit, we switch to always sending a channel type when we're in
explicit mode. This is compatible with prior versions of lnd as they
won't send a channel type, and we'll just arrive at the same type via
the existing implicit funding.

Fixes https://github.com/lightningnetwork/lnd/issues/6067
2022-01-25 17:16:12 -08:00
Matthew Bajorek
9d399d412a docs: update release note for #6073 [skip ci] 2022-01-25 17:14:13 -08:00
Matthew Bajorek
3e3de70a7a netann: clarify invalid config timeout constraints [skip ci] 2022-01-25 17:13:52 -08:00
Elle Mouton
e8002dd536 lnwallet+docs: minrelayfee always above fee floor
The minimum relay fee is always ensured to be above our fee floor except
in the very first min relay fee query to bitcoind. This commit ensures
that the fee floor is respected in this first query.
2022-01-25 17:11:56 -08:00
Bjarne Magnussen
c8173b60b3 add to release notes 0.14.2 2022-01-25 17:08:34 -08:00
Bjarne Magnussen
f06aecc5da lnrpc: refactor populating lnrpc.Transaction inside SubscribeTransaction 2022-01-25 17:07:48 -08:00
Martin Habovstiak
a5471576ea docs: added release notes regarding #5539 2022-01-25 17:06:32 -08:00
Martin Habovstiak
6678f25ca0 test: don't enforce reserved value in PSBT midstep
This adds an integration test that makes sure channel can be funded from
empty wallet using PSBT if the funding transaction contains an output
belonging to the wallet, satisfying the reserve.
2022-01-25 17:06:32 -08:00
Martin Habovstiak
1b9a126809 lnwallet: don't enforce new reserved value in PSBT midstep
This change avoids enforcing new reserved value when PSBT funding is not
finished yet as new inputs and outputs may still be added that could
change the outcome of the check.

This originally failed in the scenario when funding a channel from
external wallet *and depositing to on-chain wallet* was done
simultaneously in a single transaction. If such transaction confirms
then reserved UTXO is guaranteed to be available but the check didn't
take it into account.

The enforcement still occurs in the final step of PSBT funding flow, so
it is safe. It also occurs in case of non-PSBT funding.
2022-01-25 17:06:32 -08:00
Matthew Bajorek
ad8fc3ceb7 lncli: Add json flag to trackpayment [skip ci] 2022-01-25 17:03:39 -08:00
Olaoluwa Osuntokun
2bdb8e3b62 Merge branch 'v0.14.2-beta-5971' into 0-14-2-branch-rc1 2022-01-25 17:02:16 -08:00
yyforyongyu
acbc11fd40 docs: add release note for ChanStatusFlags 2022-01-25 17:02:16 -08:00
yyforyongyu
b227d72067 rpcserver: expose ChanStatusFlags in pending close
This commit exposes the ChanStatusFlags inside waitingCloseResp such
that the channel close type is exposed.
2022-01-25 17:02:16 -08:00
Andras Banki-Horvath
9c0d2cf208 docs: update release notes 2022-01-25 17:01:13 -08:00
Andras Banki-Horvath
36d98a9b3d routing: fix memory corruption in MC store
Since bbolt returns references to internally stored data when storing
locally it's best to copy the byte slices returned or alternatively
convert them to string (which also makes a copy) to avoid crashes casued
by memory corruption.
2022-01-25 16:59:22 -08:00
Olaoluwa Osuntokun
24a033900a Merge branch 'v0.14.2-beta-6062' into 0-14-2-branch-rc1 2022-01-25 16:59:00 -08:00
yyforyongyu
9c81108de2 docs: update release note for fee rate fix 2022-01-25 16:59:00 -08:00
yyforyongyu
361b8a9691 chainfee: update test TestWebAPIFeeEstimator 2022-01-25 16:59:00 -08:00
yyforyongyu
a9bb51a788 chainfee: handle conf target not found in cache 2022-01-25 16:59:00 -08:00
Olaoluwa Osuntokun
3fb9cbc032 Merge branch 'v0.14.2-beta-6071' into 0-14-2-branch-rc1 2022-01-25 16:57:57 -08:00
kon
e179d3f0e4 routerrpc: fix wrong error messages
when payment_hash or final_cltv_delta and payment_request was set, the error message showed that the parameters shouldn't be set with dest instead of payment_request

[skip ci]
2022-01-25 16:57:57 -08:00
Olaoluwa Osuntokun
f02f230ba9 Merge branch 'v0.14.2-beta-6049' into 0-14-2-branch-rc1 2022-01-25 16:57:18 -08:00
Andras Banki-Horvath
508a3714aa docs: update release notes 2022-01-25 16:57:18 -08:00
Andras Banki-Horvath
2a4b3fe354 etcd: make max message size configurable 2022-01-25 16:57:18 -08:00
Olaoluwa Osuntokun
4062003c91 Merge branch 'v0.14.2-beta-6035' into 0-14-2-branch-rc1 2022-01-25 16:56:54 -08:00
naveen
f99cf4f7cb multi: Remove GO111MODULE env variable in Makefile
The `GO111MODULE` variable is not required from go 1.16
https://go.dev/blog/go116-module-changes
2022-01-25 16:56:54 -08:00
Oliver Gugger
f12f40dfcb mod+tools+Makefile: use go install to fetch dependencies
Instead of hard coding a commit to use for a binary tool that we use
during the build process, we now only use "go install" to install the
binaries and the golang builtin versioning system to pin the exact
version/commit we want to use in go.mod.
2022-01-25 16:56:54 -08:00
Oliver Gugger
e9e580ee1a GitHub+Makefile: remove travis goals 2022-01-25 16:56:54 -08:00
Oliver Gugger
43507e969c docs+Makefile: remove goveralls
We use a GitHub Action for sending the coverage to coveralls.io and
don't need the goveralls binary anymore.
2022-01-25 16:56:54 -08:00
rockstardev
b767e1c7ae
Reverting changes picked up from feature branches
These changes haven't made it into master on lightning/lnd
2021-12-22 20:58:31 -06:00
rockstardev
e2ddfde44e
Cleaning up README, adding new versions 2021-12-22 19:51:11 -06:00
rockstardev
a08ce6fdb7
Merge branch 'version/0.14.1-beta' 2021-12-22 19:40:35 -06:00
rockstardev
177d04ecaa
Merge branch 'version/0.14.0-beta'
# Conflicts:
#	.github/pull_request_template.md
#	README.md
#	build/version.go
#	chainreg/chainregistry.go
#	cmd/lncli/cmd_payments.go
#	docs/release-notes/release-notes-0.13.3.md
#	docs/release-notes/release-notes-0.14.0.md
#	go.mod
#	go.sum
#	htlcswitch/interfaces.go
#	htlcswitch/switch.go
#	htlcswitch/switch_test.go
#	lntest/itest/lnd_test.go
#	lnwallet/test_utils.go
2021-12-22 19:40:23 -06:00
rockstardev
bfda9ea312
Merge branch 'version/0.13.3-beta'
# Conflicts:
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
2021-12-22 19:38:40 -06:00
rockstardev
94693c31b7
Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
(cherry picked from commit a185998bcf)
2021-11-25 14:10:40 +09:00
rockstardev
b9f43ac43e
Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
(cherry picked from commit a185998bcf)
2021-11-20 21:39:49 +09:00
rockstardev
67907c415e
Bumping loop to v0.15.0-beta 2021-10-09 12:34:34 -05:00
rockstardev
820c830ae1
Updating docker images to compile for new version of GoLang 2021-10-09 12:33:26 -05:00
rockstardev
83b7c64b76
Merge branch 'version/0.13.1-beta'
# Conflicts:
#	.github/workflows/main.yml
#	.github/workflows/release.yaml
#	.travis.yml
#	Makefile
#	channeldb/channel.go
#	channeldb/channel_test.go
#	cmd/lncli/cmd_pay.go
#	config.go
#	contractcourt/briefcase_test.go
#	discovery/gossiper.go
#	discovery/gossiper_test.go
#	docker-initunlocklnd.sh
#	docs/release.md
#	invoices/invoice_expiry_watcher_test.go
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
#	lncfg/gossip.go
#	lnrpc/Dockerfile
#	lnrpc/gen_protos.sh
#	lnrpc/gen_protos_docker.sh
#	lnrpc/invoicesrpc/invoices_server.go
#	lnrpc/routerrpc/router.pb.go
#	lnrpc/routerrpc/router.proto
#	lnrpc/routerrpc/router.swagger.json
#	lnrpc/routerrpc/router_backend.go
#	lnrpc/rpc.pb.go
#	lntest/itest/lnd_test.go
#	lntest/itest/log_error_whitelist.txt
#	routing/integrated_routing_context_test.go
#	routing/payment_session.go
#	routing/router.go
#	routing/router_test.go
#	rpcserver.go
#	sample-lnd.conf
#	scripts/verify-install.sh
#	server.go
2021-10-09 12:22:29 -05:00
rockstardev
25c56c4974
Commenting script to preserve information about tricky unlocking mechanism 2021-10-09 11:33:26 -05:00
rockstardev
22937c97f1
Improving unlock script to wait for proper state when it comes to wallet unlocking 2021-10-09 11:33:20 -05:00
rockstardev
9f60321b89
Installing xxd on arm32 and arm64 2021-10-09 11:33:13 -05:00
rockstardev
787ab54072
Updating init http error code condition with lnd-0.13.1-beta 2021-10-09 11:32:48 -05:00
rockstardev
9a8f64c512
Adding loop binary in lnd container 2021-10-09 11:32:41 -05:00
rockstardev
2fa461271b
Adding environment variable to influence LND's rest host
(cherry picked from commit 39d25171ce)
(cherry picked from commit 7b6c31d223)
2021-10-09 11:31:03 -05:00
rockstardev
e32d15659b
Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
(cherry picked from commit a185998bcf)
2021-10-09 11:30:47 -05:00
Oliver Gugger
4f567577db
build: bump version to v0.13.3-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2021-10-04 16:07:22 +02:00
Olaoluwa Osuntokun
186b6cce2b
build: bump version to v0.13.3-beta.rc2
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2021-10-03 12:22:04 -07:00
Olaoluwa Osuntokun
ab8d342cad multi: fix cherry-pick compilation issues 2021-10-03 12:21:16 -07:00
Oliver Gugger
6e519ca910 scripts: verify version in manifest
To make a downgrade attack harder, we also check that the version string
is contained in the manifest, on the same line as the hash.
2021-10-03 12:18:27 -07:00
Oliver Gugger
4569ed424d scripts: allow packaged release archive to be verified
Instead of only allowing to verify installed/unpacked binaries, we also
allow a single binary or packaged release archive to be verified.
2021-10-03 12:16:40 -07:00
Oliver Gugger
c97040b77e docker: add keys to docker image
Because the PGP keys are no longer downloaded from Keybase but are used
from the repo directly, we also have to copy them to the Docker image so
we can run the script without needing to supply them through a volume.
2021-10-03 12:16:40 -07:00
Oliver Gugger
53899b3fd4 scripts: pin signatures to keys
With this commit we add a new restriction that checks that the
username in the signature file (manifest-<username>-<version>.sig) actually
does have a signing key and that the signature was created with that key.
The signature is only counted towards the minimum of 5 signatures if
that check is successful.
The changes in this commit were inspired by @kixunil in #5048.
2021-10-03 12:16:40 -07:00
Oliver Gugger
50b7748f2c scripts: make sure signature files have unique names
To fix a simple attack where the same file would be uploaded multiple
times under the same name, we make sure we only count unique file names.
2021-10-03 12:16:40 -07:00
positiveblue
6d1fa7d84a scripts: add positiveblue key to verify script 2021-10-03 12:16:40 -07:00
Oliver Gugger
fca4058f2e scripts: add signing keys to repo
Instead of importing the keys from Keybase, we add all the signing keys
to the repository. In addition to having the key file present each key's
ID must also be added to the verification script. This acts as a double
check that the correct key is added and makes a key change more
explicit.
2021-10-03 12:16:40 -07:00
Conner Fromknecht
13bc2eee66 docs: update release verification scripts for v0.12.1-beta 2021-10-03 12:16:40 -07:00
Conner Fromknecht
cda414c84d docs: remove unnecessary docker pull from release verification
Docker will automatically pull the image if it isn't found locally.
2021-10-03 12:16:40 -07:00
Conner Fromknecht
a8bb570a19 scripts/verify-install.sh: pass expected version as argument
This removes a vulnerability brought up by @Kixunil where both the lnd
and lncli binaries are executed to obtain their version before they have
been verified against the release. A malicious binary could have already
compromised the user's system before any of the checks had been
performed.

This commit it split out from the doc changes so that it can easily be
cherry-picked to master/0.13.0.
2021-10-03 12:16:40 -07:00
Oliver Gugger
fb8a841d3e scripts: extract functions
As a preparation to make the script easier to understand, we extract
some of the sub tasks into functions.
2021-10-03 12:16:40 -07:00
Harsha Goli
29a6b101fd scripts: add arshbot key to verify script 2021-10-03 12:16:40 -07:00
Olaoluwa Osuntokun
0342c8b33c
build: bump version to v0.13.3-beta.rc1 2021-10-03 11:52:39 -07:00
eugene
2f68e95013 docs: update release notes for 0.13.3 2021-10-03 11:30:53 -07:00
eugene
0e3d06a562 multi: introduce config-level DustThreshold for defining threshold 2021-10-03 11:30:53 -07:00
eugene
072bde093c htlcswitch: call evaluateDustThreshold in SendHTLC, handlePacketForward
This commit makes SendHTLC (we are the source) evaluate the dust
threshold of the outgoing channel against the default threshold of
500K satoshis. If the threshold is exceeded by adding this HTLC, we
fail backwards. It also makes handlePacketForward (we are forwarding)
evaluate the dust threshold of the incoming channel and the outgoing
channel and fails backwards if either channel's dust sum exceeds the
default threshold.
2021-10-03 11:30:52 -07:00
eugene
16d59544ea htlcswitch: extend ChannelLink iface with dustHandler iface
This allows the Switch to determine the dust exposure of a certain
channel and allows the link to set the feerate of the mailbox given
a fee update.
2021-10-03 11:29:44 -07:00
eugene
4558381ffa htlcswitch: extend Mailbox iface with dust, fee methods
This commit extends the Mailbox interface with the SetDustClosure,
SetFeeRate, and DustPackets methods. This enables the mailbox to
report the dust exposure to the Switch when the Switch decides whether
to forward a dust packet. The dust is counted from the time an Add is
introduced via AddPacket until it is removed via AckPacket. This can
lead to some packets being counted twice before they are signed for,
but this is a trade-off between accuracy and simplicity.
2021-10-03 11:28:39 -07:00
eugene
1fc413e2f6 lnwallet: introduce GetDustSum method to calculate worst-case dust sum
It over-estimates the local or remote commitment's dust sum by
counting all updates in both updateLogs that are dust using the
trimmed-to-dust mechanism if applicable. The over-estimation is done
because ensuring an accurate counting is a trade-off between code
simplicity and accuracy.
2021-10-03 11:28:38 -07:00
eugene
c6fe623061 docs: update release notes for 0.13.3 2021-10-03 11:25:05 -07:00
eugene
655778d80d funding+lnwallet: validate ChannelReserve is above DustLimit
This is necessary and is implied by BOLT#02. Both ChannelReserve
parameters should be above both DustLimit parameters. Otherwise,
it is possible for one side to have nothing at stake.
2021-10-03 11:25:05 -07:00
eugene
ddbd0b672a multi: replace DefaultDustLimit with script-specific DustLimitForSize
This commit updates call-sites to use the proper dust limits for
various script types. This also updates the default dust limit used
in the funding flow to be 354 satoshis instead of 573 satoshis.
2021-10-03 11:25:02 -07:00
Olaoluwa Osuntokun
86d3dec7b9
build: bump version to v0.13.2-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2021-08-18 17:42:48 -07:00
Olaoluwa Osuntokun
ef70a92e49 Merge branch 'v0.13.2-beta-5554' into 0-13-2-branch 2021-08-18 17:37:07 -07:00
Olaoluwa Osuntokun
fed9c1cd8d docs/release-notes: add item for easy AMP CLI re-use 2021-08-18 17:37:07 -07:00
Olaoluwa Osuntokun
eac3f8ea1f docs/release-notes: add item for sendpayment pay_addr bug fix 2021-08-18 17:37:07 -07:00
Olaoluwa Osuntokun
6057200c72 cmd/lncli: add new option for easy AMP invoice re-use
In this commit, we add a new option (`--amp-reuse`) that allows for easy
AMP invoice re-use when using either the `sendpayment` command.
2021-08-18 17:37:07 -07:00
Olaoluwa Osuntokun
683f6f3b2e cmd/lncli: always parse the pay_addr field for sendpayment
In this commit, we fix a bug that would cause attempts to re-use an AMP
invoice to fail. Without this commit, we would only attempt to parse the
payment addr if no invoice was specified, so a user manually specifying the
pubkey of the detonation. The fix is straight forward: always parse the
`pay_addr` field as the user may be attempting to re-use an AMP invoice w/o
open coding each of the sections.
2021-08-18 17:37:07 -07:00
rockstardev
dec49aa15b
Commenting script to preserve information about tricky unlocking mechanism 2021-08-12 22:28:28 -05:00
rockstardev
824a998274
Improving unlock script to wait for proper state when it comes to wallet unlocking 2021-08-12 21:38:32 -05:00
rockstardev
570bc0824f
Installing xxd on arm32 and arm64 2021-08-12 20:54:51 -05:00
rockstardev
6baa0ee593
Updating init http error code condition with lnd-0.13.1-beta 2021-08-01 01:27:12 +02:00
rockstardev
025f953f6f
Adding loop binary in lnd container 2021-08-01 01:26:42 +02:00
rockstardev
f0714bf36e
Adding environment variable to influence LND's rest host
(cherry picked from commit 39d25171ce)
(cherry picked from commit 7b6c31d223)
2021-08-01 00:36:40 +02:00
rockstardev
ae1b824e4b
Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
(cherry picked from commit a185998bcf)
2021-08-01 00:36:27 +02:00
rockstardev
c49af2288c
Merge branch 'version/0.12.1-beta'
# Conflicts:
#	.github/workflows/docker.yml
#	.github/workflows/main.yml
#	.github/workflows/release.yaml
#	docker-entrypoint.sh
#	docker-initunlocklnd.sh
#	linuxamd64.Dockerfile
#	linuxarm32v7.Dockerfile
#	linuxarm64v8.Dockerfile
#	lncfg/address.go
2021-07-31 23:29:04 +02:00
Olaoluwa Osuntokun
596fd90ef3
build: bump version to v0.13.1-beta
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2021-07-19 11:02:54 -07:00
Olaoluwa Osuntokun
db577b23b4 Merge branch 'v0.13.1-beta-5472' into 0-13-1-branch 2021-07-19 11:01:07 -07:00
Joost Jager
2b49c4d344 build: bump btcwallet 2021-07-19 11:01:07 -07:00
Olaoluwa Osuntokun
17b0461583
build: bump version to v0.13.1-beta.rc2
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
2021-07-07 16:12:41 -07:00
rockstardev
7d676848cb
Extracting running Loop to separate script 2021-05-23 12:45:54 -05:00
rockstardev
a1c04622d3
Letting old condition continue in order for Loop to be started 2021-05-19 08:44:39 -05:00
rockstardev
8187303ada
Updating loop to 0.12.2-beta 2021-05-12 23:04:12 -05:00
rockstardev
78d5af59ee
Loop listener has problems if immidatelly starter, increasing wait time 2021-04-22 23:26:56 -05:00
rockstardev
3b3c52f1e7 Lnd doesn't listen on localhost, so we need to pass in host 2021-03-21 19:17:47 -05:00
rockstardev
b4ac312d2e Updating path to MACAROON_FILE 2021-03-21 13:23:08 -05:00
rockstardev
7e82d9a451 Adding loop to arm32v7 and arm64v8 images 2021-03-21 11:54:22 -05:00
rockstardev
e0089475f7 Consolidating string in logger to match sh name 2021-03-21 11:40:52 -05:00
rockstardev
ae99043041 Adding loop binary in lnd container 2021-03-21 11:36:45 -05:00
rockstardev
c7f4e0c306 Adding environment variable to influence LND's rest host
(cherry picked from commit 39d25171ce)
(cherry picked from commit 7b6c31d223)
2021-03-14 10:31:08 -05:00
rockstardev
5b63dc1f67 Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
(cherry picked from commit a185998bcf)
2021-03-14 10:30:59 -05:00
Conner Fromknecht
d233f61383
Merge pull request #5052 from cfromknecht/v0.12.1-beta.rc7-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc7
2021-02-22 16:55:05 -08:00
Conner Fromknecht
51aaf2bb13
build/version: bump to v0.12.1-beta.rc7 2021-02-22 12:23:16 -08:00
Conner Fromknecht
923134e52c
docs: update release verification scripts for v0.12.1-beta 2021-02-22 12:22:03 -08:00
Conner Fromknecht
a38c82d8c7
docs: remove unnecessary docker pull from release verification
Docker will automatically pull the image if it isn't found locally.
2021-02-22 12:19:43 -08:00
Conner Fromknecht
3ae60cd63f
scripts/verify-install.sh: pass expected version as argument
This removes a vulnerability brought up by @Kixunil where both the lnd
and lncli binaries are executed to obtain their version before they have
been verified against the release. A malicious binary could have already
compromised the user's system before any of the checks had been
performed.

This commit it split out from the doc changes so that it can easily be
cherry-picked to master/0.13.0.
2021-02-22 12:18:43 -08:00
Conner Fromknecht
953e3cc50d
Merge pull request #5045 from cfromknecht/v0.12.1-beta.rc6-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc6
2021-02-18 17:03:01 -08:00
Conner Fromknecht
7bfec3f8c2
build/version: bump to v0.12.1-beta.rc6 2021-02-18 11:47:56 -08:00
Conner Fromknecht
5fd74659bc
routing: avoid modifying AssumeChannelValid in unit tests
This produces a race condition when reading AssumeChannelValid from a
different goroutine. Instead we isolate the test cases and initial
AssumeChannelValid properly.
2021-02-18 08:52:35 -08:00
Conner Fromknecht
f1786f9454
routing: dial back max concurrent block fetches
This commit reduces the number of concurrent validation operations the
router will perform when fully validating the channel graph. Reports
from several users indicate that GetInfo would hang for several minutes,
which is believed to be caused by attempting to validate massive amounts
of channels in parallel. This commit returns the limit back to its
original state before adding the batched gossip improvements.

We keep the 1000 concurrent validation request limit for
AssumeChannelValid, since we don't fetch blocks in that case. This
allows us to still keep the performance benefits on mobile/low-resource
devices.
2021-02-18 08:52:34 -08:00
Conner Fromknecht
5cddeb7449
Merge pull request #5039 from cfromknecht/v0.12.1-beta.rc5-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc5
2021-02-17 12:58:23 -08:00
Conner Fromknecht
1f012c461e
build/version: bump to v0.12.1-beta.rc5 2021-02-17 12:15:59 -08:00
Conner Fromknecht
64660a2574
Revert "lnrpc/routerrpc: use new default value of 16 for maxparts"
This reverts commit 25b90832e3d74e62176a9c71b0b724d6fb49a39d, as
well as reverting some changes in other commits in the PR that weren't
fully attomic with the primary commit.
2021-02-17 12:15:58 -08:00
Conner Fromknecht
5643fe8dbe
github: check-each-commit from v0.12.0-beta 2021-02-17 12:15:58 -08:00
Oliver Gugger
1ed3c340e8
scripts: detect whether sha256sum or shasum is available
The shasum command isn't available in Alpine linux while the sha256sum
command isn't available on MacOS. We add a simple switch that tries to
detect which one is available.
2021-02-17 12:01:21 -08:00
Oliver Gugger
877fd96e8c
make: use make for docker-release
To fix an issue where the golang version would be picked up from the
host system if the docker-release command was used, we switch over to
using make inside of the container as well instead of feeding the
parameters into the release script manually.
We only pass in the flags that we might actually want to overwrite.
2021-02-17 12:01:18 -08:00
Conner Fromknecht
d6c697d509
Merge pull request #5027 from cfromknecht/v0.12.1-beta.rc4-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc4
2021-02-16 16:34:09 -08:00
Conner Fromknecht
d51f61af25
build/version: bump to v0.12.1-beta.rc4 2021-02-16 13:58:33 -08:00
Olaoluwa Osuntokun
2f4de5dc5f
cmd/lncli: add max shard size parsing for payment commands 2021-02-16 10:12:27 -08:00
Olaoluwa Osuntokun
be54ac78a6
routing: if MaxShardAmt is set, then use that as a ceiling for our splits
In this commit, we thread through the necessary state to allow users to
set a max shard amount. If this value is set, then this'll effectively
serve as a ceiling for all our split attempts. If we need to split,
we'll first try to use `paymentAmt/2`, if that's bigger than
`MaxShardAmt, then we'll use the latter instead.

Ideally in the future we have a dynamic way to automatically set both
the `MaxShardAmt` as well as `MaxParts` for users. Until then exposing
these two new fields will allow us to experiment with setting them
automatically using the RPC interface, and also give users a bit more
control over how we attempt to route payments, akin to coin control for
on-chain payments.

Fixes #4730
2021-02-16 10:12:26 -08:00
Olaoluwa Osuntokun
3a4b44a480
lnrpc/routerrpc+routing: add new MaxShardAmt field to LightningPayment 2021-02-16 10:12:26 -08:00
Olaoluwa Osuntokun
59764d7b04
lnrpc/routerrpc: add new max_shard_size_msat field to SendPaymentRequest 2021-02-16 10:12:25 -08:00
Olaoluwa Osuntokun
d29528bb69
lnrpc/routerrpc: use new default value of 16 for maxparts
In this commit, we raise the default value for the `MaxParts` field from
1 to 16. This change was motivated by the fact that many users either
forget, or don't even know this field is there in the first place. A
value of 16 was chosen rather arbitraliy (other than power of 2). In
the future, we should tune this value based on the expected number of
payment attempts for a given payment amount.
2021-02-16 10:12:01 -08:00
Conner Fromknecht
87a3aad001
htlcswitch: init mockFeeEstimator in other LinkChannelConfigs
If the tests don't execute quick enough, the link will try to sample the
network fee and cause a panic. This happens semi-regularly on travis.
2021-02-15 13:17:34 -08:00
Conner Fromknecht
6236c5b620
lntest: add Block height out of range to whitelist 2021-02-15 13:17:04 -08:00
Conner Fromknecht
5fe7d19e6a
lntest: add unable to extract ChannelUpdate to whitelist 2021-02-15 13:17:04 -08:00
Conner Fromknecht
48caa962cb
scripts/verify-install.sh: combine final SUCCESS logs 2021-02-15 13:16:51 -08:00
Conner Fromknecht
87dfb04f1e
scripts/verify-install: bump min required signatures to 5 2021-02-15 13:16:51 -08:00
Oliver Gugger
7027e940ef
scripts: add more verbose error messages to verification
We want to be more precise in what exactly went wrong and what the cause
could be.
2021-02-15 13:16:51 -08:00
Oliver Gugger
34c2d77ec5
docs+scripts: switch to detached signatures
Due to a misunderstanding of how the gpg command line options work, we
didn't actually create detached signatures because the --clear-sign
flag would overwrite that. We update our verification script to now only
download the detached signatures and verify them against the main
manifest file.
We also update the signing instructions.
2021-02-15 13:16:51 -08:00
Oliver Gugger
cdea598a30
scripts: verify hash length
To make sure we've actually calculated the hash correctly, we make sure
it's 64 characters long.
2021-02-15 13:16:51 -08:00
Oliver Gugger
00dc248baa
scripts: use shasum instead of sha256sum
Because the sha256sum binary isn't available on MacOS we instead use the
shasum -a 256 command that was used before.
2021-02-15 13:16:51 -08:00
Oliver Gugger
547181d36f
config: clean and expand backup file path
Because the CleanAndExpandPath function wasn't applied to the backup
file path, any path that contained a tilde for the home directory didn't
work.
2021-02-15 13:16:10 -08:00
Oliver Gugger
7627c619a1
scripts: allow verification of custom binary
Instead of only allowing the installed versions of lnd and lncli to be
verified, we now also support specifying explicit paths to binaries that
we want to verify.
2021-02-15 13:15:56 -08:00
Conner Fromknecht
de8dbe2c74
Merge pull request #5014 from cfromknecht/v0.12.1-beta.rc3-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc3
2021-02-11 18:01:09 -08:00
Conner Fromknecht
4ca83c3bc1
build/version: bump to v0.12.1-beta.rc3 2021-02-11 16:35:18 -08:00
Conner Fromknecht
cb6e677400
github/workflows: pin exact docker release 2021-02-11 16:32:50 -08:00
Conner Fromknecht
ea2b0150c6
Merge pull request #5009 from cfromknecht/v0.12.1-beta.rc2-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc2
2021-02-11 12:57:02 -08:00
Conner Fromknecht
1e2190e86d
build/version: bump to v0.12.1-beta.rc2 2021-02-11 00:46:32 -08:00
Olaoluwa Osuntokun
b57ea5c1cd
lncfg: detect tor resolution error case and fallback to system resolver
In this commit, we fix a bug that would cause resolution of items in
/etc/hosts (or the like) to fail as Tor wouldn't recognize them as
proper host names. With this commit, we'll catch this error and fall
back to the system's resolver.
2021-02-11 00:36:58 -08:00
Olaoluwa Osuntokun
6bca1fbc30
lncfg: use net.ParseIP to detect IPv6 addresses 2021-02-11 00:36:58 -08:00
eugene
71ab07763d
lncfg: add isIPv6Host helper to force v6 addrs through system resolver
With this commit, if --tor.active is specified, then IPv6 addresses
will no longer go through the connmgr.TorLookupIP function from btcd.
This function does not have proper IPv6 support and would fail with
the error "tor general error". Instead, use the system resolver.
2021-02-11 00:36:57 -08:00
Wilmer Paulino
b38d8d84d9
discovery: use token bucket based rate limiting to throttle gossip
The recently added gossip throttling was shown to be too aggressive,
especially with our auto channel enable/disable signaling. We switch to
a token bucket based system instead as it's based on time, rather than a
block height which isn't constantly updated at a given rate.
2021-02-11 00:36:19 -08:00
Wilmer Paulino
4d0a8ed435
Revert "lncfg: add new legacy protocol option to turn off gossip throttling"
This reverts commit b1fbbcf562.
2021-02-11 00:36:18 -08:00
Wilmer Paulino
083a62a3b2
Revert "discovery: add new option to toggle gossip rate limiting"
This reverts commit 13a2598ded.
2021-02-11 00:36:18 -08:00
Wilmer Paulino
423082a4a4
Revert "lntest: always turn off gossip throttling for nodes created in itests"
This reverts commit 447c9f2c0b.
2021-02-11 00:36:18 -08:00
Johan T. Halseth
673cbc6d91
discovery/gossiper: add local updates to graph immediately
Since the batch interval can potentially be long, adding local updates
to the graph could be slow. This would slow down operations like adding
our own channel update and announcements during the funding process, and
updating edge policies for local channels.

Now we instead check whether the update is remote or not, and only for
remote updates use the SchedulerOption to lazily add them to the graph.
2021-02-11 00:35:52 -08:00
Johan T. Halseth
e35c97c214
routing: let graph methods take scheduler option 2021-02-11 00:35:52 -08:00
Johan T. Halseth
6dde42eee6
channeldb: add SchedulerOp arg to graph update methods 2021-02-11 00:35:52 -08:00
Johan T. Halseth
3a1e34b100
batch: add option for executing requests immediately
We make the default non-lazy, and will make the incoming gossip requests
lazy.
2021-02-11 00:35:52 -08:00
Conner Fromknecht
7b98483ebe
discovery: don't historical sync when NumActiveSyncers == 0
Currently when numgraphsyncpeers=0, lnd will still attempt to perform
an initial historical sync. We change this behavior here to forgoe
historical sync entirely when numgraphsyncpeers is zero, since the
routing table isn't being updated anyway while the node is active.

This permits a no-graph lnd mode where no syncing occurs at all.
2021-02-11 00:35:32 -08:00
carla
d75756b1d1
itest: add coverage for hold invoices with hop hints
This PR updates the hold invoice itest to create a private
channel, and sets the private option on the invoices created
to add coverage for the addition of hop hints.
2021-02-11 00:35:19 -08:00
Wilmer Paulino
1378b83f7a
discovery: use source of ann upon confirmed channel ann batch
We do this instead of using the source of the AnnounceSignatures
message, as we filter out the source when broadcasting any
announcements, leading to the remote node not receiving our channel
update. Note that this is done more for the sake of correctness and to
address a flake within the integration tests, as channel updates are
sent directly and reliably to channel counterparts.
2021-02-11 00:35:02 -08:00
Olaoluwa Osuntokun
1c5ff35260
Revert "Merge pull request #4895 from wpaulino/disallow-premature-chan-updates"
This reverts commit 6e6384114c, reversing
changes made to 98ea433271.
2021-02-11 00:35:02 -08:00
rockstardev
3de4af2348
fix: correct no-rest-tls parameter in error message 2021-02-11 00:33:48 -08:00
Oliver Gugger
b67c840b4c
make: clean mobile stubs before building release
To fix an issue where the vendor.tar.gz in a release build had a
different hash if the mobile RPC stubs were in the mobile/ folder, we
clean those out first.

The culprit was the `google.golang.org/grpc/test/bufconn` package which
is currently only used in the mobile RPC stubs and nowhere else.
Therefore the vendor/module.txt was different when vendoring with the
generated mobile RPC stubs being around.
2021-02-11 00:33:48 -08:00
Johan T. Halseth
d61ec5c2f7
docs: correct sign command 2021-02-11 00:26:53 -08:00
rockstardev
a3b83494ee Update README to add link to our repository with C# Lightning clients 2021-02-07 13:37:55 -06:00
rockstardev
ed9e64e810 Update README to fix link to LND 0.12.0 image on Docker Hub 2021-02-07 13:36:12 -06:00
rockstardev
d73673492f Disabling TLS check so that we can listen on all interfaces for btcpayserver-docker deployments 2021-02-06 19:27:21 -06:00
rockstardev
bb5edcd3c6 Removing .github folder from origin repo 2021-02-06 17:21:13 -06:00
rockstardev
de4509adc1 Update README for 0.12.0-beta 2021-02-06 17:15:02 -06:00
Conner Fromknecht
79c8ecc9d7
Merge pull request #4980 from cfromknecht/v0.12.1-beta.rc1-branch-commits
Some checks failed
Docker image build / main (push) Has been cancelled
Release build / Release build (push) Has been cancelled
v0.12.1-beta.rc1
2021-02-03 22:06:50 -08:00
Conner Fromknecht
964f2e7781
bulid: bump version to v0.12.1-beta.rc1 2021-02-03 20:33:59 -08:00
eugene
ad052ad7f0
htlcswitch: reestablish unit tests 2021-02-03 20:32:45 -08:00
eugene
1d3985d3af
channeldb+lnwallet: lastWasRevokeKey to store last sent rev/sig 2021-02-03 20:32:15 -08:00
Olaoluwa Osuntokun
e06f817b47
routing: add new TestPaymentAddrOnlyNoSplit test case
This test case ensures that we won't try to split payment if the dest
has the payment addr bit, but NOT the mpp optional/require bit.
2021-02-03 20:32:03 -08:00
Olaoluwa Osuntokun
732eabc8df
routing: allow custom dest feature bits in integratedRoutingContext.testPayment
This is a preparatory commit for a new test to ensure that if a node
only has the TLV and payment addr feature bits, we don't try to split a
payment.
2021-02-03 20:31:49 -08:00
Conner Fromknecht
bb1f738d1d
gen_protos_docker: make image build non-quiet
This allows users to see progress whenever the docker image is
[re]built, and (esp on non-linux hosts) track the size of the build
context being uploaded. Currently no output is displayed, so it's hard
to attribute the source of latency, e.g. network latency, building
layers, a large work directory, etc.
2021-02-03 20:31:37 -08:00
Olaoluwa Osuntokun
2cc8b16339
build: update CI builds to use go 1.15.7 2021-02-03 20:31:26 -08:00
Juan Pablo Civile
d6d6f5b1a3
routing: limit max parts if the invoice doesn't declare MPP support 2021-02-03 20:31:12 -08:00
Juan Pablo Civile
905e1cb009
routerrpc: limit max parts if the invoice doesn't declare MPP support 2021-02-03 20:30:59 -08:00
Conner Fromknecht
aeaf5c0ed2
lntest: fix linter errors 2021-02-03 20:30:49 -08:00
Conner Fromknecht
775b6e5f68
discovery/sync_manager: remove unneeded markGraphSyncing
AFAICT it's not possible to flip back from bein synced_to_chain, so we
remove the underlying call that could reflect this. The method is moved
into the test file since it's still used to test correctness of other
portions of the flow.
2021-02-03 20:30:36 -08:00
Conner Fromknecht
bbe090a538
lntest: call markGraphSynced from gossipSyncer
Rather than performing this call in the SyncManager, we give each
gossipSyncer the ability to mark the first sync completed. This permits
pinned syncers to contribute towards the rpc-level synced_to_graph
value, allowing the value to be true after the first pinned syncer or
regular syncer complets. Unlinke regular syncers, pinned syncers can
proceed in parallel possibly decreasing the waiting time if consumers
rely on this field before proceeding to load their application.
2021-02-03 20:30:25 -08:00
Conner Fromknecht
e6af248ed8
lntest/graph_top: test pinned syncers 2021-02-03 20:30:17 -08:00
Conner Fromknecht
f04074835d
lntest/graph_top: remove dependence on net.Alice/Bob 2021-02-03 20:30:09 -08:00
Conner Fromknecht
275055d4a0
config: expose gossip.pinned-syncers for conf
The pinned syncer set is exposed as a comma-separated list of pubkeys.
2021-02-03 20:29:56 -08:00
Conner Fromknecht
c8ce80a3f4
lnrpc: expose PINNED_SYNC for listpeers 2021-02-03 20:29:40 -08:00
Conner Fromknecht
505133310d
discovery: perform initial historical sync for pinned peers 2021-02-03 20:29:24 -08:00
Conner Fromknecht
4db594425b
discovery: add support for PinnedSyncers
A pinned syncer is an ActiveSyncer that is configured to always remain
active for the lifetime of the connection. Pinned syncers do not count
towards the total NumActiveSyncer count, which are rotated periodically.

This features allows nodes to more tightly synchronize their routing
tables by ensuring they are always receiving gossip from distinguished
subset of peers.
2021-02-03 20:29:11 -08:00
Conner Fromknecht
631e6b99f9
discovery/sync_manager: Pause/Resume HistoricalSyncTicker
This gives each initial historical syncer an equal amount of time before
being rotated, even if some fail.
2021-02-03 20:29:00 -08:00
Conner Fromknecht
816c3dd2a8
discovery/sync_manager: make setHistoricalSyncer closure 2021-02-03 20:28:46 -08:00
Conner Fromknecht
8259dac5fb
discovery/sync_manager: break out IsGraphSynced check 2021-02-03 20:28:35 -08:00
Conner Fromknecht
d67d02bde5
discovery: handle err for linter 2021-02-03 20:28:28 -08:00
Andras Banki-Horvath
14653865b2
invoices+rpc: add missing channel graph to the AddInvoiceConfig
The Graph which is referenced later in the AddInvoice call graph is
unset when adding a hodl invoice. This resulted in a crash.
2021-02-03 20:28:19 -08:00
eugene
ab6ad25a92
lntest/channels: introduce subpackage to deduplicate static structs 2021-02-03 20:28:01 -08:00
Umar Bolatov
f92ec41e74
Fix typo in restorechanbackup command description 2021-02-03 20:27:54 -08:00
Oliver Gugger
a4168b2e07
ci: check mobile compilation in same step as RPC
Because we now build a docker image for the RPC compilation, we can save
some execution minutes if we run the mobile RPC and code compilation check in the
same step of the CI workflow.
2021-02-03 20:27:48 -08:00
Oliver Gugger
f15f0f8126
make+lnrpc: compile mobile RPC with docker too
Now that we have a base docker image that has all our RPC compilation
dependencies installed, we can also run the mobile RPC compilation
there. This removes the need to install falafel and goimports on the
local machine.
2021-02-03 20:27:42 -08:00
Oliver Gugger
3ad5a90800
mobile: remove grpc-gateway import
Because we compile the REST code from the rest-annotations.yaml and no
longer import the annotations in the proto files, we don't need to
specify the custom import path anymore.
2021-02-03 20:27:35 -08:00
Oliver Gugger
0fb4e7c60c
multi: remove proto install script 2021-02-03 20:27:28 -08:00
Oliver Gugger
9048a92016
make+lnrpc: use docker to compile protos
This commit aims to make it easier for developers to compile our
protobuf definitions. They now only need to have docker installed
instead of a whole set of binaries and libraries all pinned to very
specific versions.
2021-02-03 20:27:21 -08:00
Johan T. Halseth
b23dce1bc8
monitoring: run go fmt 2021-02-03 20:27:15 -08:00
Johan T. Halseth
1108c63218
make: run goimports during make fmt 2021-02-03 20:27:09 -08:00
Johan T. Halseth
cfb2343121
make: exclude autogenerated files from go fmt 2021-02-03 20:27:03 -08:00
Joost Jager
dbddc0e841
lnrpc: add htlc attempt id 2021-02-03 20:26:45 -08:00
Oliver Gugger
22f35f40be
scripts: don't fail on missing public key
When verifying the release signatures, we don't want to fail if a
signer's signature is not available in the gpg key ring. Instead we just
don't want to count the signature for now and still succeed if there's
at least one other good sig with a known key.
2021-02-03 20:26:38 -08:00
Oliver Gugger
6c1abd4de9
GitHub: use vendored actions for steps with sensitive info
To avoid leaking any sensitive information like Docker Hub credentials
because of compromised actions repositories, we use our own, vendored
actions for all steps that potentially touch sensitive information.
2021-02-03 20:26:33 -08:00
Jake Sylvestre
be692522d7
docs: add mac clang-format instructions 2021-02-03 20:26:27 -08:00
Vlad Stan
6c661b65b6
docker: add an extra listener for localhost
Make sure the lncli command can be used inside of the container without
needing to specify the --rpcserver flag all the time. Issue: #4937
2021-02-03 20:26:20 -08:00
Johan T. Halseth
49ac6a15be
scripts: add halseth key to verify script 2021-02-03 20:26:13 -08:00
Johan T. Halseth
236c839ee7
netann: ignore unknown channel updat on startup
Since the funding manager might be in process of adding the edge to the
graph, we ignore the error.
2021-02-03 20:05:24 -08:00
rockstardev
dfc8b00332 Merge branch 'version/0.12.0-beta' 2021-01-31 23:58:00 -06:00
rockstardev
f40c6ec9dd Update readme for 0.12.0-beta.rc5 2021-01-31 16:38:56 -06:00
rockstardev
29b40b7c2e Merge branch 'version/0.12.0-beta.rc5'
# Conflicts:
#	README.md
#	config.go
#	docker-entrypoint.sh
#	docker-initunlocklnd.sh
#	go.mod
#	rpcserver.go
2021-01-31 16:36:59 -06:00
rockstardev
38376fce72 Adding environment variable to influence LND's rest host
(cherry picked from commit 39d25171ce)
(cherry picked from commit 7b6c31d223)
2021-01-31 16:32:19 -06:00
rockstardev
6ab9e9a778 Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
(cherry picked from commit a185998bcf)
2021-01-31 16:32:14 -06:00
rockstardev
7b6c31d223 Adding environment variable to influence LND's rest host
(cherry picked from commit 39d25171ce)
2021-01-10 13:16:16 -06:00
rockstardev
a185998bcf Adding BtcPayServer related files and resources
(cherry picked from commit 14517a97ea)
2021-01-10 13:16:06 -06:00
rockstardev
0795375787 Updating readme for 0.11.0 2020-09-28 16:13:16 -05:00
rockstardev
72f916e5d7 Merge branch 'version/0.11.0-beta'
# Conflicts:
#	Makefile
#	channeldb/invoice_test.go
#	channeldb/meta_test.go
#	channeldb/payments.go
#	config.go
#	docker-entrypoint.sh
#	go.mod
#	go.sum
#	invoices/invoiceregistry_test.go
#	lnd.go
#	lnrpc/chainrpc/chainnotifier_server.go
#	lnrpc/routerrpc/router.pb.go
#	lnrpc/wtclientrpc/wtclient.go
#	lntest/itest/lnd_multi-hop-error-propagation.go
#	lntest/itest/lnd_multi-hop-payments.go
#	lntest/itest/lnd_test.go
#	lnwallet/btcwallet/btcwallet.go
#	log.go
#	rpcserver.go
#	watchtower/wtclient/client.go
2020-09-28 16:12:05 -05:00
Nicolas Dorier
59b57ebdc0
Update docker-entrypoint.sh 2020-09-14 12:56:54 +09:00
rockstardev
4a4374005b Adding BtcPayServer related files and resources 2020-08-30 01:54:38 -05:00
rockstardev
160aaf40d0 Adding net import that got removed 2020-08-30 01:20:06 -05:00
nicolas.dorier
df5e4eed8d Allow unsafe authentication on regtest 2020-08-30 01:20:05 -05:00
nicolas.dorier
67fabc30bb Do not assume setting options partially are unintentional 2020-08-30 01:20:04 -05:00
nicolas.dorier
477983cf64 Add --notls to disable TLS for REST endpoint 2020-08-30 01:19:46 -05:00
rockstardev
903a5ae4c5 Updating Readme to clarify purpose of repository 2020-06-09 00:01:20 -05:00
rockstardev
6574ea15ef Merge branch 'version/0.10.1-beta' 2020-06-08 23:48:34 -05:00
rockstardev
4a7514fba7 Merge branch 'version/0.9.2-beta' 2020-06-08 23:47:19 -05:00
rockstardev
9c0e948662 Merge branch 'version/0.8.2-beta' 2020-06-08 23:46:50 -05:00
rockstardev
ee7b9cefc1 Merge branch 'version/0.8.1-beta' 2020-06-08 23:46:35 -05:00
rockstardev
30efca1a0e Adding default LND tags to our docker container release 2020-06-08 23:16:33 -05:00
rockstardev
43f266655a Updating docker builder images 2020-06-08 23:16:19 -05:00
rockstardev
0a7bedc21e Adding net import that got removed 2020-06-08 23:16:14 -05:00
rockstardev
adc4b8e425 Fix typos in docker-entrypoint.sh
Thanks: https://github.com/btcpayserver/lnd/pull/2
2020-06-08 23:16:07 -05:00
rockstardev
da572ca2af Setting execute permission on .sh files 2020-06-08 23:16:01 -05:00
rockstardev
109da44f48 Adjusting Makefile for fresh version string 2020-06-08 23:15:53 -05:00
rockstardev
8ebc7f4c06 Adding BtcPayServer related files and resources 2020-06-08 23:15:15 -05:00
nicolas.dorier
0cf1a3f6b6 Allow unsafe authentication on regtest 2020-06-08 23:15:10 -05:00
nicolas.dorier
dcd6e32a05 Do not assume setting options partially are unintentional 2020-06-08 23:13:44 -05:00
nicolas.dorier
98ec34c523 Add --notls to disable TLS for REST endpoint 2020-06-08 23:13:37 -05:00
Olaoluwa Osuntokun
52bb3f3370
build: bump version to 0.10.1-beta 2020-06-03 11:18:49 -07:00
Olaoluwa Osuntokun
4f2221d56c
build: bump version to v0.10.1-beta.rc3 2020-05-28 15:56:19 -07:00
Olaoluwa Osuntokun
df2c832aa8 Merge branch 'v0.10.1-beta-4327' into v0.10.1-beta-rc3-branch 2020-05-28 15:50:46 -07:00
Joost Jager
bca3bb4d33 routing: don't treat bad features as an unexpected error
Previous behavior led to the payment loop being abandoned immediately,
resulting in a payment stuck in state in_flight.
2020-05-28 15:50:46 -07:00
Olaoluwa Osuntokun
018b55881e Merge branch 'v0.10.1-beta-4332' into v0.10.1-beta-rc3-branch 2020-05-28 15:50:26 -07:00
Conner Fromknecht
564217213c lnd: use Infof to format errors on channeldb open 2020-05-28 15:50:26 -07:00
Conner Fromknecht
745bf0a6c9 channeldb/db: lower-case ErrDryRunMigrationOk message 2020-05-28 15:50:26 -07:00
Olaoluwa Osuntokun
cb36cd9357 Merge branch 'v0.10.1-beta-4335' into v0.10.1-beta-rc3-branch 2020-05-28 15:50:01 -07:00
Joost Jager
6cd4cc47c1 rpcserver+routerrpc: remove payment limit 2020-05-28 15:48:09 -07:00
Olaoluwa Osuntokun
ac7bb1dec2 Merge branch 'v0.10.1-beta-4298' into v0.10.1-beta-rc3-branch 2020-05-27 16:04:16 -07:00
Conner Fromknecht
5cb7ca6bf4 invoices/invoiceregistry: properly synchronize backlog
This commit moves the db calls for retrieving add and settle backlogs
outide of the main event loop. All other db operations are performed
outside of the event loop and synchronized via the invoice registry's
mutex, which also synchronizes the order in which events submitted to be
processed.

This resolves various concurrency issues where notifications can be
missed of inconsistent reads against the databse. This is especially
important in this case because we are actually making two separate
database calls.
2020-05-27 16:04:16 -07:00
Conner Fromknecht
544e606e2c invoices: return error from SubscribeNotifications on shutdown 2020-05-27 16:04:16 -07:00
Conner Fromknecht
2edda573a5 channeldb/invoices: ignore error when no settles exist
This fixes a bug that would cause no backlog to be delivered at all.
2020-05-27 16:04:16 -07:00
Olaoluwa Osuntokun
ae6e84ddfd
build: bump version to v0.10.1-beta.rc2 2020-05-21 17:26:15 -07:00
Olaoluwa Osuntokun
d764cc8fbf Merge branch 'v0.10.1-beta-4302' into v0.10.1-beta-rc2-branch 2020-05-21 17:24:08 -07:00
Wilmer Paulino
c45b2387c2 btcwallet: add transaction outputs bounds check to FetchInputInfo
This prevents a panic when providing an incompatible output index for
the transaction.
2020-05-21 17:23:23 -07:00
Olaoluwa Osuntokun
e883304279
build: bump version to v0.10.1-beta.rc1 2020-05-18 19:28:34 -07:00
Olaoluwa Osuntokun
2c789d92d3 Merge branch 'v0.10.1-beta-4291' into v0.10.1-beta-rc1-branch 2020-05-18 19:26:35 -07:00
Wilmer Paulino
adbbde6f31 build: update to latest btcd and btcwallet versions
This update introduces backwards compatibility for btcd nodes running
versions prior to v0.20.1-beta.
2020-05-18 19:26:08 -07:00
Olaoluwa Osuntokun
580d478cd3 Merge branch 'v0.10.1-beta-4226' into v0.10.1-beta-rc1-branch 2020-05-18 19:25:27 -07:00
Roei Erez
e52982fd0b Ensure chain notifier is started before accessed.
The use case comes from the RPC layer that is ready before the
chain notifier which is used in the sub server.
2020-05-18 19:25:27 -07:00
Roei Erez
470537ec3a chainntnfs: use sync.Once to start notifiers. 2020-05-18 19:25:27 -07:00
Olaoluwa Osuntokun
d63198a792 Merge branch 'v0.10.1-beta-4277' into v0.10.1-beta-rc1-branch 2020-05-18 19:25:15 -07:00
Joost Jager
d914f55e2c lnwallet: return signer error 2020-05-18 19:25:15 -07:00
Olaoluwa Osuntokun
35c23a9d85 Merge branch 'v0.10.1-beta-4274' into v0.10.1-beta-rc1-branch 2020-05-18 19:24:53 -07:00
Wilmer Paulino
0c13b29a0e wtmock: prevent race conditions by not using ClientSession pointers
These race conditions originate from the mock database storing and
returning pointers, rather than returning a copy.

Observed on Travis:

WARNING: DATA RACE
Read at 0x00c0003222b8 by goroutine 149:
  github.com/lightningnetwork/lnd/watchtower/wtclient.(*sessionQueue).drainBackups()
      /home/runner/work/lnd/lnd/watchtower/wtclient/session_queue.go:288 +0xed
  github.com/lightningnetwork/lnd/watchtower/wtclient.(*sessionQueue).sessionManager()
      /home/runner/work/lnd/lnd/watchtower/wtclient/session_queue.go:281 +0x450

Previous write at 0x00c0003222b8 by goroutine 93:
  github.com/lightningnetwork/lnd/watchtower/wtclient.getClientSessions()
      /home/runner/work/lnd/lnd/watchtower/wtclient/client.go:365 +0x24f
  github.com/lightningnetwork/lnd/watchtower/wtclient.(*TowerClient).handleNewTower()
      /home/runner/work/lnd/lnd/watchtower/wtclient/client.go:1063 +0x23e
  github.com/lightningnetwork/lnd/watchtower/wtclient.(*TowerClient).backupDispatcher()
      /home/runner/work/lnd/lnd/watchtower/wtclient/client.go:784 +0x10b9
2020-05-18 19:24:52 -07:00
Wilmer Paulino
3afa4178ba wtclient: test case re-add removed tower 2020-05-18 19:24:52 -07:00
Wilmer Paulino
badbc5a491 rpc: use existing rpc logger for wtclientrpc
The logger string used to identify the wtclient and wtclientrpc loggers
was the same, leading to being unable to modify the log level of the
wtclient logger as it would be overwritten with the wtclientrpc's one.
To simplify things, we decide to use the existing RPC logger for
wtclientrpc.
2020-05-18 19:24:52 -07:00
Wilmer Paulino
1cbb574333 wtclient: filter out inactive sessions upon adding existing/new tower 2020-05-18 19:24:52 -07:00
Wilmer Paulino
2de2f28d23 wtclient: load missing info into client sessions upon new tower
This addresses a potential panic in where we relied on this missing info
being populated.
2020-05-18 19:24:52 -07:00
Wilmer Paulino
4a91472469 wtclient: refactor existing candidate session filtering into method 2020-05-18 19:24:52 -07:00
Olaoluwa Osuntokun
7daead6d85 Merge branch 'v0.10.1-beta-4257' into v0.10.1-beta-rc1-branch 2020-05-18 19:24:17 -07:00
Joost Jager
5e83ed9d89 routing+routerrpc: add multiple outgoing channel restriction 2020-05-18 19:23:12 -07:00
Joost Jager
389b715f15 routing/test: add channel id constants 2020-05-18 19:20:15 -07:00
Olaoluwa Osuntokun
eb445d5789 Merge branch 'v0.10.1-beta-2668' into v0.10.1-beta-rc1-branch 2020-05-18 19:19:34 -07:00
Conner Fromknecht
412d7f5c38 config: adds cli configurable --migration-dry-run 2020-05-18 19:18:25 -07:00
Conner Fromknecht
4b7e8669ac channeldb/db: adds optional dry-run abort for migrations 2020-05-18 19:17:08 -07:00
Olaoluwa Osuntokun
935c2f2c10 Merge branch 'v0.10.1-beta-4253' into v0.10.1-beta-rc1-branch 2020-05-18 19:16:41 -07:00
Olaoluwa Osuntokun
3c0b438f16 cmd/lncli: remove usage of Millisecond() for Go 1.12
The new table format for the pay command started to use the
`Millisecond()` method on `time.Duration`. However, this method was only
added in Go 1.13, so this breaks the build for Go 1.12. We replace this
by manual division. `time.Duration` "natively" is in nanoseconds, so we
covert to milli seconds by dividing my `time.Millisecond`, which is
1,000,000.
2020-05-18 19:16:41 -07:00
Olaoluwa Osuntokun
b38c529ba8 Merge branch 'v0.10.1-beta-4234' into v0.10.1-beta-rc1-branch 2020-05-18 19:16:13 -07:00
carla
3289b31b09 lntest/test: add htlc events test to multi-hop error propagation 2020-05-18 19:16:13 -07:00
carla
a80c69982d lntest/test: move multi-hop error propagation into its own file 2020-05-18 19:16:13 -07:00
carla
926892c906 lntest/test: test htlcnotifier stream for successful multi-hop payments 2020-05-18 19:16:13 -07:00
carla
d70f77efaf lntest/test: move multi-hop payments test into own file 2020-05-18 19:16:13 -07:00
carla
08da737316 lnrpc: add failure detail none to link event rpc 2020-05-18 19:16:13 -07:00
Olaoluwa Osuntokun
913c787082 Merge branch 'v0.10.1-beta-4241' into v0.10.1-beta-rc1-branch 2020-05-18 19:15:32 -07:00
Olaoluwa Osuntokun
f8b85eaf12 channeldb: eliminate extra copy in QueryPayments
In this commit, we eliminate an extraneous copy in the `QueryPayments`
method. Before this commit, we would copy each payment from the initial
FetchPayments call into a new slice. However, pointers to payments are
return from `FetchPayments`, so we can just maintain that same reference
rather than copying again when we want to limit our response.
2020-05-18 19:15:32 -07:00
Olaoluwa Osuntokun
4384978728 Merge branch 'v0.10.1-beta-4176' into v0.10.1-beta-rc1-branch 2020-05-18 19:14:56 -07:00
Wilmer Paulino
97e5763601 rpcserver: omit uptime in ListChannels response if server not started
If the server hasn't fully started yet, it's possible that the channel
event store hasn't either, so it won't be able to consume any requests
until then. To prevent blocking, we'll just omit the uptime related
fields for now.
2020-05-18 19:14:56 -07:00
Wilmer Paulino
08f25bb5bf rpcserver: include upfront shutdown script in ListChannels response
This field could be omitted from the response if we were unable to
calculate the channel's uptime.
2020-05-18 19:14:56 -07:00
rockstardev
5cfd1603da Adding default LND tags to our docker container release 2020-05-13 17:45:38 -05:00
rockstardev
b4c54919e9 Updating docker builder images 2020-04-24 17:46:16 -05:00
rockstardev
62e49ec081 Adding net import that got removed 2020-04-24 17:45:46 -05:00
rockstardev
840abbbdd2 Fix typos in docker-entrypoint.sh
Thanks: https://github.com/btcpayserver/lnd/pull/2
2020-04-24 17:08:08 -05:00
rockstardev
967b0662ce Setting execute permission on .sh files 2020-04-24 17:08:02 -05:00
rockstardev
afb350e553 Adjusting Makefile for fresh version string 2020-04-24 17:07:55 -05:00
rockstardev
83994bef9c Adding BtcPayServer related files and resources 2020-04-24 17:07:49 -05:00
nicolas.dorier
7324f343b9 Allow unsafe authentication on regtest 2020-04-24 17:07:42 -05:00
nicolas.dorier
7c275b2b25 Do not assume setting options partially are unintentional 2020-04-24 17:07:36 -05:00
nicolas.dorier
f05de358c7 Add --notls to disable TLS for REST endpoint 2020-04-24 17:07:29 -05:00
Olaoluwa Osuntokun
ab87dc5fe2
build: bump version to v0.9.2-beta 2020-03-12 17:02:03 -07:00
Olaoluwa Osuntokun
9f47bbc552
build: update to x/crypto version w/o broken poly1305 arm assembly
In this commit, we update to a new version of `x/crypto` that drops
broken ARM assembly that can cause a segfault in systems like raspis.
The broken assembly was removed in this commit to the runtime:
8b774103d3.

Fixes #4052.
2020-03-12 17:01:57 -07:00
Olaoluwa Osuntokun
8aead58288
build: update to version v0.9.1-beta 2020-02-28 18:06:29 -03:00
Olaoluwa Osuntokun
a7cf1b4ff5 build: bump version to v0.9.1-beta.rc1
We also add '.' to the semantic versioning alphabet to ensure it isn't
stripped out.
2020-02-20 19:24:25 -08:00
Olaoluwa Osuntokun
e78d2a061b Merge branch 'v0.9.1-beta-3932' into v0.9.1-beta-rc1-branch 2020-02-20 18:59:05 -08:00
Johan T. Halseth
1fa21e6bcd lnd: reload cert data after renewal
After renewing the certificate, the new certificate wasn't actually
loaded and used, causing the old one to be used until lnd was restarted.
This fixes that by reloading it after it has been written.
2020-02-20 18:59:04 -08:00
Johan T. Halseth
d7f6a39704 lnd+cert: recreate TLS files if IPs or DNS changed
This commit makes lnd recreate its TLS certificate if the config's
tlsextradomains or tlsextraips changed. This is useful, since earlier
user would have to manually delete the files to trigger lnd to recreate
them.

To ensure users don't accidentally have their TLS certificate recreated,
we gate it behind a flag --tlsautorefresh that defaults to false.
2020-02-20 18:59:04 -08:00
Johan T. Halseth
2c8a18fe6f cert+test: IsOutdated check for TLS files if IPs or DNS changed
This commit creates a new utility method IsOutdated that can be used to
check whether a TLS certificate mathces the extra IPs and domains given
in the lnd config.
2020-02-20 18:59:04 -08:00
Johan T. Halseth
51aba35512 cert: extract IP and DNS parsing into methods 2020-02-20 18:59:04 -08:00
Olaoluwa Osuntokun
362d53e5bb Merge branch 'v0.9.1-beta-3691' into v0.9.1-beta-rc1-branch 2020-02-20 18:58:45 -08:00
Johan T. Halseth
15099045fc lnwallet/channel: add TODO 2020-02-20 18:58:45 -08:00
Johan T. Halseth
8db2465638 lnwallet/channel: take remote commitment view into availableBalance calculation
Since our HTLC must also be added to the remote commitment, we do the
balance caluclation also from the remote chain perspective and report
our minimum balance from the two commit views as our available balance.
2020-02-20 18:58:45 -08:00
Johan T. Halseth
c30831dd0d lnwallet: take remote initiator's balance into account
When we send non-dust HTLCs as the non-initiator, the remote party will
have to pay the extra commitment fee. To account for this we figure out
if they can afford paying this fee, if not we report that we only have
balance available for dust HTLCs, since these HTLCs won't increase the
commitment fee.
2020-02-20 18:58:45 -08:00
Johan T. Halseth
e3da653f33 lnwallet/channel: account for HTLC fee when reporting available balance 2020-02-20 18:58:45 -08:00
Johan T. Halseth
7628eb2b76 link+lnwallet: move bandwidth channel reserve validation into channel
Since we want to handle the edge case where paying the HTLC fee would
take the initiator below the reserve, we move the subtraction of the
reserve into availableBalance where this calculation will be performed.
2020-02-20 18:58:45 -08:00
Johan T. Halseth
2f0c01c992 lnwallet/channel: break up availableBalance 2020-02-20 18:58:45 -08:00
Johan T. Halseth
60d843f32d lnwallet: check local commitment sanity when adding HTLC
This commit adds an extra validation step when adding HTLCs. Previously
we would only validate the remote commitment resulting from adding an
HTLC, which in most cases is enough. However, there are situations where
the dustlimits are different, which could lead to the resulting remote
commitment from adding the HTLC being valid, but not the local
commitment.

Now we also validate the local commitment. A test to trigger the case is
added.
2020-02-20 18:58:45 -08:00
Johan T. Halseth
9373f92940 lnwallet tests: add test for dipping remote below chan reserve
This commit adds a test that was previously not performed, namely that
adding a HTLC would dip the remote initiator below its channel reserve.
2020-02-20 18:58:44 -08:00
Johan T. Halseth
e5c39a6569 lnwallet/channel: make validateCommitmentSanity take our/their predict
add

To ba able to validate the commitment sanity both for remote and local
commitments, and at the same time predict both our and their add, we let
validateCommitmentSanity take an extra payment descriptor to make this
possible.
2020-02-20 18:58:44 -08:00
Olaoluwa Osuntokun
74eeff5370 Merge branch 'v0.9.1-beta-3910' into v0.9.1-beta-rc1-branch 2020-02-20 18:58:15 -08:00
nsa
28aece1220 lnwallet: adding TestMaxAsynchronousHtlcs unit test
Adds a new test which asserts that the new ReceiveHTLC logic can
handle proper commitment overflow calculation in the face of
asynchronous updates.
2020-02-20 18:58:15 -08:00
nsa
46c5293ff4 lnwallet: fixing unit tests to properly handle new receive validation
This commit fixes the TestMaxAcceptedHTLCs, TestMaxPendingAmount,
TestMinHTLC, & TestChanReserve unit tests to pass with the new
ReceiveHTLC logic. Instead of asserting specific failures upon
receiving a new commitment signature, the various assertions were
moved to assert on the error returned from ReceiveHTLC.
2020-02-20 18:58:15 -08:00
nsa
22b8402322 lnwallet: call valdiateCommitmentSanity in ReceiveHTLC
This commit checks the commitment sanity when receiving an HTLC so
that if a commitment transaction will overflow from an ADD, it is
caught earlier rather than in ReceiveNewCommitment.
2020-02-20 18:58:15 -08:00
Olaoluwa Osuntokun
ab2324c652 Merge branch 'v0.9.1-beta-3998' into v0.9.1-beta-rc1-branch 2020-02-20 18:57:38 -08:00
Johan T. Halseth
2908984b16 lnwallet: state transition from correct node during test, remove panic
The unit test TestNewBreachRetributionSkipsDustHtlcs triggered a state
transition from Bob, even though it was Alice that had added the HTLCs.
This is wrong since it will lead to Bob still owing Alice a commitment,
which is not accounted for in the unit tests.

We add a sanity check that the add heights has been set for all entries
found in the logs, and return an error otherwise. This won't happen
during normal operation, but it does reveal the mistake in the unit
test, which is fixed by making Alice trigger the transition.

In addition we resolve a long standing TODO by removing a (purposeful)
panic in the channel state machine. Old version of lnd had a bug that
could lead to the parent entries being lost during channel restore. A
panic was added to get to the bottom of if.

This is now fixed, so new nodes shouldn't encounter it. However, to be
on the safe side, instead of panicking we return an error back to
gracefully exit the channel state machine.
2020-02-20 18:57:37 -08:00
Johan T. Halseth
857d26eb71 lnwallet: unify remote and local update log fetch 2020-02-20 18:57:37 -08:00
Olaoluwa Osuntokun
e3e93ab0e6 Merge branch 'v0.9.1-beta-3876' into v0.9.1-beta-rc1-branch 2020-02-20 18:56:01 -08:00
Roei Erez
6152625c53 contractcourt+switch: keep channels with timed-out initiated htlcs.
This commit enables the user to specify he is not interested in
automatically close channels with pending payments that their
corresponding htlcs have timed-out.
By requiring a configurable grace period uptime of our node
before closing such channels, we give a chance to the other node to
properly cancel the htlc and avoid unnecessary on-chain transaction.
In mobile it is very important for the user experience as otherwise
channels will be force closed more frequently.
2020-02-20 18:56:01 -08:00
Roei Erez
f24db730e4 contractcourt: change shouldGoOnChain signature.
This commit changes the shouldGoOnChain signature to get the htlc
as parameter. I will allow the function to take decisions based on
whether the htlc is Incoming or Outgoing.
2020-02-20 18:56:01 -08:00
Olaoluwa Osuntokun
66210aa722 Merge branch 'v0.9.1-beta-3965' into v0.9.1-beta-rc1-branch 2020-02-20 18:54:43 -08:00
Oliver Gugger
8fb33dc5bf rpcserver: instruct REST marshaler to emit default values
This change instructs the REST proxy server to overwrite its default
JSON marshaler settings. That allows us to set EmitDefaults to true
which will result in all JSON fields returned in REST responses to
be fully populated, even if their values are falsey.
2020-02-20 18:54:43 -08:00
Olaoluwa Osuntokun
fbcf388a56 Merge branch 'v0.9.1-beta-3980' into v0.9.1-beta-rc1-branch 2020-02-20 18:54:04 -08:00
Joost Jager
b0c6c1c39c invoices: fix htlc timer deadlock 2020-02-20 18:54:04 -08:00
Joost Jager
44495fdefb invoices: move log into update context 2020-02-20 18:54:04 -08:00
Joost Jager
eea67b00cb invoices: add hash to update context 2020-02-20 18:54:04 -08:00
Olaoluwa Osuntokun
b269185cf0 Merge branch 'v0.9.1-beta-3950' into v0.9.1-beta-rc1-branch 2020-02-20 18:53:34 -08:00
Andras Banki-Horvath
8437f127f0 invoices: fix slow startup with many expired invoices
This commit intends to fix slow first startup time when there are many
invoices that need to be canceled. The slowdown is caused by a combination
of adding invoices to the expiry watcher one-by-one and slow
cancellation. Due to slow cancellation and the unbuffered channel which
we use to pass invoices to the expiry watcher blocks the registry.
With this fix we'll instead batch add invoices to the expiry watcher and
thereby won't block the registry startup.
2020-02-20 18:53:33 -08:00
Olaoluwa Osuntokun
f102a00a04 Merge branch 'v0.9.1-beta-3925' into v0.9.1-beta-rc1-branch 2020-02-20 18:52:54 -08:00
Wilmer Paulino
1d8da3123e discovery: check ChainHash in QueryChannelRange messages
If the provided ChainHash in a QueryChannelRange message does not match
that of our current chain, then we should send a blank response, rather
than reply with channels for the wrong chain.
2020-02-20 18:52:54 -08:00
Olaoluwa Osuntokun
4ac37c9f34 Merge branch 'v0.9.1-beta-3992' into v0.9.1-beta-rc1-branch 2020-02-20 18:52:36 -08:00
Joost Jager
156f683e87 lnwallet: fix invalid value use in restoreUpdate
Updates were always restored with the same log index. This could cause a
crash when the logs were compacted and possibly other problems
elsewhere.

Extended unit test to cover the crash scenario.
2020-02-20 18:52:36 -08:00
Olaoluwa Osuntokun
ba822bb7cc Merge branch 'v0.9.1-beta-3872' into v0.9.1-beta-rc1-branch 2020-02-20 18:51:53 -08:00
Joost Jager
666da0d10c lnwallet: restore unsigned acked remote updates
This commit updates the channel state machine to
persistently store remote updates that we have received a
signature for, but that we haven't yet included in a commit
signature of our own.

Previously those updates were only stored in memory and
dropped across restarts. This lead to the production of
an invalid signature and channel force closure. The remote
party expects us to include those updates.
2020-02-20 18:51:52 -08:00
Joost Jager
38445efce7 lnwallet: extract pending local updates restore method
Extract method in preparation for restoring dangling remote updates. We
need to get rid of the early return.
2020-02-20 18:51:52 -08:00
Joost Jager
9da8ad6aa7 channeldb: extract log update serialization
Extract functionality to methods as a preparation for serializing remote
log updates.
2020-02-20 18:51:52 -08:00
Joost Jager
a1b6edef87 channeldb: update UpdateCommitment description
This method is only used to update the local commitment transaction.
Updated comment accordingly.
2020-02-20 18:51:52 -08:00
Joost Jager
716c87fc4e lnwallet/test: test remote update after restart
This test asserts that remote updates that are locked-in on the local
commitment, but haven't been signed for on the remote commitment, are
properly restored after a restart.
2020-02-20 18:51:52 -08:00
Joost Jager
f8b1c8162c lnwallet/test: describe existing bug after restart with dangling remote updates 2020-02-20 18:51:52 -08:00
Joost Jager
1f477f443b lnwallet: restore missing field in local log update
When restoring an htlc fulfill update from disk, the payment hash wasn't
restored previously.
2020-02-20 18:51:52 -08:00
Olaoluwa Osuntokun
25b3d78cb5 Merge branch 'v0.9.1-beta-4017' into v0.9.1-beta-rc1-branch 2020-02-20 18:49:12 -08:00
Olaoluwa Osuntokun
d0d542c477 build: update to latest btcwallet version with rescan addr fix
In this commit, we update to the latest `btcwallet` version that
includes a fix for how we perform rescans. Before this commit, the
wallet would load ALL the created keys into the wallet to perform a
rescan. This is unnecessary, as many of the keys we create are actually
used in contracts, so the wallet can't spend them directly anyway.

For neutrino nodes, this would've caused them to attempt o match more
items in the filter than necessary, possibly resulting in an increased
number of false positive block fetches.
2020-02-20 18:48:36 -08:00
rockstardev
84c25f83bd Setting execute permission on .sh files 2020-01-14 15:25:38 -06:00
rockstardev
2fbbcd2e1d Adjusting Makefile for fresh version string 2020-01-14 15:25:32 -06:00
rockstardev
2e98e45a6e Adding BtcPayServer related files and resources 2020-01-14 15:25:26 -06:00
nicolas.dorier
84200f9299 Allow unsafe authentication on regtest 2020-01-14 15:25:21 -06:00
nicolas.dorier
dc2ef53b82 Do not assume setting options partially are unintentional 2020-01-14 15:25:14 -06:00
nicolas.dorier
4ba6cd647d Add --notls to disable TLS for REST endpoint 2020-01-14 15:25:07 -06:00
Olaoluwa Osuntokun
9cd40c5950
build: bump version to v0.8.2 2019-12-11 16:55:34 -08:00
Olaoluwa Osuntokun
0bc44ec5aa Merge branch 'v0.8.2-beta-3804' into v0.8.2-beta-rc2-branch 2019-12-06 16:10:35 -08:00
Olaoluwa Osuntokun
7ab4667114 Revert "funding: ensure the chan policy max htlc size is below max pay size"
This reverts commit 9b3385e87d.
2019-12-06 16:10:35 -08:00
Olaoluwa Osuntokun
dbb1f3b873 Revert "peer: clamp a link's max HTLC forwarding policy to current max HTLC pay size"
This reverts commit c943d85019.
2019-12-06 16:10:35 -08:00
Olaoluwa Osuntokun
87851c2cdf Merge branch 'v0.8.2-beta-3752' into v0.8.2-beta-rc1-branch 2019-12-04 19:40:58 -08:00
Johan T. Halseth
da737764d0 chainntnfs/txnotifier: promote historical spend log to info
And add some more details.
2019-12-04 19:40:57 -08:00
Johan T. Halseth
8d54778c16 chainntnfs/txnotifier: add more debug logs aroung spend dispatch
To track down missing spends.
2019-12-04 19:40:57 -08:00
Johan T. Halseth
ab9ac096ea chainntnfs/bitcoind: log finished hitsorical spend dispatch 2019-12-04 19:40:57 -08:00
Johan T. Halseth
0bcc2bb52f chainntnfs/interface: add String method for SpendDetaill 2019-12-04 19:40:57 -08:00
Johan T. Halseth
afeb6eea65 chainntnfs/txnotifier: include script in SpendRequest string representation 2019-12-04 19:40:57 -08:00
Olaoluwa Osuntokun
594c832180 Merge branch 'v0.8.2-beta-3790' into v0.8.2-beta-rc1-branch 2019-12-04 19:40:10 -08:00
Olaoluwa Osuntokun
d7fd142d1f funding: ensure the chan policy max htlc size is below max pay size 2019-12-04 19:40:09 -08:00
Olaoluwa Osuntokun
0df8cf866d peer: clamp a link's max HTLC forwarding policy to current max HTLC pay size
In this commit, we start to clamp the max HTLC forwarding policy to the
current register max HTLC payment size. By doing this, we ensure that
any links that have a advertised max HTLC transit size above the max
payment size will reject any incoming or outgoing attempts for such
large payments.
2019-12-04 19:40:09 -08:00
Olaoluwa Osuntokun
1fab42a7e2 lnrpc/routerrpc: make SendToRoute consistent with other payment RPCs
In this commitment, we make the `SendToRoute` RPC call consistent with
all the other payment RPCs which will properly adhere to the current max
payment sat limit. This is a prep commit for the future wumbo soft cap
that will eventually land in lnd.
2019-12-04 19:40:09 -08:00
Olaoluwa Osuntokun
6a6ba4efd7 htlcswitch: fix inconsistency between attribute name and godoc comment 2019-12-04 19:40:09 -08:00
Olaoluwa Osuntokun
bb6e3d92e9 cmd/lncli: exit if user opts to not recover SCB files 2019-12-04 19:39:31 -08:00
Olaoluwa Osuntokun
6893931fbf Merge branch 'v0.8.2-beta-3719' into v0.8.2-beta-rc1-branch 2019-12-04 19:38:45 -08:00
Oliver Gugger
6530b499fc lntest: add unconfirmed channel SCB test 2019-12-04 19:38:45 -08:00
Oliver Gugger
9b65a90f3f chanbackup: set funding broadcast height on restore 2019-12-04 19:38:45 -08:00
Oliver Gugger
b3599b0354 chanbackup: encode broadcast height in chan ID for unconfirmed channels 2019-12-04 19:38:45 -08:00
Olaoluwa Osuntokun
f345297009 Merge branch 'v0.8.2-beta-3737' into v0.8.2-beta-rc1-branch 2019-12-04 19:36:37 -08:00
Oliver Gugger
8ebf765924 lntest: add SCB repeated restore test 2019-12-04 19:36:37 -08:00
Oliver Gugger
b8bda0d934 chanbackup: continue recovery if channel already exists 2019-12-04 19:36:37 -08:00
Olaoluwa Osuntokun
f5aae3c06c Merge branch 'v0.8.2-beta-3698' into v0.8.2-beta-rc1-branch 2019-12-04 19:34:18 -08:00
Andreas M. Antonopoulos
dae5f614fc Warn user before doing SCB restore
SCB restore closes all open channels. We need to warn users that this is what will happen if they try to do an SCB restore.
2019-12-04 19:34:18 -08:00
rockstardev
052358f9c8 Setting execute permission on .sh files 2019-11-21 23:48:53 -06:00
rockstardev
08ad05bca0 Adjusting Makefile for fresh version string 2019-11-21 23:28:39 -06:00
rockstardev
a6b5798acd Adding BtcPayServer related files and resources 2019-11-21 23:28:29 -06:00
nicolas.dorier
8aedb15382 Allow unsafe authentication on regtest 2019-11-21 23:27:43 -06:00
nicolas.dorier
127dabcc02 Do not assume setting options partially are unintentional 2019-11-21 23:24:15 -06:00
nicolas.dorier
f0d13cbb8e Add --notls to disable TLS for REST endpoint 2019-11-21 23:23:52 -06:00
Wilmer Paulino
0bff2ed554 lnwallet: fix test inconsistencies to support bitcoind 0.19.0
bitcoind's sendrawtransaction API in v0.19.0 now enforces a maximum fee
rate of 0.1 BTC/kb and valid output scripts.
2019-11-14 16:32:14 -08:00
Wilmer Paulino
2b1effdf99 build: bump btcsuite and neutrino dependencies to latest tagged versions
The btcwallet update includes some edge-case wallet bug fixes and an
optimization on ZMQ connections for bitcoind backends.

The btcd update allows for compatibility with bitcoind v0.19.0 backends.
2019-11-14 16:31:56 -08:00
987 changed files with 41013 additions and 88465 deletions

View File

@ -1,4 +0,0 @@
version: v1.57.0
plugins:
- module: 'github.com/lightningnetwork/lnd/tools/linters'
path: ./tools/linters

View File

@ -7,26 +7,18 @@ inputs:
key-prefix:
description: "A prefix to use for the cache key, to separate cache entries from other workflows"
required: false
use-build-cache:
description: "Whether to use the build cache"
required: false
# Boolean values aren't supported in the workflow syntax, so we use a
# string. To not confuse the value with true/false, we use 'yes' and 'no'.
default: 'yes'
runs:
using: "composite"
steps:
- name: setup go ${{ inputs.go-version }}
uses: actions/setup-go@v5
uses: actions/setup-go@v3
with:
go-version: '${{ inputs.go-version }}'
cache: 'false'
- name: go cache
if: ${{ inputs.use-build-cache == 'yes' }}
uses: actions/cache@v4
uses: actions/cache@v3
with:
# In order:
# * Module download cache
@ -38,39 +30,11 @@ runs:
~/.cache/go-build
~/Library/Caches/go-build
~\AppData\Local\go-build
# The key is used to create and later look up the cache. It's made of
# four parts:
# - The base part is made from the OS name, Go version and a
# job-specified key prefix. Example: `linux-go-1.23.12-unit-test-`.
# It ensures that a job running on Linux with Go 1.23 only looks for
# caches from the same environment.
# - The unique part is the `hashFiles('**/go.sum')`, which calculates a
# hash (a fingerprint) of the go.sum file.
key: ${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-${{ hashFiles('**/go.sum') }}
# The restore-keys provides a list of fallback keys. If no cache
# matches the key exactly, the action will look for a cache where the
# key starts with one of the restore-keys. The action searches the
# restore-keys list in order and restores the most recently created
# cache that matches the prefix. Once the job is done, a new cache is
# created and saved using the new key.
key: ${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-${{ github.job }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-${{ github.job }}-
${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-
- name: go module cache
if: ${{ inputs.use-build-cache == 'no' }}
uses: actions/cache@v4
with:
# Just the module download cache.
path: |
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-no-build-cache-${{ github.job }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-no-build-cache-${{ github.job }}-
${{ runner.os }}-go-${{ inputs.go-version }}-${{ inputs.key-prefix }}-no-build-cache-
- name: set GOPATH
shell: bash
run: |

View File

@ -11,9 +11,8 @@ Steps for reviewers to follow to test the change.
- [ ] Bug fixes contain tests triggering the bug to prevent regressions.
### Code Style and Documentation
- [ ] The change is not [insubstantial](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md#substantial-contributions-only). Typo fixes are not accepted to fight bot spam.
- [ ] The change obeys the [Code Documentation and Commenting](https://github.com/lightningnetwork/lnd/blob/master/docs/development_guidelines.md#code-documentation-and-commenting) guidelines, and lines wrap at 80.
- [ ] Commits follow the [Ideal Git Commit Structure](https://github.com/lightningnetwork/lnd/blob/master/docs/development_guidelines.md#ideal-git-commit-structure).
- [ ] The change obeys the [Code Documentation and Commenting](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md#CodeDocumentation) guidelines, and lines wrap at 80.
- [ ] Commits follow the [Ideal Git Commit Structure](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md#IdealGitCommitStructure).
- [ ] Any new logging statements use an appropriate subsystem and logging level.
- [ ] Any new lncli commands have appropriate tags in the comments for the rpc in the proto file.
- [ ] [There is a change description in the release notes](https://github.com/lightningnetwork/lnd/tree/master/docs/release-notes), or `[skip ci]` in the commit message for small changes.

View File

@ -21,20 +21,17 @@ defaults:
shell: bash
env:
BITCOIN_VERSION: "29"
BITCOIN_VERSION: "28"
# TRANCHES defines the number of tranches used in the itests.
TRANCHES: 16
TRANCHES: 8
# SMALL_TRANCHES defines the number of tranches used in the less stable itest
# builds
#
# TODO(yy): remove this value and use TRANCHES.
SMALL_TRANCHES: 8
# If you change this please also update GO_VERSION in Makefile (then run
# `make lint` to see where else it needs to be updated as well).
GO_VERSION: 1.23.12
# If you change this value, please change it in the following files as well:
# /.travis.yml
# /Dockerfile
# /dev.Dockerfile
# /make/builder.Dockerfile
# /.github/workflows/release.yml
GO_VERSION: 1.22.6
jobs:
########################
@ -44,11 +41,8 @@ jobs:
name: Sqlc check
runs-on: ubuntu-latest
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
@ -70,11 +64,8 @@ jobs:
name: RPC and mobile compilation check
runs-on: ubuntu-latest
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
@ -101,11 +92,8 @@ jobs:
name: check commits
runs-on: ubuntu-latest
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -127,11 +115,8 @@ jobs:
name: lint code
runs-on: ubuntu-latest
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -158,33 +143,18 @@ jobs:
cross-compile:
name: cross compilation
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
# Please keep this list in sync with make/release_flags.mk!
include:
- name: i386
sys: freebsd-386 linux-386 windows-386
- name: amd64
sys: darwin-amd64 freebsd-amd64 linux-amd64 netbsd-amd64 openbsd-amd64 windows-amd64
- name: arm
sys: darwin-arm64 freebsd-arm linux-armv6 linux-armv7 linux-arm64 windows-arm
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
with:
go-version: '${{ env.GO_VERSION }}'
key-prefix: cross-compile
use-build-cache: 'no'
- name: build release for all architectures
run: make release sys="${{ matrix.sys }}"
run: make release
########################
# sample configuration check
@ -193,11 +163,8 @@ jobs:
name: sample configuration check
runs-on: ubuntu-latest
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
@ -218,19 +185,16 @@ jobs:
fail-fast: false
matrix:
unit_type:
- unit-cover
- btcd unit-cover
- unit tags="kvdb_etcd"
- unit tags="kvdb_postgres"
- unit tags="kvdb_sqlite"
- unit-race
- btcd unit-race
- unit-module
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -239,7 +203,7 @@ jobs:
uses: ./.github/actions/rebase
- name: git checkout fuzzing seeds
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
repository: lightninglabs/lnd-fuzz
path: lnd-fuzz
@ -259,26 +223,20 @@ jobs:
- name: run ${{ matrix.unit_type }}
run: make ${{ matrix.unit_type }}
- name: Clean coverage
run: grep -Ev '(\.pb\.go|\.pb\.json\.go|\.pb\.gw\.go)' coverage.txt > coverage-norpc.txt
if: matrix.unit_type == 'unit-cover'
- name: Send coverage
uses: coverallsapp/github-action@v2
if: matrix.unit_type == 'unit-cover'
continue-on-error: true
uses: shogo82148/actions-goveralls@v1
if: matrix.unit_type == 'btcd unit-cover'
with:
file: coverage-norpc.txt
path-to-profile: coverage.txt
flag-name: 'unit'
format: 'golang'
parallel: true
########################
# run integration tests with TRANCHES
# run ubuntu integration tests
########################
basic-integration-test:
name: basic itests
ubuntu-integration-test:
name: run ubuntu itests
runs-on: ubuntu-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
strategy:
@ -292,14 +250,23 @@ jobs:
args: backend=bitcoind cover=1
- name: bitcoind-notxindex
args: backend="bitcoind notxindex"
- name: bitcoind-rpcpolling
args: backend="bitcoind rpcpolling" cover=1
- name: bitcoind-etcd
args: backend=bitcoind dbbackend=etcd
- name: bitcoind-postgres
args: backend=bitcoind dbbackend=postgres
- name: bitcoind-sqlite
args: backend=bitcoind dbbackend=sqlite
- name: bitcoind-postgres-nativesql
args: backend=bitcoind dbbackend=postgres nativesql=true
- name: bitcoind-sqlite-nativesql
args: backend=bitcoind dbbackend=sqlite nativesql=true
- name: neutrino
args: backend=neutrino cover=1
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -317,93 +284,14 @@ jobs:
run: ./scripts/install_bitcoind.sh $BITCOIN_VERSION
- name: run ${{ matrix.name }}
run: make itest-parallel tranches=${{ env.TRANCHES }} ${{ matrix.args }} shuffleseed=${{ github.run_id }}${{ strategy.job-index }}
- name: Clean coverage
run: grep -Ev '(\.pb\.go|\.pb\.json\.go|\.pb\.gw\.go)' coverage.txt > coverage-norpc.txt
if: ${{ contains(matrix.args, 'cover=1') }}
run: make itest-parallel tranches=${{ env.TRANCHES }} ${{ matrix.args }}
- name: Send coverage
if: ${{ contains(matrix.args, 'cover=1') }}
continue-on-error: true
uses: coverallsapp/github-action@v2
uses: shogo82148/actions-goveralls@v1
with:
file: coverage-norpc.txt
path-to-profile: coverage.txt
flag-name: 'itest-${{ matrix.name }}'
format: 'golang'
parallel: true
- name: Zip log files on failure
if: ${{ failure() }}
timeout-minutes: 5 # timeout after 5 minute
run: 7z a logs-itest-${{ matrix.name }}.zip itest/**/*.log itest/postgres.log
- name: Upload log files on failure
uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: logs-itest-${{ matrix.name }}
path: logs-itest-${{ matrix.name }}.zip
retention-days: 5
########################
# run integration tests with SMALL_TRANCHES
########################
integration-test:
name: itests
runs-on: ubuntu-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
strategy:
# Allow other tests in the matrix to continue if one fails.
fail-fast: false
matrix:
include:
- name: bitcoind-rpcpolling
args: backend="bitcoind rpcpolling"
- name: bitcoind-etcd
args: backend=bitcoind dbbackend=etcd
- name: bitcoind-sqlite
args: backend=bitcoind dbbackend=sqlite
- name: bitcoind-sqlite-nativesql
args: backend=bitcoind dbbackend=sqlite nativesql=true
- name: bitcoind-postgres
args: backend=bitcoind dbbackend=postgres
- name: bitcoind-postgres-nativesql
args: backend=bitcoind dbbackend=postgres nativesql=true
steps:
- name: git checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: fetch and rebase on ${{ github.base_ref }}
if: github.event_name == 'pull_request'
uses: ./.github/actions/rebase
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
with:
go-version: '${{ env.GO_VERSION }}'
key-prefix: integration-test
- name: install bitcoind
run: ./scripts/install_bitcoind.sh $BITCOIN_VERSION
- name: run ${{ matrix.name }}
run: make itest-parallel tranches=${{ env.SMALL_TRANCHES }} ${{ matrix.args }} shuffleseed=${{ github.run_id }}${{ strategy.job-index }}
- name: Clean coverage
run: grep -Ev '(\.pb\.go|\.pb\.json\.go|\.pb\.gw\.go)' coverage.txt > coverage-norpc.txt
if: ${{ contains(matrix.args, 'cover=1') }}
- name: Send coverage
if: ${{ contains(matrix.args, 'cover=1') }}
continue-on-error: true
uses: coverallsapp/github-action@v2
with:
file: coverage-norpc.txt
flag-name: 'itest-${{ matrix.name }}'
format: 'golang'
parallel: true
- name: Zip log files on failure
@ -412,7 +300,7 @@ jobs:
run: 7z a logs-itest-${{ matrix.name }}.zip itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-itest-${{ matrix.name }}
@ -424,12 +312,12 @@ jobs:
# run windows integration test
########################
windows-integration-test:
name: windows itest
name: run windows itest
runs-on: windows-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
steps:
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -444,7 +332,7 @@ jobs:
key-prefix: integration-test
- name: run itest
run: make itest-parallel tranches=${{ env.SMALL_TRANCHES }} windows=1 shuffleseed=${{ github.run_id }}
run: make itest-parallel tranches=${{ env.TRANCHES }} windows=1
- name: kill any remaining lnd processes
if: ${{ failure() }}
@ -457,7 +345,7 @@ jobs:
run: 7z a logs-itest-windows.zip itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-itest-windows
@ -468,12 +356,12 @@ jobs:
# run macOS integration test
########################
macos-integration-test:
name: macOS itest
name: run macOS itest
runs-on: macos-14
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
steps:
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -487,8 +375,14 @@ jobs:
go-version: '${{ env.GO_VERSION }}'
key-prefix: integration-test
- name: install bitcoind
run: |
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}.0/bitcoin-${BITCOIN_VERSION}.0-arm64-apple-darwin.tar.gz
tar zxvf bitcoin-${BITCOIN_VERSION}.0-arm64-apple-darwin.tar.gz
mv bitcoin-${BITCOIN_VERSION}.0 /tmp/bitcoin
- name: run itest
run: make itest-parallel tranches=${{ env.SMALL_TRANCHES }} shuffleseed=${{ github.run_id }}
run: PATH=$PATH:/tmp/bitcoin/bin make itest-parallel tranches=${{ env.TRANCHES }} backend=bitcoind
- name: Zip log files on failure
if: ${{ failure() }}
@ -496,7 +390,7 @@ jobs:
run: 7z a logs-itest-macos.zip itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-itest-macos
@ -518,11 +412,8 @@ jobs:
- github.com/golang/protobuf v1.5.3
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: ensure dependencies at correct version
run: if ! grep -q "${{ matrix.pinned_dep }}" go.mod; then echo dependency ${{ matrix.pinned_dep }} should not be altered ; exit 1 ; fi
@ -535,39 +426,18 @@ jobs:
runs-on: ubuntu-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-changelog'')'
steps:
- name: cleanup space
run: rm -rf /opt/hostedtoolcache
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: release notes check
run: scripts/check-release-notes.sh
########################
# Backwards Compatibility Test
########################
backwards-compatability-test:
name: backwards compatability test
runs-on: ubuntu-latest
steps:
- name: git checkout
uses: actions/checkout@v4
- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 🛡️ backwards compatibility test
run: make backwards-compat-test
# Notify about the completion of all coverage collecting jobs.
finish:
if: ${{ always() }}
needs: [unit-test, basic-integration-test]
needs: [unit-test, ubuntu-integration-test]
runs-on: ubuntu-latest
steps:
- name: Send coverage
uses: coverallsapp/github-action@v2
continue-on-error: true
- uses: shogo82148/actions-goveralls@v1
with:
parallel-finished: true

View File

@ -10,9 +10,12 @@ defaults:
shell: bash
env:
# If you change this please also update GO_VERSION in Makefile (then run
# `make lint` to see where else it needs to be updated as well).
GO_VERSION: 1.23.12
# If you change this value, please change it in the following files as well:
# /Dockerfile
# /dev.Dockerfile
# /make/builder.Dockerfile
# /.github/workflows/main.yml
GO_VERSION: 1.22.6
jobs:
main:
@ -20,18 +23,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: git checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: cleanup space
run: rm -rf /opt/hostedtoolcache && mkdir -p /opt/hostedtoolcache/go
- name: setup go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
uses: actions/setup-go@v2
with:
go-version: '${{ env.GO_VERSION }}'
cache: 'false'
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
@ -123,12 +122,10 @@ jobs:
that `vendor.tar.gz` and `lnd-source-${{ env.RELEASE_VERSION }}.tar.gz` are in the current directory, follow these steps:
```
tar -xvzf lnd-source-${{ env.RELEASE_VERSION }}.tar.gz
mv vendor.tar.gz lnd-source/
cd lnd-source
tar -xvzf vendor.tar.gz
go install -v -mod=vendor -ldflags "-X github.com/lightningnetwork/lnd/build.Commit=${{ env.RELEASE_VERSION }}" ./cmd/lnd
go install -v -mod=vendor -ldflags "-X github.com/lightningnetwork/lnd/build.Commit=${{ env.RELEASE_VERSION }}" ./cmd/lncli
tar -xvzf lnd-source-${{ env.RELEASE_VERSION }}.tar.gz
GO111MODULE=on go install -v -mod=vendor -ldflags "-X github.com/lightningnetwork/lnd/build.Commit=${{ env.RELEASE_VERSION }}" ./cmd/lnd
GO111MODULE=on go install -v -mod=vendor -ldflags "-X github.com/lightningnetwork/lnd/build.Commit=${{ env.RELEASE_VERSION }}" ./cmd/lncli
```
The `-mod=vendor` flag tells the `go build` command that it doesn't need to fetch the dependencies, and instead, they're all enclosed in the local vendor directory.

5
.gitignore vendored
View File

@ -44,9 +44,6 @@ cmd/cmd
*.key
*.hex
# Ignore the custom linter binary if it is built.
custom-gcl
cmd/lncli/lncli
# Files from mobile build.
@ -80,5 +77,3 @@ coverage.txt
# Release build directory (to avoid build.vcs.modified Golang build tag to be
# set to true by having untracked files in the working directory).
/lnd-*/
.aider*

View File

@ -1,7 +1,5 @@
run:
# If you change this please also update GO_VERSION in Makefile (then run
# `make lint` to see where else it needs to be updated as well).
go: "1.23.12"
go: "1.22.6"
# Abort after 10 minutes.
timeout: 10m
@ -22,22 +20,14 @@ run:
- integration
linters-settings:
custom:
ll:
type: "module"
description: "Custom lll linter with 'S' log line exclusion."
settings:
# Max line length, lines longer will be reported.
line-length: 80
# Tab width in spaces.
tab-width: 8
# The regex that we will use to detect the start of an `S` log line.
log-regex: "^\\s*.*(L|l)og\\.(Info|Debug|Trace|Warn|Error|Critical)S\\("
errorlint:
# Check for incorrect fmt.Errorf error wrapping.
errorf: true
govet:
# Don't report about shadowed variables
check-shadowing: false
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
@ -55,12 +45,16 @@ linters-settings:
excludes:
- G402 # Look for bad TLS connection settings.
- G306 # Poor file permissions used when writing to a new file.
- G601 # Implicit memory aliasing in for loop.
- G115 # Integer overflow in conversion.
staticcheck:
checks: ["-SA1019"]
lll:
# Max line length, lines longer will be reported.
line-length: 80
# Tab width in spaces.
tab-width: 8
funlen:
# Checks the number of lines in a function.
# If lower than 0, disable the check.
@ -111,10 +105,6 @@ linters-settings:
linters:
enable-all: true
disable:
# We instead use our own custom line length linter called `ll` since
# then we can ignore log lines.
- lll
# Global variables are used in many places throughout the code base.
- gochecknoglobals
@ -142,13 +132,16 @@ linters:
- unparam
- wastedassign
# Disable gofumpt as it has weird behavior regarding formatting multiple
# lines for a function which is in conflict with our contribution
# guidelines. See https://github.com/mvdan/gofumpt/issues/235.
- gofumpt
# Disable whitespace linter as it has conflict rules against our
# contribution guidelines.
# contribution guidelines. See https://github.com/bombsimon/wsl/issues/109.
#
# TODO(yy): bring it back when the above issue is fixed.
- wsl
# Allow using default empty values.
@ -192,6 +185,7 @@ linters:
# The linter is too aggressive and doesn't add much value since reviewers
# will also catch magic numbers that make sense to extract.
- gomnd
- mnd
# Some of the tests cannot be parallelized. On the other hand, we don't
@ -210,14 +204,11 @@ linters:
- depguard
- gosmopolitan
- intrange
- goconst
# Deprecated linters that have been replaced by newer ones.
- tenv
issues:
# Only show newly introduced problems.
new-from-rev: 03eab4db64540aa5f789c617793e4459f4ba9e78
new-from-rev: 77c7f776d5cbf9e147edc81d65ae5ba177a684e5
# Skip autogenerated files for mobile and gRPC as well as copied code for
# internal use.

View File

@ -1,6 +1,9 @@
# If you change this please also update GO_VERSION in Makefile (then run
# `make lint` to see where else it needs to be updated as well).
FROM golang:1.24.11-alpine as builder
# If you change this value, please change it in the following files as well:
# /dev.Dockerfile
# /make/builder.Dockerfile
# /.github/workflows/main.yml
# /.github/workflows/release.yml
FROM golang:1.22.6-alpine as builder
# Force Go to use the cgo based DNS resolver. This is required to ensure DNS
# queries required to connect to linked containers succeed.
@ -21,7 +24,7 @@ RUN apk add --no-cache --update alpine-sdk \
&& cd /go/src/github.com/lightningnetwork/lnd \
&& git checkout $checkout \
&& make release-install
# Start a new, final image.
FROM alpine as final

101
Makefile
View File

@ -1,17 +1,19 @@
PKG := github.com/lightningnetwork/lnd
ESCPKG := github.com\/lightningnetwork\/lnd
MOBILE_PKG := $(PKG)/mobile
TOOLS_DIR := tools
GOCC ?= go
PREFIX ?= /usr/local
BTCD_PKG := github.com/btcsuite/btcd
GOACC_PKG := github.com/ory/go-acc
GOIMPORTS_PKG := github.com/rinchsan/gosimports/cmd/gosimports
GO_BIN := ${GOPATH}/bin
BTCD_BIN := $(GO_BIN)/btcd
GOIMPORTS_BIN := $(GO_BIN)/gosimports
GOMOBILE_BIN := $(GO_BIN)/gomobile
GOACC_BIN := $(GO_BIN)/go-acc
MOBILE_BUILD_DIR :=${GOPATH}/src/$(MOBILE_PKG)/build
IOS_BUILD_DIR := $(MOBILE_BUILD_DIR)/ios
@ -25,17 +27,27 @@ COMMIT := $(subst -dirty,-fresh-btcpay,$(COMMIT))
LDFLAGS := -ldflags "-X $(PKG)/build.Commit=$(COMMIT)"
# Determine the minor version of the active Go installation.
ACTIVE_GO_VERSION := $(shell $(GOCC) version | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p')
ACTIVE_GO_VERSION := $(shell go version | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p')
ACTIVE_GO_VERSION_MINOR := $(shell echo $(ACTIVE_GO_VERSION) | cut -d. -f2)
LOOPVARFIX :=
ifeq ($(shell expr $(ACTIVE_GO_VERSION_MINOR) \>= 21), 1)
LOOPVARFIX := GOEXPERIMENT=loopvar
endif
LOOPVARFIX :=
ifeq ($(shell expr $(GO_VERSION_MINOR) \>= 21), 1)
LOOPVARFIX := GOEXPERIMENT=loopvar
endif
# GO_VERSION is the Go version used for the release build, docker files, and
# GitHub Actions. This is the reference version for the project. All other Go
# versions are checked against this version.
GO_VERSION = 1.23.12
GO_VERSION = 1.22.6
GOBUILD := $(GOCC) build -v
GOINSTALL := $(GOCC) install -v
GOTEST := $(GOCC) test
GOBUILD := $(LOOPVARFIX) go build -v
GOINSTALL := $(LOOPVARFIX) go install -v
GOTEST := $(LOOPVARFIX) go test
GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*" -not -name "*pb.go" -not -name "*pb.gw.go" -not -name "*.pb.json.go")
@ -69,8 +81,8 @@ endif
DOCKER_TOOLS = docker run \
--rm \
-v $(shell bash -c "$(GOCC) env GOCACHE || (mkdir -p /tmp/go-cache; echo /tmp/go-cache)"):/tmp/build/.cache \
-v $(shell bash -c "$(GOCC) env GOMODCACHE || (mkdir -p /tmp/go-modcache; echo /tmp/go-modcache)"):/tmp/build/.modcache \
-v $(shell bash -c "go env GOCACHE || (mkdir -p /tmp/go-cache; echo /tmp/go-cache)"):/tmp/build/.cache \
-v $(shell bash -c "go env GOMODCACHE || (mkdir -p /tmp/go-modcache; echo /tmp/go-modcache)"):/tmp/build/.modcache \
-v $(shell bash -c "mkdir -p /tmp/go-lint-cache; echo /tmp/go-lint-cache"):/root/.cache/golangci-lint \
-v $$(pwd):/build lnd-tools
@ -87,13 +99,17 @@ all: scratch check install
# ============
# DEPENDENCIES
# ============
$(GOACC_BIN):
@$(call print, "Installing go-acc.")
cd $(TOOLS_DIR); go install -trimpath -tags=tools $(GOACC_PKG)
$(BTCD_BIN):
@$(call print, "Installing btcd.")
cd $(TOOLS_DIR); $(GOCC) install -trimpath $(BTCD_PKG)
cd $(TOOLS_DIR); go install -trimpath $(BTCD_PKG)
$(GOIMPORTS_BIN):
@$(call print, "Installing goimports.")
cd $(TOOLS_DIR); $(GOCC) install -trimpath $(GOIMPORTS_PKG)
cd $(TOOLS_DIR); go install -trimpath $(GOIMPORTS_PKG)
# ============
# INSTALLATION
@ -154,7 +170,7 @@ release-install:
release: clean-mobile
@$(call print, "Releasing lnd and lncli binaries.")
$(VERSION_CHECK)
./scripts/release.sh build-release "$(VERSION_TAG)" "$(BUILD_SYSTEM)" "$(RELEASE_TAGS)" "$(RELEASE_LDFLAGS)" "$(GO_VERSION)"
./scripts/release.sh build-release "$(VERSION_TAG)" "$(BUILD_SYSTEM)" "$(RELEASE_TAGS)" "$(RELEASE_LDFLAGS)"
#? docker-release: Same as release but within a docker container to support reproducible builds on BSD/MacOS platforms
docker-release:
@ -187,32 +203,20 @@ ifeq ($(dbbackend),postgres)
docker rm lnd-postgres --force || echo "Starting new postgres container"
# Start a fresh postgres instance. Allow a maximum of 500 connections so
# that multiple lnd instances with a maximum number of connections of 20
# each can run concurrently. Note that many of the settings here are
# specifically for integration testing and are not fit for running
# production nodes. The increase in max connections ensures that there
# are enough entries allocated for the RWConflictPool to allow multiple
# conflicting transactions to track serialization conflicts. The
# increase in predicate locks and locks per transaction is to allow the
# queries to lock individual rows instead of entire tables, helping
# reduce serialization conflicts. Disabling sequential scan for small
# tables also helps prevent serialization conflicts by ensuring lookups
# lock only relevant rows in the index rather than the entire table.
docker run --name lnd-postgres -e POSTGRES_PASSWORD=postgres -p 6432:5432 -d postgres:13-alpine -N 1500 -c max_pred_locks_per_transaction=1024 -c max_locks_per_transaction=128 -c enable_seqscan=off
docker logs -f lnd-postgres >itest/postgres.log 2>&1 &
# that multiple lnd instances with a maximum number of connections of 50
# each can run concurrently.
docker run --name lnd-postgres -e POSTGRES_PASSWORD=postgres -p 6432:5432 -d postgres:13-alpine -N 500
docker logs -f lnd-postgres &
# Wait for the instance to be started.
sleep $(POSTGRES_START_DELAY)
endif
clean-itest-logs:
rm -rf itest/*.log itest/.logs-*
#? itest-only: Only run integration tests without re-building binaries
itest-only: clean-itest-logs db-instance
itest-only: db-instance
@$(call print, "Running integration tests with ${backend} backend.")
date
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_part.sh 0 1 $(SHUFFLE_SEED) $(TEST_FLAGS) $(ITEST_FLAGS) -test.v
rm -rf itest/*.log itest/.logs-*; date
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_part.sh 0 1 $(TEST_FLAGS) $(ITEST_FLAGS)
$(COLLECT_ITEST_COVERAGE)
#? itest: Build and run integration tests
@ -222,10 +226,10 @@ itest: build-itest itest-only
itest-race: build-itest-race itest-only
#? itest-parallel: Build and run integration tests in parallel mode, running up to ITEST_PARALLELISM test tranches in parallel (default 4)
itest-parallel: clean-itest-logs build-itest db-instance
itest-parallel: build-itest db-instance
@$(call print, "Running tests")
date
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_parallel.sh $(ITEST_PARALLELISM) $(NUM_ITEST_TRANCHES) $(SHUFFLE_SEED) $(TEST_FLAGS) $(ITEST_FLAGS)
rm -rf itest/*.log itest/.logs-*; date
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_parallel.sh $(ITEST_PARALLELISM) $(NUM_ITEST_TRANCHES) $(TEST_FLAGS) $(ITEST_FLAGS)
$(COLLECT_ITEST_COVERAGE)
#? itest-clean: Kill all running itest processes
@ -249,12 +253,12 @@ unit-debug: $(BTCD_BIN)
$(UNIT_DEBUG)
#? unit-cover: Run unit tests in coverage mode
unit-cover: $(BTCD_BIN)
unit-cover: $(GOACC_BIN)
@$(call print, "Running unit coverage tests.")
$(UNIT_COVER)
$(GOACC)
#? unit-race: Run unit tests in race detector mode
unit-race: $(BTCD_BIN)
unit-race:
@$(call print, "Running unit race tests.")
env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(UNIT_RACE)
@ -267,18 +271,18 @@ unit-bench: $(BTCD_BIN)
# FLAKE HUNTING
# =============
#? flakehunter-itest: Run the integration tests continuously until one fails
flakehunter-itest: build-itest
#? flakehunter: Run the integration tests continuously until one fails
flakehunter: build-itest
@$(call print, "Flake hunting ${backend} integration tests.")
while [ $$? -eq 0 ]; do make itest-only icase='${icase}' backend='${backend}'; done
#? flakehunter-unit: Run the unit tests continuously until one fails
flakehunter-unit:
@$(call print, "Flake hunting unit test.")
scripts/unit-test-flake-hunter.sh ${pkg} ${case}
#? flake-unit: Run the unit tests continuously until one fails
flake-unit:
@$(call print, "Flake hunting unit tests.")
while [ $$? -eq 0 ]; do GOTRACEBACK=all $(UNIT) -count=1; done
#? flakehunter-itest-parallel: Run the integration tests continuously until one fails, running up to ITEST_PARALLELISM test tranches in parallel (default 4)
flakehunter-itest-parallel:
#? flakehunter-parallel: Run the integration tests continuously until one fails, running up to ITEST_PARALLELISM test tranches in parallel (default 4)
flakehunter-parallel:
@$(call print, "Flake hunting ${backend} integration tests in parallel.")
while [ $$? -eq 0 ]; do make itest-parallel tranches=1 parallel=${ITEST_PARALLELISM} icase='${icase}' backend='${backend}'; done
@ -323,7 +327,7 @@ check-go-version: check-go-version-dockerfile check-go-version-yaml
#? lint-source: Run static code analysis
lint-source: docker-tools
@$(call print, "Linting source.")
$(DOCKER_TOOLS) custom-gcl run -v $(LINT_WORKERS)
$(DOCKER_TOOLS) golangci-lint run -v $(LINT_WORKERS)
#? lint: Run static code analysis
lint: check-go-version lint-source
@ -355,11 +359,6 @@ help: Makefile
@$(call print, "Listing commands:")
@sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /'
#? backwards-compat-test: Run basic backwards compatibility test
backwards-compat-test:
@$(call print, "Running backwards compatability test")
./scripts/bw-compatibility-test/test.sh
#? sqlc: Generate sql models and queries in Go
sqlc:
@$(call print, "Generating sql models and queries in Go")
@ -404,7 +403,7 @@ mobile-rpc:
#? vendor: Create a vendor directory with all dependencies
vendor:
@$(call print, "Re-creating vendor directory.")
rm -r vendor/; $(GOCC) mod vendor
rm -r vendor/; go mod vendor
#? apple: Build mobile RPC stubs and project template for iOS and macOS
apple: mobile-rpc

154
README.md
View File

@ -1,101 +1,89 @@
## Lightning Network Daemon
# BTCPayServer LND
[![Release build](https://github.com/lightningnetwork/lnd/actions/workflows/release.yaml/badge.svg)](https://github.com/lightningnetwork/lnd/actions/workflows/release.yaml)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/lightningnetwork/lnd/blob/master/LICENSE)
[![Irc](https://img.shields.io/badge/chat-on%20libera-brightgreen.svg)](https://web.libera.chat/#lnd)
[![Godoc](https://godoc.org/github.com/lightningnetwork/lnd?status.svg)](https://godoc.org/github.com/lightningnetwork/lnd)
[![Go Report Card](https://goreportcard.com/badge/github.com/lightningnetwork/lnd)](https://goreportcard.com/report/github.com/lightningnetwork/lnd)
This repository is used to build LND Docker container images that are distributed with BTCPayServer by default.
<img src="logo.png">
Docker images are published to https://hub.docker.com/r/btcpayserver/lnd/
The Lightning Network Daemon (`lnd`) - is a complete implementation of a
[Lightning Network](https://lightning.network) node. `lnd` has several pluggable back-end
chain services including [`btcd`](https://github.com/btcsuite/btcd) (a
full-node), [`bitcoind`](https://github.com/bitcoin/bitcoin), and
[`neutrino`](https://github.com/lightninglabs/neutrino) (a new experimental light client). The project's codebase uses the
[btcsuite](https://github.com/btcsuite/) set of Bitcoin libraries, and also
exports a large set of isolated re-usable Lightning Network related libraries
within it. In the current state `lnd` is capable of:
* Creating channels.
* Closing channels.
* Completely managing all channel states (including the exceptional ones!).
* Maintaining a fully authenticated+validated channel graph.
* Performing path finding within the network, passively forwarding incoming payments.
* Sending outgoing [onion-encrypted payments](https://github.com/lightningnetwork/lightning-onion)
through the network.
* Updating advertised fee schedules.
* Automatic channel management ([`autopilot`](https://github.com/lightningnetwork/lnd/tree/master/autopilot)).
Versions:
- [0.18.3-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.18.3-beta/images/sha256-513ddd55a5af44a14e27110ee14cb28f1c7a69205bcaa2fba4e66275c1f725e5?context=repo)
- Includes 0.28.7-beta Loop
- [Fix for lnd unlock password \n problem](https://github.com/btcpayserver/lnd/pull/7)
- [0.18.1-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.18.1-beta/images/sha256-5fbfa76a218ab59bf9206485f4c0c071a525f9f0906255a5672054741d043b79?context=repo)
- Includes 0.28.5-beta Loop
- [0.18.0-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.18.0-beta/images/sha256-e6043dddf0bdbd5c740e882447c441b37f87f2c736ebb08747a4aff5e100d9bf?context=repo)
- Includes 0.28.2-beta Loop
- [0.17.4-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.17.4-beta/images/sha256-b62ecff5ca71d37f9b4846f35b4d86ddc4faa3fc1dd0618ae9221d99f47708bd?context=explore)
- Includes 0.26.6-beta Loop
- [0.17.3-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.17.3-beta/images/sha256-141611de6c062835e9513dd1ec4155c779d7a7b55258eb1fe06e228b0835fa56?context=repo)
- Includes 0.26.6-beta Loop
- [0.17.2-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.17.2-beta/images/sha256-936767369b703a67daf6db6a008a3b53c15f407d29a7ad2327a0de28f5951b30?context=explore)
- Includes 0.26.5-beta Loop
- [0.17.1-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.17.1-beta/images/sha256-b5c106136bd33a422463c736a1db8bd3541f95ac6f277dae86ab2a01b0c3445a?context=explore)
- Includes 0.26.5-beta Loop
- [0.17.0-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.17.0-beta/images/sha256-58b98f983cd786bcb4d48ea8586144cafd44d58dc3018e26bfbfcf875f495368?context=explore)
- Includes 0.26.4-beta Loop
- [0.17.0-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.17.0-beta/images/sha256-58b98f983cd786bcb4d48ea8586144cafd44d58dc3018e26bfbfcf875f495368?context=explore)
- Includes 0.26.4-beta Loop
- [0.16.4-beta-1](https://hub.docker.com/layers/btcpayserver/lnd/v0.16.4-beta-1/images/sha256-9dd204b62d6c892485b3dd8a76e8f48545ceda5702c9d47329ba4bcbc535a8b4?context=explore)
- [0.16.3-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.16.3-beta/images/sha256-9ff34769378cfca18664c7d1da3747e7ad7fb7f38a9a7b82a3d4f85e5bfef7bf?context=explore)
- [0.16.2-beta-1](https://hub.docker.com/layers/btcpayserver/lnd/v0.16.2-beta-1/images/sha256-bfff9de84a0a4af9d643ff555125358861b70374976b970cc00d1e7fc44ed520?context=explore)
- [0.16.1-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.16.0-beta/images/sha256-f0eb70c20691aaa2ffc34fd5bd6c284299c84e96152cda5e46882a3aa4a3c6a2?context=explore)
- [0.16.0-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.16.0-beta/images/sha256-f0eb70c20691aaa2ffc34fd5bd6c284299c84e96152cda5e46882a3aa4a3c6a2?context=explore)
- [0.15.4-beta](https://hub.docker.com/layers/btcpayserver/lnd/v0.15.4-beta-1/images/sha256-cadbbff93cf36146e24fa4f32170b4b9d278a2e1acfdc50470790a94506ee9c3?context=explore)
- [Other versions are tagged](https://github.com/btcpayserver/lnd/tags), but obsoleted and not supported.
- All LND versions prior to 0.15.4 contain a consensus bug that prevents them from properly parsing transactions with more than 500,000 witness items per input (https://github.com/btcsuite/btcd/issues/1906)
- All LND versions prior to 0.15.2 contain a bug that prevents them from properly parsing Taproot transactions with script size over 11000 bytes (https://github.com/lightningnetwork/lnd/issues/7002)
- LND version 0.14.0-beta shipped with check that made it incompatable with c-lightning and eclair (https://github.com/lightningnetwork/lnd/issues/5890)
- All LND versions prior to 0.13.3 contain specification-level vulnerability (https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003257.html)
- All LND versions prior to 0.7 contain critical vulnerability (https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-September/002174.html)
## Lightning Network Specification Compliance
`lnd` _fully_ conforms to the [Lightning Network specification
(BOLTs)](https://github.com/lightningnetwork/lightning-rfc). BOLT stands for:
Basis of Lightning Technology. The specifications are currently being drafted
by several groups of implementers based around the world including the
developers of `lnd`. The set of specification documents as well as our
implementation of the specification are still a work-in-progress. With that
said, the current status of `lnd`'s BOLT compliance is:
Each version is marked with appropriate `basedon-vX.X.X-beta` tags. We are using `basedon` prefix in order not to conflict with LND tags from source repository.
- [X] BOLT 1: Base Protocol
- [X] BOLT 2: Peer Protocol for Channel Management
- [X] BOLT 3: Bitcoin Transaction and Script Formats
- [X] BOLT 4: Onion Routing Protocol
- [X] BOLT 5: Recommendations for On-chain Transaction Handling
- [X] BOLT 7: P2P Node and Channel Discovery
- [X] BOLT 8: Encrypted and Authenticated Transport
- [X] BOLT 9: Assigned Feature Flags
- [X] BOLT 10: DNS Bootstrap and Assisted Node Location
- [X] BOLT 11: Invoice Protocol for Lightning Payments
## Updating LND version in BTCPay Server
## Developer Resources
1. **Update https://github.com/btcpayserver/lnd**
The daemon has been designed to be as developer friendly as possible in order
to facilitate application development on top of `lnd`. Two primary RPC
interfaces are exported: an HTTP REST API, and a [gRPC](https://grpc.io/)
service. The exported APIs are not yet stable, so be warned: they may change
drastically in the near future.
a) Go to https://github.com/lightningnetwork/lnd/releases and find the commit on which we should add our resources.
b) Checkout a new branch for that commit, usually in the format of `lnd/v0.18.3-beta`.
c) Cherry-pick the `Adding BtcPayServer related files and resources` commit. [Example commit](https://github.com/btcpayserver/lnd/commit/ae4bb33c6a3db8b7cc01d18fdf46e600ead9bed4).
d) Tag it with the `basedon-v*` prefix name and push it. For v0.18.1, the tag name was `basedon-v0.18.3-beta`.
i. Before you push the tag to CircleCI to build and publish image to Docker Hub, you can test if building the image works locally.
ii. You can do this for linuxamd64 for example by using command `docker build --pull -t local-lnd:test_version -f linuxamd64.Dockerfile .`
e) The build process will start (it [matches on tag format](.circleci/config.yml#L11)). Here is [an example CircleCI build](https://app.circleci.com/pipelines/github/btcpayserver/lnd/202/workflows/b90b5888-c0b8-4207-860e-a63ce21077af).
f) The resulting image will be published to Docker Hub. Example [Docker Hub image for v0.18.3](https://hub.docker.com/layers/btcpayserver/lnd/v0.18.3-beta/images/sha256-513ddd55a5af44a14e27110ee14cb28f1c7a69205bcaa2fba4e66275c1f725e5?context=repo).
An automatically generated set of documentation for the RPC APIs can be found
at [api.lightning.community](https://api.lightning.community). A set of developer
resources including guides, articles, example applications and community resources can be found at:
[docs.lightning.engineering](https://docs.lightning.engineering).
Occasionally, there are problems with:
- Versioning of base Docker images used for building Go binaries. You may need to bump that base image - [example commit](https://github.com/btcpayserver/lnd/commit/c841954c515a9d067c24987291316b093b91c2f2).
- [Updating Loop](https://github.com/lightninglabs/loop) as part of the package, which needs to happen occasionally. [Example bump of Loop version](https://github.com/btcpayserver/lnd/commit/b3aecc7ac58280ef662e39ba99461573a30fe79a
Finally, we also have an active
[Slack](https://lightning.engineering/slack.html) where protocol developers, application developers, testers and users gather to
discuss various aspects of `lnd` and also Lightning in general.
3. **Update https://github.com/btcpayserver/BTCPayServer.Lightning**
First-time contributors are [highly encouraged to start with code review
first](docs/review.md), before creating their own Pull Requests.
Now we need to update the dependency in our Lightning library project. This library has tests, so we will know if something is broken.
## Installation
In order to build from source, please see [the installation
instructions](docs/INSTALL.md).
a) Modify the `docker-compose.yml` file to reference the new LND version. [Example](https://github.com/btcpayserver/BTCPayServer.Lightning/pull/162/commits/413784ef9b2a8e7aa0496eb91f792ff0086c0ef7).
b) Checkout a new branch for that commit, usually in the format of `feat/lnd-0.18.1`.
c) Title the commit `Bumping LND to 0.18.1-beta`.
d) Open a pull request and reference Docker Hub and Tag. [Example PR](https://github.com/btcpayserver/BTCPayServer.Lightning/pull/162).
e) Once tests pass, you can merge it.
## Docker
To run lnd from Docker, please see the main [Docker instructions](docs/DOCKER.md)
4. **Update https://github.com/btcpayserver/btcpayserver**
## IRC
* irc.libera.chat
* channel #lnd
* [webchat](https://web.libera.chat/#lnd)
This will give access to LND to the whole dev team and allow for further testing on their dev machines if everything works as expected.
## Safety
a) Modify 4 `docker-compose.yml` files in `BTCPayServer.Tests`. [Example pull request to emulate](https://github.com/btcpayserver/btcpayserver/pull/6795).
b) When you open the PR, include the version and link to the BTCPayServer.Lightning PR.
c) Once tests pass, you can merge it.
When operating a mainnet `lnd` node, please refer to our [operational safety
guidelines](docs/safety.md). It is important to note that `lnd` is still
**beta** software and that ignoring these operational guidelines can lead to
loss of funds.
5. **Update https://github.com/btcpayserver/btcpayserver-docker**
## Security
a) Now that everything is prepared, open a PR in the btcpayserver-docker repository to allow these changes to propagate to everyone. [Example pull request](https://github.com/btcpayserver/btcpayserver-docker/pull/911).
b) Open the PR in DRAFT mode and tag @NicolasDorier and @Pavlenex as reviewers. They typically handle releases, and once they test that the LND version update works on their server, they can ACK the update and merge it as part of the release process.
The developers of `lnd` take security _very_ seriously. The disclosure of
security vulnerabilities helps us secure the health of `lnd`, privacy of our
users, and also the health of the Lightning Network as a whole. If you find
any issues regarding security or privacy, please disclose the information
responsibly by sending an email to security at lightning dot engineering,
preferably encrypted using our designated PGP key
(`91FE464CD75101DA6B6BAB60555C6465E5BCB3AF`) which can be found
[here](https://gist.githubusercontent.com/Roasbeef/6fb5b52886183239e4aa558f83d085d3/raw/5fa96010af201628bcfa61e9309d9b13d23d220f/security@lightning.engineering).
## Source repository
## Further reading
* [Step-by-step send payment guide with docker](https://github.com/lightningnetwork/lnd/tree/master/docker)
* [Contribution guide](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md)
https://github.com/lightningnetwork/lnd
## Links
* [BTCPayServer main repo](https://github.com/btcpayserver/btcpayserver)
* [BTCPayServer-Docker repo](https://github.com/btcpayserver/btcpayserver-docker)
* [BTCPayServer.Lightning](https://github.com/btcpayserver/BTCPayServer.Lightning)

View File

@ -1,664 +0,0 @@
package lnd
import (
"context"
"fmt"
"maps"
"sync"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btclog/v2"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnutils"
)
// accessMan is responsible for managing the server's access permissions.
type accessMan struct {
cfg *accessManConfig
// banScoreMtx is used for the server's ban tracking. If the server
// mutex is also going to be locked, ensure that this is locked after
// the server mutex.
banScoreMtx sync.RWMutex
// peerChanInfo is a mapping from remote public key to {bool, uint64}
// where the bool indicates that we have an open/closed channel with the
// peer and where the uint64 indicates the number of pending-open
// channels we currently have with them. This mapping will be used to
// determine access permissions for the peer. The map key is the
// string-version of the serialized public key.
//
// NOTE: This MUST be accessed with the banScoreMtx held.
peerChanInfo map[string]channeldb.ChanCount
// peerScores stores each connected peer's access status. The map key
// is the string-version of the serialized public key.
//
// NOTE: This MUST be accessed with the banScoreMtx held.
//
// TODO(yy): unify `peerScores` and `peerChanInfo` - there's no need to
// create two maps tracking essentially the same info. `numRestricted`
// can also be derived from `peerChanInfo`.
peerScores map[string]peerSlotStatus
// numRestricted tracks the number of peers with restricted access in
// peerScores. This MUST be accessed with the banScoreMtx held.
numRestricted int64
}
type accessManConfig struct {
// initAccessPerms checks the channeldb for initial access permissions
// and then populates the peerChanInfo and peerScores maps.
initAccessPerms func() (map[string]channeldb.ChanCount, error)
// shouldDisconnect determines whether we should disconnect a peer or
// not.
shouldDisconnect func(*btcec.PublicKey) (bool, error)
// maxRestrictedSlots is the number of restricted slots we'll allocate.
maxRestrictedSlots int64
}
func newAccessMan(cfg *accessManConfig) (*accessMan, error) {
a := &accessMan{
cfg: cfg,
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
counts, err := a.cfg.initAccessPerms()
if err != nil {
return nil, err
}
// We'll populate the server's peerChanInfo map with the counts fetched
// via initAccessPerms. Also note that we haven't yet connected to the
// peers.
maps.Copy(a.peerChanInfo, counts)
acsmLog.Info("Access Manager initialized")
return a, nil
}
// hasPeer checks whether a given peer already exists in the internal maps.
func (a *accessMan) hasPeer(ctx context.Context,
pub string) (peerAccessStatus, bool) {
// Lock banScoreMtx for reading so that we can read the banning maps
// below.
a.banScoreMtx.RLock()
defer a.banScoreMtx.RUnlock()
count, found := a.peerChanInfo[pub]
if found {
if count.HasOpenOrClosedChan {
acsmLog.DebugS(ctx, "Peer has open/closed channel, "+
"assigning protected access")
// Exit early if the peer is no longer restricted.
return peerStatusProtected, true
}
if count.PendingOpenCount != 0 {
acsmLog.DebugS(ctx, "Peer has pending channel(s), "+
"assigning temporary access")
// Exit early if the peer is no longer restricted.
return peerStatusTemporary, true
}
return peerStatusRestricted, true
}
// Check if the peer is found in the scores map.
status, found := a.peerScores[pub]
if found {
acsmLog.DebugS(ctx, "Peer already has access", "access",
status.state)
return status.state, true
}
return peerStatusRestricted, false
}
// assignPeerPerms assigns a new peer its permissions. This does not track the
// access in the maps. This is intentional.
func (a *accessMan) assignPeerPerms(remotePub *btcec.PublicKey) (
peerAccessStatus, error) {
ctx := btclog.WithCtx(
context.TODO(), lnutils.LogPubKey("peer", remotePub),
)
peerMapKey := string(remotePub.SerializeCompressed())
acsmLog.DebugS(ctx, "Assigning permissions")
// Default is restricted unless the below filters say otherwise.
access, peerExist := a.hasPeer(ctx, peerMapKey)
// Exit early if the peer is not restricted.
if access != peerStatusRestricted {
return access, nil
}
// If we are here, it means the peer has peerStatusRestricted.
//
// Check whether this peer is banned.
shouldDisconnect, err := a.cfg.shouldDisconnect(remotePub)
if err != nil {
acsmLog.ErrorS(ctx, "Error checking disconnect status", err)
// Access is restricted here.
return access, err
}
if shouldDisconnect {
acsmLog.WarnS(ctx, "Peer is banned, assigning restricted access",
ErrGossiperBan)
// Access is restricted here.
return access, ErrGossiperBan
}
// If we've reached this point and access hasn't changed from
// restricted, then we need to check if we even have a slot for this
// peer.
acsmLog.DebugS(ctx, "Peer has no channels, assigning restricted access")
// If this is an existing peer, there's no need to check for slot limit.
if peerExist {
acsmLog.DebugS(ctx, "Skipped slot check for existing peer")
return access, nil
}
a.banScoreMtx.RLock()
defer a.banScoreMtx.RUnlock()
if a.numRestricted >= a.cfg.maxRestrictedSlots {
acsmLog.WarnS(ctx, "No more restricted slots available, "+
"denying peer", ErrNoMoreRestrictedAccessSlots,
"num_restricted", a.numRestricted, "max_restricted",
a.cfg.maxRestrictedSlots)
return access, ErrNoMoreRestrictedAccessSlots
}
return access, nil
}
// newPendingOpenChan is called after the pending-open channel has been
// committed to the database. This may transition a restricted-access peer to a
// temporary-access peer.
func (a *accessMan) newPendingOpenChan(remotePub *btcec.PublicKey) error {
a.banScoreMtx.Lock()
defer a.banScoreMtx.Unlock()
ctx := btclog.WithCtx(
context.TODO(), lnutils.LogPubKey("peer", remotePub),
)
acsmLog.DebugS(ctx, "Processing new pending open channel")
peerMapKey := string(remotePub.SerializeCompressed())
// Fetch the peer's access status from peerScores.
status, found := a.peerScores[peerMapKey]
if !found {
acsmLog.ErrorS(ctx, "Peer score not found", ErrNoPeerScore)
// If we didn't find the peer, we'll return an error.
return ErrNoPeerScore
}
switch status.state {
case peerStatusProtected:
acsmLog.DebugS(ctx, "Peer already protected, no change")
// If this peer's access status is protected, we don't need to
// do anything.
return nil
case peerStatusTemporary:
// If this peer's access status is temporary, we'll need to
// update the peerChanInfo map. The peer's access status will
// stay temporary.
peerCount, found := a.peerChanInfo[peerMapKey]
if !found {
// Error if we did not find any info in peerChanInfo.
acsmLog.ErrorS(ctx, "Pending peer info not found",
ErrNoPendingPeerInfo)
return ErrNoPendingPeerInfo
}
// Increment the pending channel amount.
peerCount.PendingOpenCount += 1
a.peerChanInfo[peerMapKey] = peerCount
acsmLog.DebugS(ctx, "Peer is temporary, incremented "+
"pending count",
"pending_count", peerCount.PendingOpenCount)
case peerStatusRestricted:
// If the peer's access status is restricted, then we can
// transition it to a temporary-access peer. We'll need to
// update numRestricted and also peerScores. We'll also need to
// update peerChanInfo.
peerCount := channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 1,
}
a.peerChanInfo[peerMapKey] = peerCount
// A restricted-access slot has opened up.
oldRestricted := a.numRestricted
a.numRestricted -= 1
a.peerScores[peerMapKey] = peerSlotStatus{
state: peerStatusTemporary,
}
acsmLog.InfoS(ctx, "Peer transitioned restricted -> "+
"temporary (pending open)",
"old_restricted", oldRestricted,
"new_restricted", a.numRestricted)
default:
// This should not be possible.
err := fmt.Errorf("invalid peer access status %v for %x",
status.state, peerMapKey)
acsmLog.ErrorS(ctx, "Invalid peer access status", err)
return err
}
return nil
}
// newPendingCloseChan is called when a pending-open channel prematurely closes
// before the funding transaction has confirmed. This potentially demotes a
// temporary-access peer to a restricted-access peer. If no restricted-access
// slots are available, the peer will be disconnected.
func (a *accessMan) newPendingCloseChan(remotePub *btcec.PublicKey) error {
a.banScoreMtx.Lock()
defer a.banScoreMtx.Unlock()
ctx := btclog.WithCtx(
context.TODO(), lnutils.LogPubKey("peer", remotePub),
)
acsmLog.DebugS(ctx, "Processing pending channel close")
peerMapKey := string(remotePub.SerializeCompressed())
// Fetch the peer's access status from peerScores.
status, found := a.peerScores[peerMapKey]
if !found {
acsmLog.ErrorS(ctx, "Peer score not found", ErrNoPeerScore)
return ErrNoPeerScore
}
switch status.state {
case peerStatusProtected:
// If this peer is protected, we don't do anything.
acsmLog.DebugS(ctx, "Peer is protected, no change")
return nil
case peerStatusTemporary:
// If this peer is temporary, we need to check if it will
// revert to a restricted-access peer.
peerCount, found := a.peerChanInfo[peerMapKey]
if !found {
acsmLog.ErrorS(ctx, "Pending peer info not found",
ErrNoPendingPeerInfo)
// Error if we did not find any info in peerChanInfo.
return ErrNoPendingPeerInfo
}
currentNumPending := peerCount.PendingOpenCount - 1
acsmLog.DebugS(ctx, "Peer is temporary, decrementing "+
"pending count",
"pending_count", currentNumPending)
if currentNumPending == 0 {
// Remove the entry from peerChanInfo.
delete(a.peerChanInfo, peerMapKey)
// If this is the only pending-open channel for this
// peer and it's getting removed, attempt to demote
// this peer to a restricted peer.
if a.numRestricted == a.cfg.maxRestrictedSlots {
// There are no available restricted slots, so
// we need to disconnect this peer. We leave
// this up to the caller.
acsmLog.WarnS(ctx, "Peer last pending "+
"channel closed: ",
ErrNoMoreRestrictedAccessSlots,
"num_restricted", a.numRestricted,
"max_restricted", a.cfg.maxRestrictedSlots)
return ErrNoMoreRestrictedAccessSlots
}
// Otherwise, there is an available restricted-access
// slot, so we can demote this peer.
a.peerScores[peerMapKey] = peerSlotStatus{
state: peerStatusRestricted,
}
// Update numRestricted.
oldRestricted := a.numRestricted
a.numRestricted++
acsmLog.InfoS(ctx, "Peer transitioned "+
"temporary -> restricted "+
"(last pending closed)",
"old_restricted", oldRestricted,
"new_restricted", a.numRestricted)
return nil
}
// Else, we don't need to demote this peer since it has other
// pending-open channels with us.
peerCount.PendingOpenCount = currentNumPending
a.peerChanInfo[peerMapKey] = peerCount
acsmLog.DebugS(ctx, "Peer still has other pending channels",
"pending_count", currentNumPending)
return nil
case peerStatusRestricted:
// This should not be possible. This indicates an error.
err := fmt.Errorf("invalid peer access state transition: "+
"pending close for restricted peer %x", peerMapKey)
acsmLog.ErrorS(ctx, "Invalid peer access state transition", err)
return err
default:
// This should not be possible.
err := fmt.Errorf("invalid peer access status %v for %x",
status.state, peerMapKey)
acsmLog.ErrorS(ctx, "Invalid peer access status", err)
return err
}
}
// newOpenChan is called when a pending-open channel becomes an open channel
// (i.e. the funding transaction has confirmed). If the remote peer is a
// temporary-access peer, it will be promoted to a protected-access peer.
func (a *accessMan) newOpenChan(remotePub *btcec.PublicKey) error {
a.banScoreMtx.Lock()
defer a.banScoreMtx.Unlock()
ctx := btclog.WithCtx(
context.TODO(), lnutils.LogPubKey("peer", remotePub),
)
acsmLog.DebugS(ctx, "Processing new open channel")
peerMapKey := string(remotePub.SerializeCompressed())
// Fetch the peer's access status from peerScores.
status, found := a.peerScores[peerMapKey]
if !found {
// If we didn't find the peer, we'll return an error.
acsmLog.ErrorS(ctx, "Peer score not found", ErrNoPeerScore)
return ErrNoPeerScore
}
switch status.state {
case peerStatusProtected:
acsmLog.DebugS(ctx, "Peer already protected, no change")
// If the peer's state is already protected, we don't need to do
// anything more.
return nil
case peerStatusTemporary:
// If the peer's state is temporary, we'll upgrade the peer to
// a protected peer.
peerCount, found := a.peerChanInfo[peerMapKey]
if !found {
// Error if we did not find any info in peerChanInfo.
acsmLog.ErrorS(ctx, "Pending peer info not found",
ErrNoPendingPeerInfo)
return ErrNoPendingPeerInfo
}
peerCount.HasOpenOrClosedChan = true
peerCount.PendingOpenCount -= 1
a.peerChanInfo[peerMapKey] = peerCount
newStatus := peerSlotStatus{
state: peerStatusProtected,
}
a.peerScores[peerMapKey] = newStatus
acsmLog.InfoS(ctx, "Peer transitioned temporary -> "+
"protected (channel opened)")
return nil
case peerStatusRestricted:
// This should not be possible. For the server to receive a
// state-transition event via NewOpenChan, the server must have
// previously granted this peer "temporary" access. This
// temporary access would not have been revoked or downgraded
// without `CloseChannel` being called with the pending
// argument set to true. This means that an open-channel state
// transition would be impossible. Therefore, we can return an
// error.
err := fmt.Errorf("invalid peer access status: new open "+
"channel for restricted peer %x", peerMapKey)
acsmLog.ErrorS(ctx, "Invalid peer access status", err)
return err
default:
// This should not be possible.
err := fmt.Errorf("invalid peer access status %v for %x",
status.state, peerMapKey)
acsmLog.ErrorS(ctx, "Invalid peer access status", err)
return err
}
}
// checkAcceptIncomingConn checks whether, given the remote's public hex-
// encoded key, we should not accept this incoming connection or immediately
// disconnect. This does not assign to the server's peerScores maps. This is
// just an inbound filter that the brontide listeners use.
//
// TODO(yy): We should also consider removing this `checkAcceptIncomingConn`
// check as a) it doesn't check for ban score; and b) we should, and already
// have this check when we handle incoming connection in `InboundPeerConnected`.
func (a *accessMan) checkAcceptIncomingConn(remotePub *btcec.PublicKey) (
bool, error) {
ctx := btclog.WithCtx(
context.TODO(), lnutils.LogPubKey("peer", remotePub),
)
peerMapKey := string(remotePub.SerializeCompressed())
acsmLog.TraceS(ctx, "Checking incoming connection ban score")
a.banScoreMtx.RLock()
defer a.banScoreMtx.RUnlock()
_, found := a.peerChanInfo[peerMapKey]
// Exit early if found.
if found {
acsmLog.DebugS(ctx, "Peer found (protected/temporary), "+
"accepting")
return true, nil
}
_, found = a.peerScores[peerMapKey]
// Exit early if found.
if found {
acsmLog.DebugS(ctx, "Found existing peer, accepting")
return true, nil
}
acsmLog.DebugS(ctx, "Peer not found in counts, checking restricted "+
"slots")
// Check numRestricted to see if there is an available slot. In
// the future, it's possible to add better heuristics.
if a.numRestricted < a.cfg.maxRestrictedSlots {
// There is an available slot.
acsmLog.DebugS(ctx, "Restricted slot available, accepting ",
"num_restricted", a.numRestricted, "max_restricted",
a.cfg.maxRestrictedSlots)
return true, nil
}
// If there are no slots left, then we reject this connection.
acsmLog.WarnS(ctx, "No restricted slots available, rejecting ",
ErrNoMoreRestrictedAccessSlots, "num_restricted",
a.numRestricted, "max_restricted", a.cfg.maxRestrictedSlots)
return false, ErrNoMoreRestrictedAccessSlots
}
// addPeerAccess tracks a peer's access in the maps. This should be called when
// the peer has fully connected.
func (a *accessMan) addPeerAccess(remotePub *btcec.PublicKey,
access peerAccessStatus, inbound bool) {
ctx := btclog.WithCtx(
context.TODO(), lnutils.LogPubKey("peer", remotePub),
)
acsmLog.DebugS(ctx, "Adding peer access", "access", access)
// Add the remote public key to peerScores.
a.banScoreMtx.Lock()
defer a.banScoreMtx.Unlock()
peerMapKey := string(remotePub.SerializeCompressed())
// Exit early if this is an existing peer, which means it won't take
// another slot.
_, found := a.peerScores[peerMapKey]
if found {
acsmLog.DebugS(ctx, "Skipped taking restricted slot for "+
"existing peer")
return
}
a.peerScores[peerMapKey] = peerSlotStatus{state: access}
// Exit early if this is not a restricted peer.
if access != peerStatusRestricted {
acsmLog.DebugS(ctx, "Skipped taking restricted slot as peer "+
"already has access", "access", access)
return
}
// Increment numRestricted if this is an inbound connection.
if inbound {
oldRestricted := a.numRestricted
a.numRestricted++
acsmLog.DebugS(ctx, "Incremented restricted slots",
"old_restricted", oldRestricted,
"new_restricted", a.numRestricted)
return
}
// Otherwise, this is a newly created outbound connection. We won't
// place any restriction on it, instead, we will do a hot upgrade here
// to move it from restricted to temporary.
peerCount := channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 0,
}
a.peerChanInfo[peerMapKey] = peerCount
a.peerScores[peerMapKey] = peerSlotStatus{
state: peerStatusTemporary,
}
acsmLog.InfoS(ctx, "Upgraded outbound peer: restricted -> temporary")
}
// removePeerAccess removes the peer's access from the maps. This should be
// called when the peer has been disconnected.
func (a *accessMan) removePeerAccess(ctx context.Context, peerPubKey string) {
acsmLog.DebugS(ctx, "Removing access:")
a.banScoreMtx.Lock()
defer a.banScoreMtx.Unlock()
status, found := a.peerScores[peerPubKey]
if !found {
acsmLog.InfoS(ctx, "Peer score not found during removal")
return
}
if status.state == peerStatusRestricted {
// If the status is restricted, then we decrement from
// numRestrictedSlots.
oldRestricted := a.numRestricted
a.numRestricted--
acsmLog.DebugS(ctx, "Decremented restricted slots",
"old_restricted", oldRestricted,
"new_restricted", a.numRestricted)
}
acsmLog.TraceS(ctx, "Deleting from peerScores:")
delete(a.peerScores, peerPubKey)
// We now check whether this peer has channels with us or not.
info, found := a.peerChanInfo[peerPubKey]
if !found {
acsmLog.DebugS(ctx, "Chan info not found during removal:")
return
}
// Exit early if the peer has channel(s) with us.
if info.HasOpenOrClosedChan {
acsmLog.DebugS(ctx, "Skipped removing peer with channels:")
return
}
// Skip removing the peer if it has pending open/close with us.
if info.PendingOpenCount != 0 {
acsmLog.DebugS(ctx, "Skipped removing peer with pending "+
"channels:")
return
}
// Given this peer has no channels with us, we can now remove it.
delete(a.peerChanInfo, peerPubKey)
acsmLog.TraceS(ctx, "Removed peer from peerChanInfo:")
}

View File

@ -1,814 +0,0 @@
package lnd
import (
"context"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/stretchr/testify/require"
)
// assertInboundConnection asserts that we're able to accept an inbound
// connection successfully without any access permissions being violated.
func assertInboundConnection(t *testing.T, a *accessMan,
remotePub *btcec.PublicKey, status peerAccessStatus) {
remotePubSer := string(remotePub.SerializeCompressed())
isSlotAvailable, err := a.checkAcceptIncomingConn(remotePub)
require.NoError(t, err)
require.True(t, isSlotAvailable)
peerAccess, err := a.assignPeerPerms(remotePub)
require.NoError(t, err)
require.Equal(t, status, peerAccess)
a.addPeerAccess(remotePub, peerAccess, true)
peerScore, ok := a.peerScores[remotePubSer]
require.True(t, ok)
require.Equal(t, status, peerScore.state)
}
func assertAccessState(t *testing.T, a *accessMan, remotePub *btcec.PublicKey,
expectedStatus peerAccessStatus) {
remotePubSer := string(remotePub.SerializeCompressed())
peerScore, ok := a.peerScores[remotePubSer]
require.True(t, ok)
require.Equal(t, expectedStatus, peerScore.state)
}
// TestAccessManRestrictedSlots tests that the configurable number of
// restricted slots are properly allocated. It also tests that certain peers
// with access permissions are allowed to bypass the slot mechanism.
func TestAccessManRestrictedSlots(t *testing.T) {
t.Parallel()
// We'll pre-populate the map to mock the database fetch. We'll make
// three peers. One has an open/closed channel. One has both an open
// / closed channel and a pending channel. The last one has only a
// pending channel.
peerPriv1, err := btcec.NewPrivateKey()
require.NoError(t, err)
peerKey1 := peerPriv1.PubKey()
peerKeySer1 := string(peerKey1.SerializeCompressed())
peerPriv2, err := btcec.NewPrivateKey()
require.NoError(t, err)
peerKey2 := peerPriv2.PubKey()
peerKeySer2 := string(peerKey2.SerializeCompressed())
peerPriv3, err := btcec.NewPrivateKey()
require.NoError(t, err)
peerKey3 := peerPriv3.PubKey()
peerKeySer3 := string(peerKey3.SerializeCompressed())
var (
peer1PendingCount = 0
peer2PendingCount = 1
peer3PendingCount = 1
)
initPerms := func() (map[string]channeldb.ChanCount, error) {
return map[string]channeldb.ChanCount{
peerKeySer1: {
HasOpenOrClosedChan: true,
PendingOpenCount: uint64(peer1PendingCount),
},
peerKeySer2: {
HasOpenOrClosedChan: true,
PendingOpenCount: uint64(peer2PendingCount),
},
peerKeySer3: {
HasOpenOrClosedChan: false,
PendingOpenCount: uint64(peer3PendingCount),
},
}, nil
}
disconnect := func(*btcec.PublicKey) (bool, error) {
return false, nil
}
cfg := &accessManConfig{
initAccessPerms: initPerms,
shouldDisconnect: disconnect,
maxRestrictedSlots: 1,
}
a, err := newAccessMan(cfg)
require.NoError(t, err)
// Check that the peerChanInfo map is correctly populated with three
// peers.
require.Equal(t, 0, int(a.numRestricted))
require.Equal(t, 3, len(a.peerChanInfo))
peerCount1, ok := a.peerChanInfo[peerKeySer1]
require.True(t, ok)
require.True(t, peerCount1.HasOpenOrClosedChan)
require.Equal(t, peer1PendingCount, int(peerCount1.PendingOpenCount))
peerCount2, ok := a.peerChanInfo[peerKeySer2]
require.True(t, ok)
require.True(t, peerCount2.HasOpenOrClosedChan)
require.Equal(t, peer2PendingCount, int(peerCount2.PendingOpenCount))
peerCount3, ok := a.peerChanInfo[peerKeySer3]
require.True(t, ok)
require.False(t, peerCount3.HasOpenOrClosedChan)
require.Equal(t, peer3PendingCount, int(peerCount3.PendingOpenCount))
// We'll now start to connect the peers. We'll add a new fourth peer
// that will take up the restricted slot. The first three peers should
// be able to bypass this restricted slot mechanism.
peerPriv4, err := btcec.NewPrivateKey()
require.NoError(t, err)
peerKey4 := peerPriv4.PubKey()
// Follow the normal process of an incoming connection. We check if we
// can accommodate this peer in checkAcceptIncomingConn and then we
// assign its access permissions and then insert into the map.
assertInboundConnection(t, a, peerKey4, peerStatusRestricted)
// Connect the three peers. This should happen without any issue.
assertInboundConnection(t, a, peerKey1, peerStatusProtected)
assertInboundConnection(t, a, peerKey2, peerStatusProtected)
assertInboundConnection(t, a, peerKey3, peerStatusTemporary)
// Check that a pending-open channel promotes the restricted peer.
err = a.newPendingOpenChan(peerKey4)
require.NoError(t, err)
assertAccessState(t, a, peerKey4, peerStatusTemporary)
// Assert that accessman's internal state is updated with peer4. We
// expect this new peer to have 1 pending open count.
peerCount4, ok := a.peerChanInfo[string(peerKey4.SerializeCompressed())]
require.True(t, ok)
require.False(t, peerCount4.HasOpenOrClosedChan)
require.Equal(t, 1, int(peerCount4.PendingOpenCount))
// Check that an open channel promotes the temporary peer.
err = a.newOpenChan(peerKey3)
require.NoError(t, err)
assertAccessState(t, a, peerKey3, peerStatusProtected)
// Assert that accessman's internal state is updated with peer3. We
// expect this existing peer to decrement its pending open count and the
// flag `HasOpenOrClosedChan` should be true.
peerCount3, ok = a.peerChanInfo[peerKeySer3]
require.True(t, ok)
require.True(t, peerCount3.HasOpenOrClosedChan)
require.Equal(t, peer3PendingCount-1, int(peerCount3.PendingOpenCount))
// We should be able to accommodate a new peer.
peerPriv5, err := btcec.NewPrivateKey()
require.NoError(t, err)
peerKey5 := peerPriv5.PubKey()
assertInboundConnection(t, a, peerKey5, peerStatusRestricted)
// Check that a pending-close channel event for peer 4 demotes the
// peer.
err = a.newPendingCloseChan(peerKey4)
require.ErrorIs(t, err, ErrNoMoreRestrictedAccessSlots)
// Assert that peer4 is removed.
_, ok = a.peerChanInfo[string(peerKey4.SerializeCompressed())]
require.False(t, ok)
}
// TestAssignPeerPerms asserts that the peer's access status is correctly
// assigned.
func TestAssignPeerPerms(t *testing.T) {
t.Parallel()
// genPeerPub is a helper closure that generates a random public key.
genPeerPub := func() *btcec.PublicKey {
peerPriv, err := btcec.NewPrivateKey()
require.NoError(t, err)
return peerPriv.PubKey()
}
disconnect := func(_ *btcec.PublicKey) (bool, error) {
return true, nil
}
noDisconnect := func(_ *btcec.PublicKey) (bool, error) {
return false, nil
}
var testCases = []struct {
name string
peerPub *btcec.PublicKey
chanCount channeldb.ChanCount
shouldDisconnect func(*btcec.PublicKey) (bool, error)
numRestricted int
expectedStatus peerAccessStatus
expectedErr error
}{
// peer1 has a channel with us, and we expect it to have a
// protected status.
{
name: "peer with channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: true,
},
shouldDisconnect: noDisconnect,
expectedStatus: peerStatusProtected,
expectedErr: nil,
},
// peer2 has a channel open and a pending channel with us, we
// expect it to have a protected status.
{
name: "peer with channels and pending channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: true,
PendingOpenCount: 1,
},
shouldDisconnect: noDisconnect,
expectedStatus: peerStatusProtected,
expectedErr: nil,
},
// peer3 has a pending channel with us, and we expect it to have
// a temporary status.
{
name: "peer with pending channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 1,
},
shouldDisconnect: noDisconnect,
expectedStatus: peerStatusTemporary,
expectedErr: nil,
},
// peer4 has no channel with us, and we expect it to have a
// restricted status.
{
name: "peer with no channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 0,
},
shouldDisconnect: noDisconnect,
expectedStatus: peerStatusRestricted,
expectedErr: nil,
},
// peer5 has no channel with us, and we expect it to have a
// restricted status. We also expect the error `ErrGossiperBan`
// to be returned given we will use a mocked `shouldDisconnect`
// in this test to disconnect on peer5 only.
{
name: "peer with no channels and banned",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 0,
},
shouldDisconnect: disconnect,
expectedStatus: peerStatusRestricted,
expectedErr: ErrGossiperBan,
},
// peer6 has no channel with us, and we expect it to have a
// restricted status. Since this peer is seen, we don't expect
// the error `ErrNoMoreRestrictedAccessSlots` to be returned.
{
name: "peer with no channels and restricted",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 0,
},
shouldDisconnect: noDisconnect,
numRestricted: 1,
expectedStatus: peerStatusRestricted,
expectedErr: nil,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
peerStr := string(tc.peerPub.SerializeCompressed())
initPerms := func() (map[string]channeldb.ChanCount,
error) {
return map[string]channeldb.ChanCount{
peerStr: tc.chanCount,
}, nil
}
cfg := &accessManConfig{
initAccessPerms: initPerms,
shouldDisconnect: tc.shouldDisconnect,
maxRestrictedSlots: 1,
}
a, err := newAccessMan(cfg)
require.NoError(t, err)
// Initialize the internal state of the accessman.
a.numRestricted = int64(tc.numRestricted)
status, err := a.assignPeerPerms(tc.peerPub)
require.Equal(t, tc.expectedStatus, status)
require.ErrorIs(t, tc.expectedErr, err)
})
}
}
// TestAssignPeerPermsBypassRestriction asserts that when a peer has a channel
// with us, either it being open, pending, or closed, no restriction is placed
// on this peer.
func TestAssignPeerPermsBypassRestriction(t *testing.T) {
t.Parallel()
// genPeerPub is a helper closure that generates a random public key.
genPeerPub := func() *btcec.PublicKey {
peerPriv, err := btcec.NewPrivateKey()
require.NoError(t, err)
return peerPriv.PubKey()
}
// Mock shouldDisconnect to always return true and assert that it has no
// effect on the peer.
disconnect := func(_ *btcec.PublicKey) (bool, error) {
return true, nil
}
var testCases = []struct {
name string
peerPub *btcec.PublicKey
chanCount channeldb.ChanCount
expectedStatus peerAccessStatus
}{
// peer1 has a channel with us, and we expect it to have a
// protected status.
{
name: "peer with channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: true,
},
expectedStatus: peerStatusProtected,
},
// peer2 has a channel open and a pending channel with us, we
// expect it to have a protected status.
{
name: "peer with channels and pending channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: true,
PendingOpenCount: 1,
},
expectedStatus: peerStatusProtected,
},
// peer3 has a pending channel with us, and we expect it to have
// a temporary status.
{
name: "peer with pending channels",
peerPub: genPeerPub(),
chanCount: channeldb.ChanCount{
HasOpenOrClosedChan: false,
PendingOpenCount: 1,
},
expectedStatus: peerStatusTemporary,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
peerStr := string(tc.peerPub.SerializeCompressed())
initPerms := func() (map[string]channeldb.ChanCount,
error) {
return map[string]channeldb.ChanCount{
peerStr: tc.chanCount,
}, nil
}
// Config the accessman such that it has zero max slots
// and always return true on `shouldDisconnect`. We
// should see the peers in this test are not affected by
// these checks.
cfg := &accessManConfig{
initAccessPerms: initPerms,
shouldDisconnect: disconnect,
maxRestrictedSlots: 0,
}
a, err := newAccessMan(cfg)
require.NoError(t, err)
status, err := a.assignPeerPerms(tc.peerPub)
require.NoError(t, err)
require.Equal(t, tc.expectedStatus, status)
})
}
}
// TestAssignPeerPermsBypassExisting asserts that when the peer is a
// pre-existing peer, it won't be restricted.
func TestAssignPeerPermsBypassExisting(t *testing.T) {
t.Parallel()
// genPeerPub is a helper closure that generates a random public key.
genPeerPub := func() *btcec.PublicKey {
peerPriv, err := btcec.NewPrivateKey()
require.NoError(t, err)
return peerPriv.PubKey()
}
// peer1 exists in `peerChanInfo` map.
peer1 := genPeerPub()
peer1Str := string(peer1.SerializeCompressed())
// peer2 exists in `peerScores` map.
peer2 := genPeerPub()
peer2Str := string(peer2.SerializeCompressed())
// peer3 is a new peer.
peer3 := genPeerPub()
// Create params to init the accessman.
initPerms := func() (map[string]channeldb.ChanCount, error) {
return map[string]channeldb.ChanCount{
peer1Str: {},
}, nil
}
disconnect := func(*btcec.PublicKey) (bool, error) {
return false, nil
}
cfg := &accessManConfig{
initAccessPerms: initPerms,
shouldDisconnect: disconnect,
maxRestrictedSlots: 0,
}
a, err := newAccessMan(cfg)
require.NoError(t, err)
// Add peer2 to the `peerScores`.
a.peerScores[peer2Str] = peerSlotStatus{
state: peerStatusTemporary,
}
// Assigning to peer1 should not return an error.
status, err := a.assignPeerPerms(peer1)
require.NoError(t, err)
require.Equal(t, peerStatusRestricted, status)
// Assigning to peer2 should not return an error.
status, err = a.assignPeerPerms(peer2)
require.NoError(t, err)
require.Equal(t, peerStatusTemporary, status)
// Assigning to peer3 should return an error.
status, err = a.assignPeerPerms(peer3)
require.ErrorIs(t, err, ErrNoMoreRestrictedAccessSlots)
require.Equal(t, peerStatusRestricted, status)
}
// TestHasPeer asserts `hasPeer` returns the correct results.
func TestHasPeer(t *testing.T) {
t.Parallel()
ctx := context.Background()
// Create a testing accessMan.
a := &accessMan{
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// peer1 exists with an open channel.
peer1 := "peer1"
a.peerChanInfo[peer1] = channeldb.ChanCount{
HasOpenOrClosedChan: true,
}
peer1Access := peerStatusProtected
// peer2 exists with a pending channel.
peer2 := "peer2"
a.peerChanInfo[peer2] = channeldb.ChanCount{
PendingOpenCount: 1,
}
peer2Access := peerStatusTemporary
// peer3 exists without any channels.
peer3 := "peer3"
a.peerChanInfo[peer3] = channeldb.ChanCount{}
peer3Access := peerStatusRestricted
// peer4 exists with a score.
peer4 := "peer4"
peer4Access := peerStatusTemporary
a.peerScores[peer4] = peerSlotStatus{state: peer4Access}
// peer5 doesn't exist.
peer5 := "peer5"
// We now assert `hasPeer` returns the correct results.
//
// peer1 should be found with peerStatusProtected.
access, found := a.hasPeer(ctx, peer1)
require.True(t, found)
require.Equal(t, peer1Access, access)
// peer2 should be found with peerStatusTemporary.
access, found = a.hasPeer(ctx, peer2)
require.True(t, found)
require.Equal(t, peer2Access, access)
// peer3 should be found with peerStatusRestricted.
access, found = a.hasPeer(ctx, peer3)
require.True(t, found)
require.Equal(t, peer3Access, access)
// peer4 should be found with peerStatusTemporary.
access, found = a.hasPeer(ctx, peer4)
require.True(t, found)
require.Equal(t, peer4Access, access)
// peer5 should NOT be found.
access, found = a.hasPeer(ctx, peer5)
require.False(t, found)
require.Equal(t, peerStatusRestricted, access)
}
// TestAddPeerAccessInbound asserts the num of slots is correctly incremented
// only for a new inbound peer with restricted access.
func TestAddPeerAccessInbound(t *testing.T) {
t.Parallel()
// Create a testing accessMan.
a := &accessMan{
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// Create a testing key.
priv, err := btcec.NewPrivateKey()
require.NoError(t, err)
pub := priv.PubKey()
pubStr := string(pub.SerializeCompressed())
// Add this peer as an inbound peer with peerStatusRestricted.
a.addPeerAccess(pub, peerStatusRestricted, true)
// Assert the accessMan's internal state.
//
// We expect to see one peer found in the score map, and one slot is
// taken, and this peer is not found in the counts map.
require.Len(t, a.peerScores, 1)
require.Equal(t, int64(1), a.numRestricted)
require.NotContains(t, a.peerChanInfo, pubStr)
// The peer should be found in the score map.
score, ok := a.peerScores[pubStr]
require.True(t, ok)
expecedScore := peerSlotStatus{state: peerStatusRestricted}
require.Equal(t, expecedScore, score)
// Add this peer again, we expect the available slots to stay unchanged.
a.addPeerAccess(pub, peerStatusRestricted, true)
// Assert the internal state is not changed.
require.Len(t, a.peerScores, 1)
require.Equal(t, int64(1), a.numRestricted)
require.NotContains(t, a.peerChanInfo, pubStr)
// Reset the accessMan.
a = &accessMan{
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// Add this peer as an inbound peer with peerStatusTemporary.
a.addPeerAccess(pub, peerStatusTemporary, true)
// Assert the accessMan's internal state.
//
// We expect to see one peer found in the score map, and no slot is
// taken since this peer is not restricted.
require.Len(t, a.peerScores, 1)
require.Equal(t, int64(0), a.numRestricted)
// NOTE: in reality this is not possible as the peer must have been put
// into the map `peerChanInfo` before its perm can be upgraded.
require.NotContains(t, a.peerChanInfo, pubStr)
// The peer should be found in the score map.
score, ok = a.peerScores[pubStr]
require.True(t, ok)
expecedScore = peerSlotStatus{state: peerStatusTemporary}
require.Equal(t, expecedScore, score)
}
// TestAddPeerAccessOutbound asserts that outbound peer is not restricted and
// its perm is upgraded when it has peerStatusRestricted.
func TestAddPeerAccessOutbound(t *testing.T) {
t.Parallel()
// Create a testing accessMan.
a := &accessMan{
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// Create a testing key.
priv, err := btcec.NewPrivateKey()
require.NoError(t, err)
pub := priv.PubKey()
pubStr := string(pub.SerializeCompressed())
// Add this peer as an outbound peer with peerStatusRestricted.
a.addPeerAccess(pub, peerStatusRestricted, false)
// Assert the accessMan's internal state.
//
// We expect to see one peer found in the score map, and no slot is
// taken, and this peer is found in the counts map.
require.Len(t, a.peerScores, 1)
require.Equal(t, int64(0), a.numRestricted)
require.Contains(t, a.peerChanInfo, pubStr)
// The peer should be found in the score map.
score, ok := a.peerScores[pubStr]
require.True(t, ok)
// Its perm should be upgraded to temporary.
expecedScore := peerSlotStatus{state: peerStatusTemporary}
require.Equal(t, expecedScore, score)
// The peer should be found in the peer counts map.
count, ok := a.peerChanInfo[pubStr]
require.True(t, ok)
// The peer's count should be initialized correctly.
require.Zero(t, count.PendingOpenCount)
require.False(t, count.HasOpenOrClosedChan)
// Add this peer again, we expect the available slots to stay unchanged.
a.addPeerAccess(pub, peerStatusRestricted, true)
// Assert the internal state is not changed.
require.Len(t, a.peerScores, 1)
require.Equal(t, int64(0), a.numRestricted)
require.Contains(t, a.peerChanInfo, pubStr)
// Reset the accessMan.
a = &accessMan{
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// Add this peer as an inbound peer with peerStatusTemporary.
a.addPeerAccess(pub, peerStatusTemporary, true)
// Assert the accessMan's internal state.
//
// We expect to see one peer found in the score map, and no slot is
// taken since this peer is not restricted.
require.Len(t, a.peerScores, 1)
require.Equal(t, int64(0), a.numRestricted)
// NOTE: in reality this is not possible as the peer must have been put
// into the map `peerChanInfo` before its perm can be upgraded.
require.NotContains(t, a.peerChanInfo, pubStr)
// The peer should be found in the score map.
score, ok = a.peerScores[pubStr]
require.True(t, ok)
expecedScore = peerSlotStatus{state: peerStatusTemporary}
require.Equal(t, expecedScore, score)
}
// TestRemovePeerAccess asserts `removePeerAccess` correctly update the
// accessman's internal state based on the peer's status.
func TestRemovePeerAccess(t *testing.T) {
t.Parallel()
ctx := context.Background()
// Create a testing accessMan.
a := &accessMan{
peerChanInfo: make(map[string]channeldb.ChanCount),
peerScores: make(map[string]peerSlotStatus),
}
// numRestrictedExpected specifies the final value to expect once the
// test finishes.
var numRestrictedExpected int
// peer1 exists with an open channel, which should not be removed. Since
// it has protected status, the numRestricted should stay unchanged.
peer1 := "peer1"
a.peerChanInfo[peer1] = channeldb.ChanCount{
HasOpenOrClosedChan: true,
}
peer1Access := peerStatusProtected
a.peerScores[peer1] = peerSlotStatus{state: peer1Access}
// peer2 exists with a pending channel, which should not be removed.
// Since it has temporary status, the numRestricted should stay
// unchanged.
peer2 := "peer2"
a.peerChanInfo[peer2] = channeldb.ChanCount{
PendingOpenCount: 1,
}
peer2Access := peerStatusTemporary
a.peerScores[peer2] = peerSlotStatus{state: peer2Access}
// peer3 exists without any channels, which will be removed. Since it
// has restricted status, the numRestricted should be decremented.
peer3 := "peer3"
a.peerChanInfo[peer3] = channeldb.ChanCount{}
peer3Access := peerStatusRestricted
a.peerScores[peer3] = peerSlotStatus{state: peer3Access}
numRestrictedExpected--
// peer4 exists with a score and a temporary status, which will be
// removed.
peer4 := "peer4"
peer4Access := peerStatusTemporary
a.peerScores[peer4] = peerSlotStatus{state: peer4Access}
// peer5 doesn't exist, removing it will be a NOOP.
peer5 := "peer5"
// We now assert `removePeerAccess` behaves as expected.
//
// Remove peer1 should change nothing.
a.removePeerAccess(ctx, peer1)
// peer1 should be removed from peerScores but not peerChanInfo.
_, found := a.peerScores[peer1]
require.False(t, found)
_, found = a.peerChanInfo[peer1]
require.True(t, found)
// Remove peer2 should change nothing.
a.removePeerAccess(ctx, peer2)
// peer2 should be removed from peerScores but not peerChanInfo.
_, found = a.peerScores[peer2]
require.False(t, found)
_, found = a.peerChanInfo[peer2]
require.True(t, found)
// Remove peer3 should remove it from the maps.
a.removePeerAccess(ctx, peer3)
// peer3 should be removed from peerScores and peerChanInfo.
_, found = a.peerScores[peer3]
require.False(t, found)
_, found = a.peerChanInfo[peer3]
require.False(t, found)
// Remove peer4 should remove it from the maps.
a.removePeerAccess(ctx, peer4)
// peer4 should be removed from peerScores and NOT be found in
// peerChanInfo.
_, found = a.peerScores[peer4]
require.False(t, found)
_, found = a.peerChanInfo[peer4]
require.False(t, found)
// Remove peer5 should be NOOP.
a.removePeerAccess(ctx, peer5)
// peer5 should NOT be found.
_, found = a.peerScores[peer5]
require.False(t, found)
_, found = a.peerChanInfo[peer5]
require.False(t, found)
// Finally, assert the numRestricted is decremented as expected. Given
// we only have peer3 which has restricted access, it should decrement
// once.
//
// NOTE: The value is actually negative here, which is allowed in
// accessman.
require.EqualValues(t, numRestrictedExpected, a.numRestricted)
}

View File

@ -3,14 +3,13 @@ package aliasmgr
import (
"encoding/binary"
"fmt"
"maps"
"slices"
"sync"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/htlcswitch/hop"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnwire"
"golang.org/x/exp/maps"
)
// UpdateLinkAliases is a function type for a function that locates the active
@ -433,9 +432,9 @@ func (m *Manager) DeleteLocalAlias(alias,
}
// We'll filter the alias set and remove the alias from it.
aliasSet = fn.Filter(aliasSet, func(a lnwire.ShortChannelID) bool {
aliasSet = fn.Filter(func(a lnwire.ShortChannelID) bool {
return a.ToUint64() != alias.ToUint64()
})
}, aliasSet)
// If the alias set is empty, we'll delete the base SCID from the
// baseToSet map.
@ -515,17 +514,11 @@ func (m *Manager) RequestAlias() (lnwire.ShortChannelID, error) {
// haveAlias returns true if the passed alias is already assigned to a
// channel in the baseToSet map.
haveAlias := func(maybeNextAlias lnwire.ShortChannelID) bool {
return fn.Any(
slices.Collect(maps.Values(m.baseToSet)),
func(aliasList []lnwire.ShortChannelID) bool {
return fn.Any(
aliasList,
func(alias lnwire.ShortChannelID) bool {
return alias == maybeNextAlias
},
)
},
)
return fn.Any(func(aliasList []lnwire.ShortChannelID) bool {
return fn.Any(func(alias lnwire.ShortChannelID) bool {
return alias == maybeNextAlias
}, aliasList)
}, maps.Values(m.baseToSet))
}
err := kvdb.Update(m.backend, func(tx kvdb.RwTx) error {

View File

@ -19,7 +19,6 @@ func TestAliasStorePeerAlias(t *testing.T) {
dbPath := filepath.Join(t.TempDir(), "testdb")
db, err := kvdb.Create(
kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
false,
)
require.NoError(t, err)
defer db.Close()
@ -53,7 +52,6 @@ func TestAliasStoreRequest(t *testing.T) {
dbPath := filepath.Join(t.TempDir(), "testdb")
db, err := kvdb.Create(
kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
false,
)
require.NoError(t, err)
defer db.Close()
@ -86,7 +84,6 @@ func TestAliasLifecycle(t *testing.T) {
dbPath := filepath.Join(t.TempDir(), "testdb")
db, err := kvdb.Create(
kvdb.BoltBackendName, dbPath, true, kvdb.DefaultDBTimeout,
false,
)
require.NoError(t, err)
defer db.Close()

View File

@ -2,7 +2,6 @@ package autopilot
import (
"bytes"
"context"
"fmt"
"math/rand"
"net"
@ -12,7 +11,6 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/lnwire"
)
@ -168,9 +166,8 @@ type Agent struct {
pendingOpens map[NodeID]LocalChannel
pendingMtx sync.Mutex
quit chan struct{}
wg sync.WaitGroup
cancel fn.Option[context.CancelFunc]
quit chan struct{}
wg sync.WaitGroup
}
// New creates a new instance of the Agent instantiated using the passed
@ -205,20 +202,17 @@ func New(cfg Config, initialState []LocalChannel) (*Agent, error) {
func (a *Agent) Start() error {
var err error
a.started.Do(func() {
ctx, cancel := context.WithCancel(context.Background())
a.cancel = fn.Some(cancel)
err = a.start(ctx)
err = a.start()
})
return err
}
func (a *Agent) start(ctx context.Context) error {
func (a *Agent) start() error {
rand.Seed(time.Now().Unix())
log.Infof("Autopilot Agent starting")
a.wg.Add(1)
go a.controller(ctx)
go a.controller()
return nil
}
@ -236,7 +230,6 @@ func (a *Agent) Stop() error {
func (a *Agent) stop() error {
log.Infof("Autopilot Agent stopping")
a.cancel.WhenSome(func(fn context.CancelFunc) { fn() })
close(a.quit)
a.wg.Wait()
@ -408,7 +401,7 @@ func mergeChanState(pendingChans map[NodeID]LocalChannel,
// and external state changes as a result of decisions it makes w.r.t channel
// allocation, or attributes affecting its control loop being updated by the
// backing Lightning Node.
func (a *Agent) controller(ctx context.Context) {
func (a *Agent) controller() {
defer a.wg.Done()
// We'll start off by assigning our starting balance, and injecting
@ -509,9 +502,6 @@ func (a *Agent) controller(ctx context.Context) {
// immediately.
case <-a.quit:
return
case <-ctx.Done():
return
}
a.pendingMtx.Lock()
@ -549,7 +539,7 @@ func (a *Agent) controller(ctx context.Context) {
log.Infof("Triggering attachment directive dispatch, "+
"total_funds=%v", a.totalBalance)
err := a.openChans(ctx, availableFunds, numChans, totalChans)
err := a.openChans(availableFunds, numChans, totalChans)
if err != nil {
log.Errorf("Unable to open channels: %v", err)
}
@ -558,8 +548,8 @@ func (a *Agent) controller(ctx context.Context) {
// openChans queries the agent's heuristic for a set of channel candidates, and
// attempts to open channels to them.
func (a *Agent) openChans(ctx context.Context, availableFunds btcutil.Amount,
numChans uint32, totalChans []LocalChannel) error {
func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32,
totalChans []LocalChannel) error {
// As channel size we'll use the maximum channel size available.
chanSize := a.cfg.Constraints.MaxChanSize()
@ -608,9 +598,7 @@ func (a *Agent) openChans(ctx context.Context, availableFunds btcutil.Amount,
selfPubBytes := a.cfg.Self.SerializeCompressed()
nodes := make(map[NodeID]struct{})
addresses := make(map[NodeID][]net.Addr)
if err := a.cfg.Graph.ForEachNode(ctx, func(_ context.Context,
node Node) error {
if err := a.cfg.Graph.ForEachNode(func(node Node) error {
nID := NodeID(node.PubKey())
// If we come across ourselves, them we'll continue in
@ -648,7 +636,7 @@ func (a *Agent) openChans(ctx context.Context, availableFunds btcutil.Amount,
// graph.
log.Debugf("Scoring %d nodes for chan_size=%v", len(nodes), chanSize)
scores, err := a.cfg.Heuristic.NodeScores(
ctx, a.cfg.Graph, totalChans, chanSize, nodes,
a.cfg.Graph, totalChans, chanSize, nodes,
)
if err != nil {
return fmt.Errorf("unable to calculate node scores : %w", err)

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"errors"
"fmt"
"net"
@ -86,9 +85,9 @@ func (m *mockHeuristic) Name() string {
return "mock"
}
func (m *mockHeuristic) NodeScores(_ context.Context, g ChannelGraph,
chans []LocalChannel, chanSize btcutil.Amount,
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
func (m *mockHeuristic) NodeScores(g ChannelGraph, chans []LocalChannel,
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
map[NodeID]*NodeScore, error) {
if m.nodeScoresArgs != nil {
directive := directiveArg{

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"fmt"
"sync"
)
@ -169,10 +168,8 @@ func betweennessCentrality(g *SimpleGraph, s int, centrality []float64) {
}
// Refresh recalculates and stores centrality values.
func (bc *BetweennessCentrality) Refresh(ctx context.Context,
graph ChannelGraph) error {
cache, err := NewSimpleGraph(ctx, graph)
func (bc *BetweennessCentrality) Refresh(graph ChannelGraph) error {
cache, err := NewSimpleGraph(graph)
if err != nil {
return err
}

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"fmt"
"testing"
@ -31,9 +30,6 @@ func TestBetweennessCentralityMetricConstruction(t *testing.T) {
// Tests that empty graph results in empty centrality result.
func TestBetweennessCentralityEmptyGraph(t *testing.T) {
t.Parallel()
ctx := context.Background()
centralityMetric, err := NewBetweennessCentralityMetric(1)
require.NoError(
t, err,
@ -46,7 +42,7 @@ func TestBetweennessCentralityEmptyGraph(t *testing.T) {
require.NoError(t, err, "unable to create graph")
success := t.Run(chanGraph.name, func(t1 *testing.T) {
err = centralityMetric.Refresh(ctx, graph)
err = centralityMetric.Refresh(graph)
require.NoError(t1, err)
centrality := centralityMetric.GetMetric(false)
@ -63,9 +59,6 @@ func TestBetweennessCentralityEmptyGraph(t *testing.T) {
// Test betweenness centrality calculating using an example graph.
func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) {
t.Parallel()
ctx := context.Background()
workers := []int{1, 3, 9, 100}
tests := []struct {
@ -107,7 +100,7 @@ func TestBetweennessCentralityWithNonEmptyGraph(t *testing.T) {
t1, graph, centralityTestGraph,
)
err = metric.Refresh(ctx, graph)
err = metric.Refresh(graph)
require.NoError(t1, err)
for _, expected := range tests {

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"fmt"
"github.com/btcsuite/btcd/btcutil"
@ -71,9 +70,9 @@ func (c *WeightedCombAttachment) Name() string {
// is the maximum possible improvement in connectivity.
//
// NOTE: This is a part of the AttachmentHeuristic interface.
func (c *WeightedCombAttachment) NodeScores(ctx context.Context, g ChannelGraph,
chans []LocalChannel, chanSize btcutil.Amount,
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
func (c *WeightedCombAttachment) NodeScores(g ChannelGraph, chans []LocalChannel,
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
map[NodeID]*NodeScore, error) {
// We now query each heuristic to determine the score they give to the
// nodes for the given channel size.
@ -82,7 +81,7 @@ func (c *WeightedCombAttachment) NodeScores(ctx context.Context, g ChannelGraph,
log.Tracef("Getting scores from sub heuristic %v", h.Name())
s, err := h.NodeScores(
ctx, g, chans, chanSize, nodes,
g, chans, chanSize, nodes,
)
if err != nil {
return nil, fmt.Errorf("unable to get sub score: %w",

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"fmt"
"sync"
@ -81,9 +80,9 @@ func (s *ExternalScoreAttachment) SetNodeScores(targetHeuristic string,
// not known will get a score of 0.
//
// NOTE: This is a part of the AttachmentHeuristic interface.
func (s *ExternalScoreAttachment) NodeScores(_ context.Context, g ChannelGraph,
chans []LocalChannel, chanSize btcutil.Amount,
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
func (s *ExternalScoreAttachment) NodeScores(g ChannelGraph, chans []LocalChannel,
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
map[NodeID]*NodeScore, error) {
existingPeers := make(map[NodeID]struct{})
for _, c := range chans {

View File

@ -1,7 +1,6 @@
package autopilot_test
import (
"context"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
@ -23,7 +22,6 @@ func randKey() (*btcec.PublicKey, error) {
// ExternalScoreAttachment correctly reflects the scores we set last.
func TestSetNodeScores(t *testing.T) {
t.Parallel()
ctx := context.Background()
const name = "externalscore"
@ -64,7 +62,7 @@ func TestSetNodeScores(t *testing.T) {
q[nID] = struct{}{}
}
resp, err := h.NodeScores(
ctx, nil, nil, btcutil.Amount(btcutil.SatoshiPerBitcoin), q,
nil, nil, btcutil.Amount(btcutil.SatoshiPerBitcoin), q,
)
if err != nil {
t.Fatal(err)

View File

@ -1,16 +1,19 @@
package autopilot
import (
"context"
"bytes"
"encoding/hex"
"net"
"sort"
"sync/atomic"
"time"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/btcutil"
graphdb "github.com/lightningnetwork/lnd/graph/db"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)
@ -32,7 +35,7 @@ var (
//
// TODO(roasbeef): move inmpl to main package?
type databaseChannelGraph struct {
db GraphSource
db *channeldb.ChannelGraph
}
// A compile time assertion to ensure databaseChannelGraph meets the
@ -40,8 +43,8 @@ type databaseChannelGraph struct {
var _ ChannelGraph = (*databaseChannelGraph)(nil)
// ChannelGraphFromDatabase returns an instance of the autopilot.ChannelGraph
// backed by a GraphSource.
func ChannelGraphFromDatabase(db GraphSource) ChannelGraph {
// backed by a live, open channeldb instance.
func ChannelGraphFromDatabase(db *channeldb.ChannelGraph) ChannelGraph {
return &databaseChannelGraph{
db: db,
}
@ -51,7 +54,11 @@ func ChannelGraphFromDatabase(db GraphSource) ChannelGraph {
// channeldb.LightningNode. The wrapper method implement the autopilot.Node
// interface.
type dbNode struct {
tx graphdb.NodeRTx
db *channeldb.ChannelGraph
tx kvdb.RTx
node *channeldb.LightningNode
}
// A compile time assertion to ensure dbNode meets the autopilot.Node
@ -64,7 +71,7 @@ var _ Node = (*dbNode)(nil)
//
// NOTE: Part of the autopilot.Node interface.
func (d *dbNode) PubKey() [33]byte {
return d.tx.Node().PubKeyBytes
return d.node.PubKeyBytes
}
// Addrs returns a slice of publicly reachable public TCP addresses that the
@ -72,7 +79,7 @@ func (d *dbNode) PubKey() [33]byte {
//
// NOTE: Part of the autopilot.Node interface.
func (d *dbNode) Addrs() []net.Addr {
return d.tx.Node().Addresses
return d.node.Addresses
}
// ForEachChannel is a higher-order function that will be used to iterate
@ -81,38 +88,44 @@ func (d *dbNode) Addrs() []net.Addr {
// describes the active channel.
//
// NOTE: Part of the autopilot.Node interface.
func (d *dbNode) ForEachChannel(ctx context.Context,
cb func(context.Context, ChannelEdge) error) error {
func (d *dbNode) ForEachChannel(cb func(ChannelEdge) error) error {
return d.db.ForEachNodeChannelTx(d.tx, d.node.PubKeyBytes,
func(tx kvdb.RTx, ei *models.ChannelEdgeInfo, ep,
_ *models.ChannelEdgePolicy) error {
return d.tx.ForEachChannel(func(ei *models.ChannelEdgeInfo, ep,
_ *models.ChannelEdgePolicy) error {
// Skip channels for which no outgoing edge policy is
// available.
//
// TODO(joostjager): Ideally the case where channels
// have a nil policy should be supported, as autopilot
// is not looking at the policies. For now, it is not
// easily possible to get a reference to the other end
// LightningNode object without retrieving the policy.
if ep == nil {
return nil
}
// Skip channels for which no outgoing edge policy is available.
//
// TODO(joostjager): Ideally the case where channels have a nil
// policy should be supported, as autopilot is not looking at
// the policies. For now, it is not easily possible to get a
// reference to the other end LightningNode object without
// retrieving the policy.
if ep == nil {
return nil
}
node, err := d.db.FetchLightningNodeTx(
tx, ep.ToNode,
)
if err != nil {
return err
}
node, err := d.tx.FetchNode(ep.ToNode)
if err != nil {
return err
}
edge := ChannelEdge{
ChanID: lnwire.NewShortChanIDFromInt(
ep.ChannelID,
),
Capacity: ei.Capacity,
Peer: &dbNode{
tx: tx,
db: d.db,
node: node,
},
}
edge := ChannelEdge{
ChanID: lnwire.NewShortChanIDFromInt(ep.ChannelID),
Capacity: ei.Capacity,
Peer: &dbNode{
tx: node,
},
}
return cb(ctx, edge)
})
return cb(edge)
})
}
// ForEachNode is a higher-order function that should be called once for each
@ -120,29 +133,352 @@ func (d *dbNode) ForEachChannel(ctx context.Context,
// error, then execution should be terminated.
//
// NOTE: Part of the autopilot.ChannelGraph interface.
func (d *databaseChannelGraph) ForEachNode(ctx context.Context,
cb func(context.Context, Node) error) error {
return d.db.ForEachNode(func(nodeTx graphdb.NodeRTx) error {
func (d *databaseChannelGraph) ForEachNode(cb func(Node) error) error {
return d.db.ForEachNode(func(tx kvdb.RTx, n *channeldb.LightningNode) error {
// We'll skip over any node that doesn't have any advertised
// addresses. As we won't be able to reach them to actually
// open any channels.
if len(nodeTx.Node().Addresses) == 0 {
if len(n.Addresses) == 0 {
return nil
}
node := &dbNode{
tx: nodeTx,
db: d.db,
tx: tx,
node: n,
}
return cb(node)
})
}
// addRandChannel creates a new channel two target nodes. This function is
// meant to aide in the generation of random graphs for use within test cases
// the exercise the autopilot package.
func (d *databaseChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) {
fetchNode := func(pub *btcec.PublicKey) (*channeldb.LightningNode, error) {
if pub != nil {
vertex, err := route.NewVertexFromBytes(
pub.SerializeCompressed(),
)
if err != nil {
return nil, err
}
dbNode, err := d.db.FetchLightningNode(vertex)
switch {
case err == channeldb.ErrGraphNodeNotFound:
fallthrough
case err == channeldb.ErrGraphNotFound:
graphNode := &channeldb.LightningNode{
HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
Features: lnwire.NewFeatureVector(
nil, lnwire.Features,
),
AuthSigBytes: testSig.Serialize(),
}
graphNode.AddPubKey(pub)
if err := d.db.AddLightningNode(graphNode); err != nil {
return nil, err
}
case err != nil:
return nil, err
}
return dbNode, nil
}
return cb(ctx, node)
})
nodeKey, err := randKey()
if err != nil {
return nil, err
}
dbNode := &channeldb.LightningNode{
HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
Features: lnwire.NewFeatureVector(
nil, lnwire.Features,
),
AuthSigBytes: testSig.Serialize(),
}
dbNode.AddPubKey(nodeKey)
if err := d.db.AddLightningNode(dbNode); err != nil {
return nil, err
}
return dbNode, nil
}
vertex1, err := fetchNode(node1)
if err != nil {
return nil, nil, err
}
vertex2, err := fetchNode(node2)
if err != nil {
return nil, nil, err
}
var lnNode1, lnNode2 *btcec.PublicKey
if bytes.Compare(vertex1.PubKeyBytes[:], vertex2.PubKeyBytes[:]) == -1 {
lnNode1, _ = vertex1.PubKey()
lnNode2, _ = vertex2.PubKey()
} else {
lnNode1, _ = vertex2.PubKey()
lnNode2, _ = vertex1.PubKey()
}
chanID := randChanID()
edge := &models.ChannelEdgeInfo{
ChannelID: chanID.ToUint64(),
Capacity: capacity,
}
edge.AddNodeKeys(lnNode1, lnNode2, lnNode1, lnNode2)
if err := d.db.AddChannelEdge(edge); err != nil {
return nil, nil, err
}
edgePolicy := &models.ChannelEdgePolicy{
SigBytes: testSig.Serialize(),
ChannelID: chanID.ToUint64(),
LastUpdate: time.Now(),
TimeLockDelta: 10,
MinHTLC: 1,
MaxHTLC: lnwire.NewMSatFromSatoshis(capacity),
FeeBaseMSat: 10,
FeeProportionalMillionths: 10000,
MessageFlags: 1,
ChannelFlags: 0,
}
if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil {
return nil, nil, err
}
edgePolicy = &models.ChannelEdgePolicy{
SigBytes: testSig.Serialize(),
ChannelID: chanID.ToUint64(),
LastUpdate: time.Now(),
TimeLockDelta: 10,
MinHTLC: 1,
MaxHTLC: lnwire.NewMSatFromSatoshis(capacity),
FeeBaseMSat: 10,
FeeProportionalMillionths: 10000,
MessageFlags: 1,
ChannelFlags: 1,
}
if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil {
return nil, nil, err
}
return &ChannelEdge{
ChanID: chanID,
Capacity: capacity,
Peer: &dbNode{
db: d.db,
node: vertex1,
},
},
&ChannelEdge{
ChanID: chanID,
Capacity: capacity,
Peer: &dbNode{
db: d.db,
node: vertex2,
},
},
nil
}
func (d *databaseChannelGraph) addRandNode() (*btcec.PublicKey, error) {
nodeKey, err := randKey()
if err != nil {
return nil, err
}
dbNode := &channeldb.LightningNode{
HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
Features: lnwire.NewFeatureVector(
nil, lnwire.Features,
),
AuthSigBytes: testSig.Serialize(),
}
dbNode.AddPubKey(nodeKey)
if err := d.db.AddLightningNode(dbNode); err != nil {
return nil, err
}
return nodeKey, nil
}
// memChannelGraph is an implementation of the autopilot.ChannelGraph backed by
// an in-memory graph.
type memChannelGraph struct {
graph map[NodeID]*memNode
}
// A compile time assertion to ensure memChannelGraph meets the
// autopilot.ChannelGraph interface.
var _ ChannelGraph = (*memChannelGraph)(nil)
// newMemChannelGraph creates a new blank in-memory channel graph
// implementation.
func newMemChannelGraph() *memChannelGraph {
return &memChannelGraph{
graph: make(map[NodeID]*memNode),
}
}
// ForEachNode is a higher-order function that should be called once for each
// connected node within the channel graph. If the passed callback returns an
// error, then execution should be terminated.
//
// NOTE: Part of the autopilot.ChannelGraph interface.
func (m memChannelGraph) ForEachNode(cb func(Node) error) error {
for _, node := range m.graph {
if err := cb(node); err != nil {
return err
}
}
return nil
}
// randChanID generates a new random channel ID.
func randChanID() lnwire.ShortChannelID {
id := atomic.AddUint64(&chanIDCounter, 1)
return lnwire.NewShortChanIDFromInt(id)
}
// randKey returns a random public key.
func randKey() (*btcec.PublicKey, error) {
priv, err := btcec.NewPrivateKey()
if err != nil {
return nil, err
}
return priv.PubKey(), nil
}
// addRandChannel creates a new channel two target nodes. This function is
// meant to aide in the generation of random graphs for use within test cases
// the exercise the autopilot package.
func (m *memChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) {
var (
vertex1, vertex2 *memNode
ok bool
)
if node1 != nil {
vertex1, ok = m.graph[NewNodeID(node1)]
if !ok {
vertex1 = &memNode{
pub: node1,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
}
} else {
newPub, err := randKey()
if err != nil {
return nil, nil, err
}
vertex1 = &memNode{
pub: newPub,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
}
if node2 != nil {
vertex2, ok = m.graph[NewNodeID(node2)]
if !ok {
vertex2 = &memNode{
pub: node2,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
}
} else {
newPub, err := randKey()
if err != nil {
return nil, nil, err
}
vertex2 = &memNode{
pub: newPub,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
}
edge1 := ChannelEdge{
ChanID: randChanID(),
Capacity: capacity,
Peer: vertex2,
}
vertex1.chans = append(vertex1.chans, edge1)
edge2 := ChannelEdge{
ChanID: randChanID(),
Capacity: capacity,
Peer: vertex1,
}
vertex2.chans = append(vertex2.chans, edge2)
m.graph[NewNodeID(vertex1.pub)] = vertex1
m.graph[NewNodeID(vertex2.pub)] = vertex2
return &edge1, &edge2, nil
}
func (m *memChannelGraph) addRandNode() (*btcec.PublicKey, error) {
newPub, err := randKey()
if err != nil {
return nil, err
}
vertex := &memNode{
pub: newPub,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
m.graph[NewNodeID(newPub)] = vertex
return newPub, nil
}
// databaseChannelGraphCached wraps a channeldb.ChannelGraph instance with the
// necessary API to properly implement the autopilot.ChannelGraph interface.
type databaseChannelGraphCached struct {
db GraphSource
db *channeldb.ChannelGraph
}
// A compile time assertion to ensure databaseChannelGraphCached meets the
@ -151,7 +487,7 @@ var _ ChannelGraph = (*databaseChannelGraphCached)(nil)
// ChannelGraphFromCachedDatabase returns an instance of the
// autopilot.ChannelGraph backed by a live, open channeldb instance.
func ChannelGraphFromCachedDatabase(db GraphSource) ChannelGraph {
func ChannelGraphFromCachedDatabase(db *channeldb.ChannelGraph) ChannelGraph {
return &databaseChannelGraphCached{
db: db,
}
@ -162,7 +498,7 @@ func ChannelGraphFromCachedDatabase(db GraphSource) ChannelGraph {
// interface.
type dbNodeCached struct {
node route.Vertex
channels map[uint64]*graphdb.DirectedChannel
channels map[uint64]*channeldb.DirectedChannel
}
// A compile time assertion to ensure dbNodeCached meets the autopilot.Node
@ -191,9 +527,7 @@ func (nc dbNodeCached) Addrs() []net.Addr {
// describes the active channel.
//
// NOTE: Part of the autopilot.Node interface.
func (nc dbNodeCached) ForEachChannel(ctx context.Context,
cb func(context.Context, ChannelEdge) error) error {
func (nc dbNodeCached) ForEachChannel(cb func(ChannelEdge) error) error {
for cid, channel := range nc.channels {
edge := ChannelEdge{
ChanID: lnwire.NewShortChanIDFromInt(cid),
@ -203,7 +537,7 @@ func (nc dbNodeCached) ForEachChannel(ctx context.Context,
},
}
if err := cb(ctx, edge); err != nil {
if err := cb(edge); err != nil {
return err
}
}
@ -216,19 +550,16 @@ func (nc dbNodeCached) ForEachChannel(ctx context.Context,
// error, then execution should be terminated.
//
// NOTE: Part of the autopilot.ChannelGraph interface.
func (dc *databaseChannelGraphCached) ForEachNode(ctx context.Context,
cb func(context.Context, Node) error) error {
func (dc *databaseChannelGraphCached) ForEachNode(cb func(Node) error) error {
return dc.db.ForEachNodeCached(func(n route.Vertex,
channels map[uint64]*graphdb.DirectedChannel) error {
channels map[uint64]*channeldb.DirectedChannel) error {
if len(channels) > 0 {
node := dbNodeCached{
node: n,
channels: channels,
}
return cb(ctx, node)
return cb(node)
}
return nil
})
@ -273,11 +604,9 @@ func (m memNode) Addrs() []net.Addr {
// describes the active channel.
//
// NOTE: Part of the autopilot.Node interface.
func (m memNode) ForEachChannel(ctx context.Context,
cb func(context.Context, ChannelEdge) error) error {
func (m memNode) ForEachChannel(cb func(ChannelEdge) error) error {
for _, channel := range m.chans {
if err := cb(ctx, channel); err != nil {
if err := cb(channel); err != nil {
return err
}
}

View File

@ -1,15 +1,12 @@
package autopilot
import (
"context"
"net"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire"
graphdb "github.com/lightningnetwork/lnd/graph/db"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)
// DefaultConfTarget is the default confirmation target for autopilot channels.
@ -36,8 +33,7 @@ type Node interface {
// iterate through all edges emanating from/to the target node. For
// each active channel, this function should be called with the
// populated ChannelEdge that describes the active channel.
ForEachChannel(context.Context, func(context.Context,
ChannelEdge) error) error
ForEachChannel(func(ChannelEdge) error) error
}
// LocalChannel is a simple struct which contains relevant details of a
@ -85,7 +81,7 @@ type ChannelGraph interface {
// ForEachNode is a higher-order function that should be called once
// for each connected node within the channel graph. If the passed
// callback returns an error, then execution should be terminated.
ForEachNode(context.Context, func(context.Context, Node) error) error
ForEachNode(func(Node) error) error
}
// NodeScore is a tuple mapping a NodeID to a score indicating the preference
@ -144,7 +140,7 @@ type AttachmentHeuristic interface {
//
// NOTE: A NodeID not found in the returned map is implicitly given a
// score of 0.
NodeScores(ctx context.Context, g ChannelGraph, chans []LocalChannel,
NodeScores(g ChannelGraph, chans []LocalChannel,
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
map[NodeID]*NodeScore, error)
}
@ -157,7 +153,7 @@ type NodeMetric interface {
Name() string
// Refresh refreshes the metric values based on the current graph.
Refresh(ctx context.Context, graph ChannelGraph) error
Refresh(graph ChannelGraph) error
// GetMetric returns the latest value of this metric. Values in the
// map are per node and can be in arbitrary domain. If normalize is
@ -220,20 +216,3 @@ type ChannelController interface {
// TODO(roasbeef): add force option?
CloseChannel(chanPoint *wire.OutPoint) error
}
// GraphSource represents read access to the channel graph.
type GraphSource interface {
// ForEachNode iterates through all the stored vertices/nodes in the
// graph, executing the passed callback with each node encountered. If
// the callback returns an error, then the transaction is aborted and
// the iteration stops early. Any operations performed on the NodeTx
// passed to the call-back are executed under the same read transaction.
ForEachNode(func(graphdb.NodeRTx) error) error
// ForEachNodeCached is similar to ForEachNode, but it utilizes the
// channel graph cache if one is available. It is less consistent than
// ForEachNode since any further calls are made across multiple
// transactions.
ForEachNodeCached(cb func(node route.Vertex,
chans map[uint64]*graphdb.DirectedChannel) error) error
}

View File

@ -1,7 +1,7 @@
package autopilot
import (
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

View File

@ -1,13 +1,12 @@
package autopilot
import (
"context"
"fmt"
"sync"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
graphdb "github.com/lightningnetwork/lnd/graph/db"
"github.com/lightningnetwork/lnd/graph"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
)
@ -37,7 +36,7 @@ type ManagerCfg struct {
// SubscribeTopology is used to get a subscription for topology changes
// on the network.
SubscribeTopology func() (*graphdb.TopologyClient, error)
SubscribeTopology func() (*graph.TopologyClient, error)
}
// Manager is struct that manages an autopilot agent, making it possible to
@ -267,8 +266,8 @@ func (m *Manager) StopAgent() error {
}
// QueryHeuristics queries the available autopilot heuristics for node scores.
func (m *Manager) QueryHeuristics(ctx context.Context, nodes []NodeID,
localState bool) (HeuristicScores, error) {
func (m *Manager) QueryHeuristics(nodes []NodeID, localState bool) (
HeuristicScores, error) {
m.Lock()
defer m.Unlock()
@ -279,8 +278,7 @@ func (m *Manager) QueryHeuristics(ctx context.Context, nodes []NodeID,
}
log.Debugf("Querying heuristics for %d nodes", len(n))
return m.queryHeuristics(ctx, n, localState)
return m.queryHeuristics(n, localState)
}
// HeuristicScores is an alias for a map that maps heuristic names to a map of
@ -291,8 +289,8 @@ type HeuristicScores map[string]map[NodeID]float64
// the agent's current active heuristic.
//
// NOTE: Must be called with the manager's lock.
func (m *Manager) queryHeuristics(ctx context.Context,
nodes map[NodeID]struct{}, localState bool) (HeuristicScores, error) {
func (m *Manager) queryHeuristics(nodes map[NodeID]struct{}, localState bool) (
HeuristicScores, error) {
// If we want to take the local state into action when querying the
// heuristics, we fetch it. If not we'll just pass an empty slice to
@ -340,7 +338,7 @@ func (m *Manager) queryHeuristics(ctx context.Context,
}
s, err := h.NodeScores(
ctx, m.cfg.PilotCfg.Graph, totalChans, chanSize, nodes,
m.cfg.PilotCfg.Graph, totalChans, chanSize, nodes,
)
if err != nil {
return nil, fmt.Errorf("unable to get sub score: %w",

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
prand "math/rand"
"time"
@ -79,9 +78,9 @@ func (p *PrefAttachment) Name() string {
// given to nodes already having high connectivity in the graph.
//
// NOTE: This is a part of the AttachmentHeuristic interface.
func (p *PrefAttachment) NodeScores(ctx context.Context, g ChannelGraph,
chans []LocalChannel, chanSize btcutil.Amount,
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []LocalChannel,
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
map[NodeID]*NodeScore, error) {
// We first run though the graph once in order to find the median
// channel size.
@ -89,10 +88,8 @@ func (p *PrefAttachment) NodeScores(ctx context.Context, g ChannelGraph,
allChans []btcutil.Amount
seenChans = make(map[uint64]struct{})
)
if err := g.ForEachNode(ctx, func(ctx context.Context, n Node) error {
err := n.ForEachChannel(ctx, func(_ context.Context,
e ChannelEdge) error {
if err := g.ForEachNode(func(n Node) error {
err := n.ForEachChannel(func(e ChannelEdge) error {
if _, ok := seenChans[e.ChanID.ToUint64()]; ok {
return nil
}
@ -117,19 +114,15 @@ func (p *PrefAttachment) NodeScores(ctx context.Context, g ChannelGraph,
// the graph.
var maxChans int
nodeChanNum := make(map[NodeID]int)
if err := g.ForEachNode(ctx, func(ctx context.Context, n Node) error {
if err := g.ForEachNode(func(n Node) error {
var nodeChans int
err := n.ForEachChannel(ctx, func(_ context.Context,
e ChannelEdge) error {
err := n.ForEachChannel(func(e ChannelEdge) error {
// Since connecting to nodes with a lot of small
// channels actually worsens our connectivity in the
// graph (we will potentially waste time trying to use
// these useless channels in path finding), we decrease
// the counter for such channels.
if e.Capacity <
medianChanSize/minMedianChanSizeFraction {
if e.Capacity < medianChanSize/minMedianChanSizeFraction {
nodeChans--
return nil
}

View File

@ -2,21 +2,13 @@ package autopilot
import (
"bytes"
"context"
"errors"
prand "math/rand"
"net"
"sync/atomic"
"testing"
"time"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
graphdb "github.com/lightningnetwork/lnd/graph/db"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/stretchr/testify/require"
)
@ -31,39 +23,22 @@ type testGraph interface {
addRandNode() (*btcec.PublicKey, error)
}
type testDBGraph struct {
db *graphdb.ChannelGraph
databaseChannelGraph
}
func newDiskChanGraph(t *testing.T) (testGraph, error) {
backend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
DBPath: t.TempDir(),
DBFileName: "graph.db",
NoFreelistSync: true,
AutoCompact: false,
AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge,
DBTimeout: kvdb.DefaultDBTimeout,
})
require.NoError(t, err)
graphDB, err := graphdb.NewChannelGraph(&graphdb.Config{KVDB: backend})
require.NoError(t, err)
require.NoError(t, graphDB.Start())
// Next, create channeldb for the first time.
cdb, err := channeldb.Open(t.TempDir())
if err != nil {
return nil, err
}
t.Cleanup(func() {
require.NoError(t, graphDB.Stop())
require.NoError(t, cdb.Close())
})
return &testDBGraph{
db: graphDB,
databaseChannelGraph: databaseChannelGraph{
db: graphDB,
},
return &databaseChannelGraph{
db: cdb.ChannelGraph(),
}, nil
}
var _ testGraph = (*testDBGraph)(nil)
var _ testGraph = (*databaseChannelGraph)(nil)
func newMemChanGraph(_ *testing.T) (testGraph, error) {
return newMemChannelGraph(), nil
@ -88,8 +63,6 @@ var chanGraphs = []struct {
// TestPrefAttachmentSelectEmptyGraph ensures that when passed an
// empty graph, the NodeSores function always returns a score of 0.
func TestPrefAttachmentSelectEmptyGraph(t *testing.T) {
t.Parallel()
ctx := context.Background()
prefAttach := NewPrefAttachment()
// Create a random public key, which we will query to get a score for.
@ -110,7 +83,7 @@ func TestPrefAttachmentSelectEmptyGraph(t *testing.T) {
// attempt to get the score for this one node.
const walletFunds = btcutil.SatoshiPerBitcoin
scores, err := prefAttach.NodeScores(
ctx, graph, nil, walletFunds, nodes,
graph, nil, walletFunds, nodes,
)
require.NoError(t1, err)
@ -129,7 +102,6 @@ func TestPrefAttachmentSelectEmptyGraph(t *testing.T) {
// and the funds are appropriately allocated across each peer.
func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
t.Parallel()
ctx := context.Background()
prand.Seed(time.Now().Unix())
@ -160,12 +132,10 @@ func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
// Get the score for all nodes found in the graph at
// this point.
nodes := make(map[NodeID]struct{})
err = graph.ForEachNode(ctx,
func(_ context.Context, n Node) error {
nodes[n.PubKey()] = struct{}{}
return nil
},
)
err = graph.ForEachNode(func(n Node) error {
nodes[n.PubKey()] = struct{}{}
return nil
})
require.NoError(t1, err)
require.Len(t1, nodes, 3)
@ -174,7 +144,7 @@ func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
// attempt to get our candidates channel score given
// the current state of the graph.
candidates, err := prefAttach.NodeScores(
ctx, graph, nil, maxChanSize, nodes,
graph, nil, maxChanSize, nodes,
)
require.NoError(t1, err)
@ -213,7 +183,6 @@ func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
// allocate all funds to each vertex (up to the max channel size).
func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
t.Parallel()
ctx := context.Background()
prand.Seed(time.Now().Unix())
@ -252,25 +221,22 @@ func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
numNodes := 0
twoChans := false
nodes := make(map[NodeID]struct{})
err = graph.ForEachNode(
ctx, func(ctx context.Context, n Node) error {
numNodes++
nodes[n.PubKey()] = struct{}{}
numChans := 0
err := n.ForEachChannel(ctx,
func(_ context.Context, c ChannelEdge) error { //nolint:ll
numChans++
return nil
},
)
if err != nil {
return err
}
twoChans = twoChans || (numChans == 2)
err = graph.ForEachNode(func(n Node) error {
numNodes++
nodes[n.PubKey()] = struct{}{}
numChans := 0
err := n.ForEachChannel(func(c ChannelEdge) error {
numChans++
return nil
})
if err != nil {
return err
}
twoChans = twoChans || (numChans == 2)
return nil
})
require.NoError(t1, err)
require.EqualValues(t1, 3, numNodes)
@ -282,7 +248,7 @@ func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
// result, the heuristic should try to greedily
// allocate funds to channels.
scores, err := prefAttach.NodeScores(
ctx, graph, nil, maxChanSize, nodes,
graph, nil, maxChanSize, nodes,
)
require.NoError(t1, err)
@ -300,7 +266,7 @@ func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
// candidates of that size.
const remBalance = btcutil.SatoshiPerBitcoin * 0.5
scores, err = prefAttach.NodeScores(
ctx, graph, nil, remBalance, nodes,
graph, nil, remBalance, nodes,
)
require.NoError(t1, err)
@ -323,7 +289,6 @@ func TestPrefAttachmentSelectGreedyAllocation(t *testing.T) {
// of zero during scoring.
func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
t.Parallel()
ctx := context.Background()
prand.Seed(time.Now().Unix())
@ -346,13 +311,10 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
require.NoError(t1, err)
nodes := make(map[NodeID]struct{})
err = graph.ForEachNode(
ctx, func(_ context.Context, n Node) error {
nodes[n.PubKey()] = struct{}{}
return nil
},
)
err = graph.ForEachNode(func(n Node) error {
nodes[n.PubKey()] = struct{}{}
return nil
})
require.NoError(t1, err)
require.Len(t1, nodes, 2)
@ -360,7 +322,7 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
// With our graph created, we'll now get the scores for
// all nodes in the graph.
scores, err := prefAttach.NodeScores(
ctx, graph, nil, maxChanSize, nodes,
graph, nil, maxChanSize, nodes,
)
require.NoError(t1, err)
@ -388,7 +350,7 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
// then all nodes should have a score of zero, since we
// already got channels to them.
scores, err = prefAttach.NodeScores(
ctx, graph, chans, maxChanSize, nodes,
graph, chans, maxChanSize, nodes,
)
require.NoError(t1, err)
@ -401,359 +363,3 @@ func TestPrefAttachmentSelectSkipNodes(t *testing.T) {
}
}
}
// addRandChannel creates a new channel two target nodes. This function is
// meant to aide in the generation of random graphs for use within test cases
// the exercise the autopilot package.
func (d *testDBGraph) addRandChannel(node1, node2 *btcec.PublicKey,
capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) {
fetchNode := func(pub *btcec.PublicKey) (*models.LightningNode, error) {
if pub != nil {
vertex, err := route.NewVertexFromBytes(
pub.SerializeCompressed(),
)
if err != nil {
return nil, err
}
dbNode, err := d.db.FetchLightningNode(vertex)
switch {
case errors.Is(err, graphdb.ErrGraphNodeNotFound):
fallthrough
case errors.Is(err, graphdb.ErrGraphNotFound):
graphNode := &models.LightningNode{
HaveNodeAnnouncement: true,
Addresses: []net.Addr{&net.TCPAddr{
IP: bytes.Repeat(
[]byte("a"), 16,
),
}},
Features: lnwire.NewFeatureVector(
nil, lnwire.Features,
),
AuthSigBytes: testSig.Serialize(),
}
graphNode.AddPubKey(pub)
err := d.db.AddLightningNode(graphNode)
if err != nil {
return nil, err
}
case err != nil:
return nil, err
}
return dbNode, nil
}
nodeKey, err := randKey()
if err != nil {
return nil, err
}
dbNode := &models.LightningNode{
HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
Features: lnwire.NewFeatureVector(
nil, lnwire.Features,
),
AuthSigBytes: testSig.Serialize(),
}
dbNode.AddPubKey(nodeKey)
if err := d.db.AddLightningNode(dbNode); err != nil {
return nil, err
}
return dbNode, nil
}
vertex1, err := fetchNode(node1)
if err != nil {
return nil, nil, err
}
vertex2, err := fetchNode(node2)
if err != nil {
return nil, nil, err
}
var lnNode1, lnNode2 *btcec.PublicKey
if bytes.Compare(vertex1.PubKeyBytes[:], vertex2.PubKeyBytes[:]) == -1 {
lnNode1, _ = vertex1.PubKey()
lnNode2, _ = vertex2.PubKey()
} else {
lnNode1, _ = vertex2.PubKey()
lnNode2, _ = vertex1.PubKey()
}
chanID := randChanID()
edge := &models.ChannelEdgeInfo{
ChannelID: chanID.ToUint64(),
Capacity: capacity,
}
edge.AddNodeKeys(lnNode1, lnNode2, lnNode1, lnNode2)
if err := d.db.AddChannelEdge(edge); err != nil {
return nil, nil, err
}
edgePolicy := &models.ChannelEdgePolicy{
SigBytes: testSig.Serialize(),
ChannelID: chanID.ToUint64(),
LastUpdate: time.Now(),
TimeLockDelta: 10,
MinHTLC: 1,
MaxHTLC: lnwire.NewMSatFromSatoshis(capacity),
FeeBaseMSat: 10,
FeeProportionalMillionths: 10000,
MessageFlags: 1,
ChannelFlags: 0,
}
if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil {
return nil, nil, err
}
edgePolicy = &models.ChannelEdgePolicy{
SigBytes: testSig.Serialize(),
ChannelID: chanID.ToUint64(),
LastUpdate: time.Now(),
TimeLockDelta: 10,
MinHTLC: 1,
MaxHTLC: lnwire.NewMSatFromSatoshis(capacity),
FeeBaseMSat: 10,
FeeProportionalMillionths: 10000,
MessageFlags: 1,
ChannelFlags: 1,
}
if err := d.db.UpdateEdgePolicy(edgePolicy); err != nil {
return nil, nil, err
}
return &ChannelEdge{
ChanID: chanID,
Capacity: capacity,
Peer: &dbNode{tx: &testNodeTx{
db: d,
node: vertex1,
}},
},
&ChannelEdge{
ChanID: chanID,
Capacity: capacity,
Peer: &dbNode{tx: &testNodeTx{
db: d,
node: vertex2,
}},
},
nil
}
func (d *testDBGraph) addRandNode() (*btcec.PublicKey, error) {
nodeKey, err := randKey()
if err != nil {
return nil, err
}
dbNode := &models.LightningNode{
HaveNodeAnnouncement: true,
Addresses: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
Features: lnwire.NewFeatureVector(
nil, lnwire.Features,
),
AuthSigBytes: testSig.Serialize(),
}
dbNode.AddPubKey(nodeKey)
if err := d.db.AddLightningNode(dbNode); err != nil {
return nil, err
}
return nodeKey, nil
}
// memChannelGraph is an implementation of the autopilot.ChannelGraph backed by
// an in-memory graph.
type memChannelGraph struct {
graph map[NodeID]*memNode
}
// A compile time assertion to ensure memChannelGraph meets the
// autopilot.ChannelGraph interface.
var _ ChannelGraph = (*memChannelGraph)(nil)
// newMemChannelGraph creates a new blank in-memory channel graph
// implementation.
func newMemChannelGraph() *memChannelGraph {
return &memChannelGraph{
graph: make(map[NodeID]*memNode),
}
}
// ForEachNode is a higher-order function that should be called once for each
// connected node within the channel graph. If the passed callback returns an
// error, then execution should be terminated.
//
// NOTE: Part of the autopilot.ChannelGraph interface.
func (m *memChannelGraph) ForEachNode(ctx context.Context,
cb func(context.Context, Node) error) error {
for _, node := range m.graph {
if err := cb(ctx, node); err != nil {
return err
}
}
return nil
}
// randChanID generates a new random channel ID.
func randChanID() lnwire.ShortChannelID {
id := atomic.AddUint64(&chanIDCounter, 1)
return lnwire.NewShortChanIDFromInt(id)
}
// randKey returns a random public key.
func randKey() (*btcec.PublicKey, error) {
priv, err := btcec.NewPrivateKey()
if err != nil {
return nil, err
}
return priv.PubKey(), nil
}
// addRandChannel creates a new channel two target nodes. This function is
// meant to aide in the generation of random graphs for use within test cases
// the exercise the autopilot package.
func (m *memChannelGraph) addRandChannel(node1, node2 *btcec.PublicKey,
capacity btcutil.Amount) (*ChannelEdge, *ChannelEdge, error) {
var (
vertex1, vertex2 *memNode
ok bool
)
if node1 != nil {
vertex1, ok = m.graph[NewNodeID(node1)]
if !ok {
vertex1 = &memNode{
pub: node1,
addrs: []net.Addr{&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
}},
}
}
} else {
newPub, err := randKey()
if err != nil {
return nil, nil, err
}
vertex1 = &memNode{
pub: newPub,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
}
if node2 != nil {
vertex2, ok = m.graph[NewNodeID(node2)]
if !ok {
vertex2 = &memNode{
pub: node2,
addrs: []net.Addr{&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
}},
}
}
} else {
newPub, err := randKey()
if err != nil {
return nil, nil, err
}
vertex2 = &memNode{
pub: newPub,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
}
edge1 := ChannelEdge{
ChanID: randChanID(),
Capacity: capacity,
Peer: vertex2,
}
vertex1.chans = append(vertex1.chans, edge1)
edge2 := ChannelEdge{
ChanID: randChanID(),
Capacity: capacity,
Peer: vertex1,
}
vertex2.chans = append(vertex2.chans, edge2)
m.graph[NewNodeID(vertex1.pub)] = vertex1
m.graph[NewNodeID(vertex2.pub)] = vertex2
return &edge1, &edge2, nil
}
func (m *memChannelGraph) addRandNode() (*btcec.PublicKey, error) {
newPub, err := randKey()
if err != nil {
return nil, err
}
vertex := &memNode{
pub: newPub,
addrs: []net.Addr{
&net.TCPAddr{
IP: bytes.Repeat([]byte("a"), 16),
},
},
}
m.graph[NewNodeID(newPub)] = vertex
return newPub, nil
}
type testNodeTx struct {
db *testDBGraph
node *models.LightningNode
}
func (t *testNodeTx) Node() *models.LightningNode {
return t.node
}
func (t *testNodeTx) ForEachChannel(f func(*models.ChannelEdgeInfo,
*models.ChannelEdgePolicy, *models.ChannelEdgePolicy) error) error {
return t.db.db.ForEachNodeChannel(t.node.PubKeyBytes, func(
edge *models.ChannelEdgeInfo, policy1,
policy2 *models.ChannelEdgePolicy) error {
return f(edge, policy1, policy2)
})
}
func (t *testNodeTx) FetchNode(pub route.Vertex) (graphdb.NodeRTx, error) {
node, err := t.db.db.FetchLightningNode(pub)
if err != nil {
return nil, err
}
return &testNodeTx{
db: t.db,
node: node,
}, nil
}
var _ graphdb.NodeRTx = (*testNodeTx)(nil)

View File

@ -1,7 +1,5 @@
package autopilot
import "context"
// diameterCutoff is used to discard nodes in the diameter calculation.
// It is the multiplier for the eccentricity of the highest-degree node,
// serving as a cutoff to discard all nodes with a smaller hop distance. This
@ -22,7 +20,7 @@ type SimpleGraph struct {
// NewSimpleGraph creates a simplified graph from the current channel graph.
// Returns an error if the channel graph iteration fails due to underlying
// failure.
func NewSimpleGraph(ctx context.Context, g ChannelGraph) (*SimpleGraph, error) {
func NewSimpleGraph(g ChannelGraph) (*SimpleGraph, error) {
nodes := make(map[NodeID]int)
adj := make(map[int][]int)
nextIndex := 0
@ -44,22 +42,17 @@ func NewSimpleGraph(ctx context.Context, g ChannelGraph) (*SimpleGraph, error) {
return nodeIndex
}
// Iterate over each node and each channel and update the adj and the
// node index.
err := g.ForEachNode(ctx, func(ctx context.Context, node Node) error {
// Iterate over each node and each channel and update the adj and the node
// index.
err := g.ForEachNode(func(node Node) error {
u := getNodeIndex(node)
return node.ForEachChannel(
ctx, func(_ context.Context,
edge ChannelEdge) error {
return node.ForEachChannel(func(edge ChannelEdge) error {
v := getNodeIndex(edge.Peer)
v := getNodeIndex(edge.Peer)
adj[u] = append(adj[u], v)
return nil
},
)
adj[u] = append(adj[u], v)
return nil
})
})
if err != nil {
return nil, err
@ -92,7 +85,9 @@ func NewSimpleGraph(ctx context.Context, g ChannelGraph) (*SimpleGraph, error) {
func maxVal(mapping map[int]uint32) uint32 {
maxValue := uint32(0)
for _, value := range mapping {
maxValue = max(maxValue, value)
if maxValue < value {
maxValue = value
}
}
return maxValue
}

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"runtime"
"github.com/btcsuite/btcd/btcutil"
@ -51,12 +50,12 @@ func (g *TopCentrality) Name() string {
// As our current implementation of betweenness centrality is non-incremental,
// NodeScores will recalculate the centrality values on every call, which is
// slow for large graphs.
func (g *TopCentrality) NodeScores(ctx context.Context, graph ChannelGraph,
chans []LocalChannel, chanSize btcutil.Amount,
nodes map[NodeID]struct{}) (map[NodeID]*NodeScore, error) {
func (g *TopCentrality) NodeScores(graph ChannelGraph, chans []LocalChannel,
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
map[NodeID]*NodeScore, error) {
// Calculate betweenness centrality for the whole graph.
if err := g.centralityMetric.Refresh(ctx, graph); err != nil {
if err := g.centralityMetric.Refresh(graph); err != nil {
return nil, err
}

View File

@ -1,7 +1,6 @@
package autopilot
import (
"context"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
@ -59,7 +58,7 @@ func testTopCentrality(t *testing.T, graph testGraph,
// Attempt to get centrality scores and expect
// that the result equals with the expected set.
scores, err := topCentrality.NodeScores(
context.Background(), graph, channels, chanSize, nodes,
graph, channels, chanSize, nodes,
)
require.NoError(t, err)

View File

@ -5,7 +5,6 @@ import (
"sync"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/sqldb"
)
// errSolo is a sentinel error indicating that the requester should re-run the
@ -56,20 +55,8 @@ func (b *batch) run() {
for i, req := range b.reqs {
err := req.Update(tx)
if err != nil {
// If we get a serialization error, we
// want the underlying SQL retry
// mechanism to retry the entire batch.
// Otherwise, we can succeed in an
// sqldb retry and still re-execute the
// failing request individually.
dbErr := sqldb.MapSQLError(err)
if !sqldb.IsSerializationError(dbErr) {
failIdx = i
return err
}
return dbErr
failIdx = i
return err
}
}
return nil

View File

@ -1,74 +0,0 @@
package batch
import (
"errors"
"path/filepath"
"sync"
"testing"
"time"
"github.com/btcsuite/btcwallet/walletdb"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/stretchr/testify/require"
)
func TestRetry(t *testing.T) {
dbDir := t.TempDir()
dbName := filepath.Join(dbDir, "weks.db")
db, err := walletdb.Create(
"bdb", dbName, true, kvdb.DefaultDBTimeout, false,
)
if err != nil {
t.Fatalf("unable to create walletdb: %v", err)
}
t.Cleanup(func() {
db.Close()
})
var (
mu sync.Mutex
called int
)
sched := NewTimeScheduler(db, &mu, time.Second)
// First, we construct a request that should retry individually and
// execute it non-lazily. It should still return the error the second
// time.
req := &Request{
Update: func(tx kvdb.RwTx) error {
called++
return errors.New("test")
},
}
err = sched.Execute(req)
// Check and reset the called counter.
mu.Lock()
require.Equal(t, 2, called)
called = 0
mu.Unlock()
require.ErrorContains(t, err, "test")
// Now, we construct a request that should NOT retry because it returns
// a serialization error, which should cause the underlying postgres
// transaction to retry. Since we aren't using postgres, this will
// cause the transaction to not be retried at all.
req = &Request{
Update: func(tx kvdb.RwTx) error {
called++
return errors.New("could not serialize access")
},
}
err = sched.Execute(req)
// Check the called counter.
mu.Lock()
require.Equal(t, 1, called)
mu.Unlock()
require.ErrorContains(t, err, "could not serialize access")
}

View File

@ -7,13 +7,12 @@ import (
"net"
"time"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/keychain"
)
// defaultHandshakes is the maximum number of handshakes that can be done in
// parallel.
const defaultHandshakes = 50
const defaultHandshakes = 1000
// Listener is an implementation of a net.Conn which executes an authenticated
// key exchange and message encryption protocol dubbed "Machine" after
@ -25,10 +24,6 @@ type Listener struct {
tcp *net.TCPListener
// shouldAccept is a closure that determines if we should accept the
// incoming connection or not based on its public key.
shouldAccept func(*btcec.PublicKey) (bool, error)
handshakeSema chan struct{}
conns chan maybeConn
quit chan struct{}
@ -39,8 +34,8 @@ var _ net.Listener = (*Listener)(nil)
// NewListener returns a new net.Listener which enforces the Brontide scheme
// during both initial connection establishment and data transfer.
func NewListener(localStatic keychain.SingleKeyECDH, listenAddr string,
shouldAccept func(*btcec.PublicKey) (bool, error)) (*Listener, error) {
func NewListener(localStatic keychain.SingleKeyECDH,
listenAddr string) (*Listener, error) {
addr, err := net.ResolveTCPAddr("tcp", listenAddr)
if err != nil {
@ -55,7 +50,6 @@ func NewListener(localStatic keychain.SingleKeyECDH, listenAddr string,
brontideListener := &Listener{
localStatic: localStatic,
tcp: l,
shouldAccept: shouldAccept,
handshakeSema: make(chan struct{}, defaultHandshakes),
conns: make(chan maybeConn),
quit: make(chan struct{}),
@ -199,28 +193,6 @@ func (l *Listener) doHandshake(conn net.Conn) {
return
}
// Call the shouldAccept closure to see if the remote node's public key
// is allowed according to our banning heuristic. This is here because
// we do not learn the remote node's public static key until we've
// received and validated Act 3.
remoteKey := brontideConn.RemotePub()
if remoteKey == nil {
connErr := fmt.Errorf("no remote pubkey")
brontideConn.conn.Close()
l.rejectConn(rejectedConnErr(connErr, remoteAddr))
return
}
accepted, acceptErr := l.shouldAccept(remoteKey)
if !accepted {
// Reject the connection.
brontideConn.conn.Close()
l.rejectConn(rejectedConnErr(acceptErr, remoteAddr))
return
}
l.acceptConn(brontideConn)
}
@ -283,9 +255,3 @@ func (l *Listener) Close() error {
func (l *Listener) Addr() net.Addr {
return l.tcp.Addr()
}
// DisabledBanClosure is used in places that NewListener is invoked to bypass
// the ban-scoring.
func DisabledBanClosure(p *btcec.PublicKey) (bool, error) {
return true, nil
}

View File

@ -35,7 +35,7 @@ func makeListener() (*Listener, *lnwire.NetAddress, error) {
addr := "localhost:0"
// Our listener will be local, and the connection remote.
listener, err := NewListener(localKeyECDH, addr, DisabledBanClosure)
listener, err := NewListener(localKeyECDH, addr)
if err != nil {
return nil, nil, err
}
@ -85,12 +85,12 @@ func establishTestConnection(t testing.TB) (net.Conn, net.Conn, error) {
remote := <-remoteConnChan
if remote.err != nil {
return nil, nil, remote.err
return nil, nil, err
}
local := <-localConnChan
if local.err != nil {
return nil, nil, local.err
return nil, nil, err
}
t.Cleanup(func() {

View File

@ -1,99 +0,0 @@
package build
import (
"fmt"
"github.com/btcsuite/btclog/v2"
)
const (
callSiteOff = "off"
callSiteShort = "short"
callSiteLong = "long"
defaultLogCompressor = Gzip
// DefaultMaxLogFiles is the default maximum number of log files to
// keep.
DefaultMaxLogFiles = 10
// DefaultMaxLogFileSize is the default maximum log file size in MB.
DefaultMaxLogFileSize = 20
)
// LogConfig holds logging configuration options.
//
//nolint:ll
type LogConfig struct {
Console *consoleLoggerCfg `group:"console" namespace:"console" description:"The logger writing to stdout and stderr."`
File *FileLoggerConfig `group:"file" namespace:"file" description:"The logger writing to LND's standard log file."`
NoCommitHash bool `long:"no-commit-hash" description:"If set, the commit-hash of the current build will not be included in log lines by default."`
}
// Validate validates the LogConfig struct values.
func (c *LogConfig) Validate() error {
if !SupportedLogCompressor(c.File.Compressor) {
return fmt.Errorf("invalid log compressor: %v",
c.File.Compressor)
}
return nil
}
// LoggerConfig holds options for a particular logger.
//
//nolint:ll
type LoggerConfig struct {
Disable bool `long:"disable" description:"Disable this logger."`
NoTimestamps bool `long:"no-timestamps" description:"Omit timestamps from log lines."`
CallSite string `long:"call-site" description:"Include the call-site of each log line." choice:"off" choice:"short" choice:"long"`
}
// DefaultLogConfig returns the default logging config options.
func DefaultLogConfig() *LogConfig {
return &LogConfig{
Console: defaultConsoleLoggerCfg(),
File: &FileLoggerConfig{
Compressor: defaultLogCompressor,
MaxLogFiles: DefaultMaxLogFiles,
MaxLogFileSize: DefaultMaxLogFileSize,
LoggerConfig: &LoggerConfig{
CallSite: callSiteOff,
},
},
}
}
// HandlerOptions returns the set of btclog.HandlerOptions that the state of the
// config struct translates to.
func (cfg *LoggerConfig) HandlerOptions() []btclog.HandlerOption {
opts := []btclog.HandlerOption{
// We wrap the logger provided by the logging library with
// another layer of abstraction with the handlerSet, and so we
// need to increase the default skip depth by 1.
btclog.WithCallSiteSkipDepth(btclog.DefaultSkipDepth + 1),
}
if cfg.NoTimestamps {
opts = append(opts, btclog.WithNoTimestamp())
}
switch cfg.CallSite {
case callSiteShort:
opts = append(opts, btclog.WithCallerFlags(btclog.Lshortfile))
case callSiteLong:
opts = append(opts, btclog.WithCallerFlags(btclog.Llongfile))
}
return opts
}
// FileLoggerConfig extends LoggerConfig with specific log file options.
//
//nolint:ll
type FileLoggerConfig struct {
*LoggerConfig `yaml:",inline"`
Compressor string `long:"compressor" description:"Compression algorithm to use when rotating logs." choice:"gzip" choice:"zstd"`
MaxLogFiles int `long:"max-files" description:"Maximum logfiles to keep (0 for no rotation)"`
MaxLogFileSize int `long:"max-file-size" description:"Maximum logfile size in MB"`
}

View File

@ -1,112 +0,0 @@
//go:build dev
// +build dev
package build
import (
"fmt"
"strings"
btclogv1 "github.com/btcsuite/btclog"
"github.com/btcsuite/btclog/v2"
)
const (
resetSeq = "0"
boldSeq = "1"
faintSeq = "2"
esc = '\x1b'
csi = string(esc) + "["
)
// consoleLoggerCfg extends the LoggerConfig struct by adding a Color option
// which is only available for a console logger.
//
//nolint:ll
type consoleLoggerCfg struct {
*LoggerConfig `yaml:",inline"`
Style bool `long:"style" description:"If set, the output will be styled with color and fonts"`
}
// defaultConsoleLoggerCfg returns the default consoleLoggerCfg for the dev
// console logger.
func defaultConsoleLoggerCfg() *consoleLoggerCfg {
return &consoleLoggerCfg{
LoggerConfig: &LoggerConfig{
CallSite: callSiteShort,
},
}
}
// HandlerOptions returns the set of btclog.HandlerOptions that the state of the
// config struct translates to.
func (cfg *consoleLoggerCfg) HandlerOptions() []btclog.HandlerOption {
opts := cfg.LoggerConfig.HandlerOptions()
if !cfg.Style {
return opts
}
return append(
opts, btclog.WithStyledLevel(
func(l btclogv1.Level) string {
return styleString(
fmt.Sprintf("[%s]", l),
boldSeq,
string(ansiColoSeq(l)),
)
},
),
btclog.WithStyledCallSite(
func(file string, line int) string {
str := fmt.Sprintf("%s:%d", file, line)
return styleString(str, faintSeq)
},
),
btclog.WithStyledKeys(func(key string) string {
return styleString(key, faintSeq)
}),
)
}
func styleString(s string, styles ...string) string {
if len(styles) == 0 {
return s
}
seq := strings.Join(styles, ";")
if seq == "" {
return s
}
return fmt.Sprintf("%s%sm%s%sm", csi, seq, s, csi+resetSeq)
}
type ansiColorSeq string
const (
ansiColorSeqDarkTeal ansiColorSeq = "38;5;30"
ansiColorSeqDarkBlue ansiColorSeq = "38;5;63"
ansiColorSeqLightBlue ansiColorSeq = "38;5;86"
ansiColorSeqYellow ansiColorSeq = "38;5;192"
ansiColorSeqRed ansiColorSeq = "38;5;204"
ansiColorSeqPink ansiColorSeq = "38;5;134"
)
func ansiColoSeq(l btclogv1.Level) ansiColorSeq {
switch l {
case btclog.LevelTrace:
return ansiColorSeqDarkTeal
case btclog.LevelDebug:
return ansiColorSeqDarkBlue
case btclog.LevelWarn:
return ansiColorSeqYellow
case btclog.LevelError:
return ansiColorSeqRed
case btclog.LevelCritical:
return ansiColorSeqPink
default:
return ansiColorSeqLightBlue
}
}

View File

@ -1,22 +0,0 @@
//go:build !dev
// +build !dev
package build
// consoleLoggerCfg embeds the LoggerConfig struct along with any extensions
// specific to a production deployment.
//
//nolint:ll
type consoleLoggerCfg struct {
*LoggerConfig `yaml:",inline"`
}
// defaultConsoleLoggerCfg returns the default consoleLoggerCfg for the prod
// console logger.
func defaultConsoleLoggerCfg() *consoleLoggerCfg {
return &consoleLoggerCfg{
LoggerConfig: &LoggerConfig{
CallSite: callSiteOff,
},
}
}

View File

@ -1,214 +0,0 @@
package build
import (
"context"
"log/slog"
btclogv1 "github.com/btcsuite/btclog"
"github.com/btcsuite/btclog/v2"
)
// handlerSet is an implementation of Handler that abstracts away multiple
// Handlers.
type handlerSet struct {
level btclogv1.Level
set []btclog.Handler
}
// newHandlerSet constructs a new HandlerSet.
func newHandlerSet(level btclogv1.Level, set ...btclog.Handler) *handlerSet {
h := &handlerSet{
set: set,
level: level,
}
h.SetLevel(level)
return h
}
// Enabled reports whether the handler handles records at the given level.
//
// NOTE: this is part of the slog.Handler interface.
func (h *handlerSet) Enabled(ctx context.Context, level slog.Level) bool {
for _, handler := range h.set {
if !handler.Enabled(ctx, level) {
return false
}
}
return true
}
// Handle handles the Record.
//
// NOTE: this is part of the slog.Handler interface.
func (h *handlerSet) Handle(ctx context.Context, record slog.Record) error {
for _, handler := range h.set {
if err := handler.Handle(ctx, record); err != nil {
return err
}
}
return nil
}
// WithAttrs returns a new Handler whose attributes consist of both the
// receiver's attributes and the arguments.
//
// NOTE: this is part of the slog.Handler interface.
func (h *handlerSet) WithAttrs(attrs []slog.Attr) slog.Handler {
newSet := &reducedSet{set: make([]slog.Handler, len(h.set))}
for i, handler := range h.set {
newSet.set[i] = handler.WithAttrs(attrs)
}
return newSet
}
// WithGroup returns a new Handler with the given group appended to the
// receiver's existing groups.
//
// NOTE: this is part of the slog.Handler interface.
func (h *handlerSet) WithGroup(name string) slog.Handler {
newSet := &reducedSet{set: make([]slog.Handler, len(h.set))}
for i, handler := range h.set {
newSet.set[i] = handler.WithGroup(name)
}
return newSet
}
// SubSystem creates a new Handler with the given sub-system tag.
//
// NOTE: this is part of the Handler interface.
func (h *handlerSet) SubSystem(tag string) btclog.Handler {
newSet := &handlerSet{set: make([]btclog.Handler, len(h.set))}
for i, handler := range h.set {
newSet.set[i] = handler.SubSystem(tag)
}
return newSet
}
// SetLevel changes the logging level of the Handler to the passed
// level.
//
// NOTE: this is part of the btclog.Handler interface.
func (h *handlerSet) SetLevel(level btclogv1.Level) {
for _, handler := range h.set {
handler.SetLevel(level)
}
h.level = level
}
// Level returns the current logging level of the Handler.
//
// NOTE: this is part of the btclog.Handler interface.
func (h *handlerSet) Level() btclogv1.Level {
return h.level
}
// WithPrefix returns a copy of the Handler but with the given string prefixed
// to each log message.
//
// NOTE: this is part of the btclog.Handler interface.
func (h *handlerSet) WithPrefix(prefix string) btclog.Handler {
newSet := &handlerSet{set: make([]btclog.Handler, len(h.set))}
for i, handler := range h.set {
newSet.set[i] = handler.WithPrefix(prefix)
}
return newSet
}
// A compile-time check to ensure that handlerSet implements btclog.Handler.
var _ btclog.Handler = (*handlerSet)(nil)
// reducedSet is an implementation of the slog.Handler interface which is
// itself backed by multiple slog.Handlers. This is used by the handlerSet
// WithGroup and WithAttrs methods so that we can apply the WithGroup and
// WithAttrs to the underlying handlers in the set. These calls, however,
// produce slog.Handlers and not btclog.Handlers. So the reducedSet represents
// the resulting set produced.
type reducedSet struct {
set []slog.Handler
}
// Enabled reports whether the handler handles records at the given level.
//
// NOTE: this is part of the slog.Handler interface.
func (r *reducedSet) Enabled(ctx context.Context, level slog.Level) bool {
for _, handler := range r.set {
if !handler.Enabled(ctx, level) {
return false
}
}
return true
}
// Handle handles the Record.
//
// NOTE: this is part of the slog.Handler interface.
func (r *reducedSet) Handle(ctx context.Context, record slog.Record) error {
for _, handler := range r.set {
if err := handler.Handle(ctx, record); err != nil {
return err
}
}
return nil
}
// WithAttrs returns a new Handler whose attributes consist of both the
// receiver's attributes and the arguments.
//
// NOTE: this is part of the slog.Handler interface.
func (r *reducedSet) WithAttrs(attrs []slog.Attr) slog.Handler {
newSet := &reducedSet{set: make([]slog.Handler, len(r.set))}
for i, handler := range r.set {
newSet.set[i] = handler.WithAttrs(attrs)
}
return newSet
}
// WithGroup returns a new Handler with the given group appended to the
// receiver's existing groups.
//
// NOTE: this is part of the slog.Handler interface.
func (r *reducedSet) WithGroup(name string) slog.Handler {
newSet := &reducedSet{set: make([]slog.Handler, len(r.set))}
for i, handler := range r.set {
newSet.set[i] = handler.WithGroup(name)
}
return newSet
}
// A compile-time check to ensure that handlerSet implements slog.Handler.
var _ slog.Handler = (*reducedSet)(nil)
// subLogGenerator implements the SubLogCreator backed by a Handler.
type subLogGenerator struct {
handler btclog.Handler
}
// newSubLogGenerator constructs a new subLogGenerator from a Handler.
func newSubLogGenerator(handler btclog.Handler) *subLogGenerator {
return &subLogGenerator{
handler: handler,
}
}
// Logger returns a new logger for a particular sub-system.
//
// NOTE: this is part of the SubLogCreator interface.
func (b *subLogGenerator) Logger(subsystemTag string) btclog.Logger {
handler := b.handler.SubSystem(subsystemTag)
return btclog.NewSLogger(handler)
}
// A compile-time check to ensure that handlerSet implements slog.Handler.
var _ SubLogCreator = (*subLogGenerator)(nil)

View File

@ -1,38 +0,0 @@
package build
import (
"os"
"github.com/btcsuite/btclog/v2"
)
// NewDefaultLogHandlers returns the standard console logger and rotating log
// writer handlers that we generally want to use. It also applies the various
// config options to the loggers.
func NewDefaultLogHandlers(cfg *LogConfig,
rotator *RotatingLogWriter) []btclog.Handler {
var handlers []btclog.Handler
consoleLogHandler := btclog.NewDefaultHandler(
os.Stdout, cfg.Console.HandlerOptions()...,
)
logFileHandler := btclog.NewDefaultHandler(
rotator, cfg.File.HandlerOptions()...,
)
maybeAddLogger := func(cmdOptionDisable bool, handler btclog.Handler) {
if !cmdOptionDisable {
handlers = append(handlers, handler)
}
}
switch LoggingType {
case LogTypeStdOut:
maybeAddLogger(cfg.Console.Disable, consoleLogHandler)
case LogTypeDefault:
maybeAddLogger(cfg.Console.Disable, consoleLogHandler)
maybeAddLogger(cfg.File.Disable, logFileHandler)
}
return handlers
}

View File

@ -1,9 +1,11 @@
package build
import (
"os"
"fmt"
"io"
"strings"
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
)
// LogType is an indicating the type of logging specified by the build flag.
@ -34,30 +36,15 @@ func (t LogType) String() string {
}
}
// Declare the supported log file compressors as exported consts for easier use
// from other projects.
const (
// Gzip is the default compressor.
Gzip = "gzip"
// Zstd is a modern compressor that compresses better than Gzip, in less
// time.
Zstd = "zstd"
)
// logCompressors maps the identifier for each supported compression algorithm
// to the extension used for the compressed log files.
var logCompressors = map[string]string{
Gzip: "gz",
Zstd: "zst",
}
// SupportedLogCompressor returns whether or not logCompressor is a supported
// compression algorithm for log files.
func SupportedLogCompressor(logCompressor string) bool {
_, ok := logCompressors[logCompressor]
return ok
// LogWriter is a stub type whose behavior can be changed using the build flags
// "stdlog" and "nolog". The default behavior is to write to both stdout and the
// RotatorPipe. Passing "stdlog" will cause it only to write to stdout, and
// "nolog" implements Write as a no-op.
type LogWriter struct {
// RotatorPipe is the write-end pipe for writing to the log rotator. It
// is written to by the Write method of the LogWriter type. This only
// needs to be set if neither the stdlog or nolog builds are set.
RotatorPipe *io.PipeWriter
}
// NewSubLogger constructs a new subsystem log from the current LogWriter
@ -93,10 +80,8 @@ func NewSubLogger(subsystem string,
// that they share the same backend, since all output is written
// to std out.
case LogTypeStdOut:
backend := btclog.NewDefaultHandler(os.Stdout)
logger := btclog.NewSLogger(
backend.SubSystem(subsystem),
)
backend := btclog.NewBackend(&LogWriter{})
logger := backend.Logger(subsystem)
// Set the logging level of the stdout logger to use the
// configured logging level specified by build flags.
@ -110,3 +95,114 @@ func NewSubLogger(subsystem string,
// For any other configurations, we'll disable logging.
return btclog.Disabled
}
// SubLoggers is a type that holds a map of subsystem loggers keyed by their
// subsystem name.
type SubLoggers map[string]btclog.Logger
// LeveledSubLogger provides the ability to retrieve the subsystem loggers of
// a logger and set their log levels individually or all at once.
type LeveledSubLogger interface {
// SubLoggers returns the map of all registered subsystem loggers.
SubLoggers() SubLoggers
// SupportedSubsystems returns a slice of strings containing the names
// of the supported subsystems. Should ideally correspond to the keys
// of the subsystem logger map and be sorted.
SupportedSubsystems() []string
// SetLogLevel assigns an individual subsystem logger a new log level.
SetLogLevel(subsystemID string, logLevel string)
// SetLogLevels assigns all subsystem loggers the same new log level.
SetLogLevels(logLevel string)
}
// ParseAndSetDebugLevels attempts to parse the specified debug level and set
// the levels accordingly on the given logger. An appropriate error is returned
// if anything is invalid.
func ParseAndSetDebugLevels(level string, logger LeveledSubLogger) error {
// Split at the delimiter.
levels := strings.Split(level, ",")
if len(levels) == 0 {
return fmt.Errorf("invalid log level: %v", level)
}
// If the first entry has no =, treat is as the log level for all
// subsystems.
globalLevel := levels[0]
if !strings.Contains(globalLevel, "=") {
// Validate debug log level.
if !validLogLevel(globalLevel) {
str := "the specified debug level [%v] is invalid"
return fmt.Errorf(str, globalLevel)
}
// Change the logging level for all subsystems.
logger.SetLogLevels(globalLevel)
// The rest will target specific subsystems.
levels = levels[1:]
}
// Go through the subsystem/level pairs while detecting issues and
// update the log levels accordingly.
for _, logLevelPair := range levels {
if !strings.Contains(logLevelPair, "=") {
str := "the specified debug level contains an " +
"invalid subsystem/level pair [%v]"
return fmt.Errorf(str, logLevelPair)
}
// Extract the specified subsystem and log level.
fields := strings.Split(logLevelPair, "=")
if len(fields) != 2 {
str := "the specified debug level has an invalid " +
"format [%v] -- use format subsystem1=level1," +
"subsystem2=level2"
return fmt.Errorf(str, logLevelPair)
}
subsysID, logLevel := fields[0], fields[1]
subLoggers := logger.SubLoggers()
// Validate subsystem.
if _, exists := subLoggers[subsysID]; !exists {
str := "the specified subsystem [%v] is invalid -- " +
"supported subsystems are %v"
return fmt.Errorf(
str, subsysID, logger.SupportedSubsystems(),
)
}
// Validate log level.
if !validLogLevel(logLevel) {
str := "the specified debug level [%v] is invalid"
return fmt.Errorf(str, logLevel)
}
logger.SetLogLevel(subsysID, logLevel)
}
return nil
}
// validLogLevel returns whether or not logLevel is a valid debug log level.
func validLogLevel(logLevel string) bool {
switch logLevel {
case "trace":
fallthrough
case "debug":
fallthrough
case "info":
fallthrough
case "warn":
fallthrough
case "error":
fallthrough
case "critical":
fallthrough
case "off":
return true
}
return false
}

View File

@ -3,6 +3,17 @@
package build
import "os"
// LoggingType is a log type that writes to both stdout and the log rotator, if
// present.
const LoggingType = LogTypeDefault
// Write writes the byte slice to both stdout and the log rotator, if present.
func (w *LogWriter) Write(b []byte) (int, error) {
os.Stdout.Write(b)
if w.RotatorPipe != nil {
w.RotatorPipe.Write(b)
}
return len(b), nil
}

View File

@ -5,3 +5,8 @@ package build
// LoggingType is a log type that writes no logs.
const LoggingType = LogTypeNone
// Write is a noop.
func (w *LogWriter) Write(b []byte) (int, error) {
return len(b), nil
}

View File

@ -1,9 +1,7 @@
package build
import (
"context"
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
)
// ShutdownLogger wraps an existing logger with a shutdown function which will
@ -43,16 +41,3 @@ func (s *ShutdownLogger) Critical(v ...interface{}) {
s.Logger.Info("Sending request for shutdown")
s.shutdown()
}
// CriticalS writes a structured log with the given message and key-value pair
// attributes with LevelCritical to the log. It will then call the shutdown
// logger's shutdown function to prompt safe shutdown.
//
// Note: it is part of the btclog.Logger interface.
func (s *ShutdownLogger) CriticalS(ctx context.Context, msg string, err error,
attr ...interface{}) {
s.Logger.CriticalS(ctx, msg, err, attr...)
s.Logger.Info("Sending request for shutdown")
s.shutdown()
}

View File

@ -3,5 +3,13 @@
package build
import "os"
// LoggingType is a log type that only writes to stdout.
const LoggingType = LogTypeStdOut
// Write writes the provided byte slice to stdout.
func (w *LogWriter) Write(b []byte) (int, error) {
os.Stdout.Write(b)
return len(b), nil
}

View File

@ -3,7 +3,7 @@ package build_test
import (
"testing"
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
"github.com/stretchr/testify/require"
)

View File

@ -1,105 +1,153 @@
package build
import (
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"github.com/btcsuite/btclog"
"github.com/jrick/logrotate/rotator"
"github.com/klauspost/compress/zstd"
)
// RotatingLogWriter is a wrapper around the LogWriter that supports log file
// rotation.
type RotatingLogWriter struct {
// pipe is the write-end pipe for writing to the log rotator.
pipe *io.PipeWriter
logWriter *LogWriter
rotator *rotator.Rotator
backendLog *btclog.Backend
logRotator *rotator.Rotator
subsystemLoggers SubLoggers
}
// A compile time check to ensure RotatingLogWriter implements the
// LeveledSubLogger interface.
var _ LeveledSubLogger = (*RotatingLogWriter)(nil)
// NewRotatingLogWriter creates a new file rotating log writer.
//
// NOTE: `InitLogRotator` must be called to set up log rotation after creating
// the writer.
func NewRotatingLogWriter() *RotatingLogWriter {
return &RotatingLogWriter{}
logWriter := &LogWriter{}
backendLog := btclog.NewBackend(logWriter)
return &RotatingLogWriter{
logWriter: logWriter,
backendLog: backendLog,
subsystemLoggers: SubLoggers{},
}
}
// GenSubLogger creates a new sublogger. A shutdown callback function
// is provided to be able to shutdown in case of a critical error.
func (r *RotatingLogWriter) GenSubLogger(tag string, shutdown func()) btclog.Logger {
logger := r.backendLog.Logger(tag)
return NewShutdownLogger(logger, shutdown)
}
// RegisterSubLogger registers a new subsystem logger.
func (r *RotatingLogWriter) RegisterSubLogger(subsystem string,
logger btclog.Logger) {
r.subsystemLoggers[subsystem] = logger
}
// InitLogRotator initializes the log file rotator to write logs to logFile and
// create roll files in the same directory. It should be called as early on
// startup and possible and must be closed on shutdown by calling `Close`.
func (r *RotatingLogWriter) InitLogRotator(cfg *FileLoggerConfig,
logFile string) error {
func (r *RotatingLogWriter) InitLogRotator(logFile string, maxLogFileSize int,
maxLogFiles int) error {
logDir, _ := filepath.Split(logFile)
err := os.MkdirAll(logDir, 0700)
if err != nil {
return fmt.Errorf("failed to create log directory: %w", err)
}
r.rotator, err = rotator.New(
logFile, int64(cfg.MaxLogFileSize*1024), false, cfg.MaxLogFiles,
r.logRotator, err = rotator.New(
logFile, int64(maxLogFileSize*1024), false, maxLogFiles,
)
if err != nil {
return fmt.Errorf("failed to create file rotator: %w", err)
}
// Reject unknown compressors.
if !SupportedLogCompressor(cfg.Compressor) {
return fmt.Errorf("unknown log compressor: %v", cfg.Compressor)
}
var c rotator.Compressor
switch cfg.Compressor {
case Gzip:
c = gzip.NewWriter(nil)
case Zstd:
c, err = zstd.NewWriter(nil)
if err != nil {
return fmt.Errorf("failed to create zstd compressor: "+
"%w", err)
}
}
// Apply the compressor and its file suffix to the log rotator.
r.rotator.SetCompressor(c, logCompressors[cfg.Compressor])
// Run rotator as a goroutine now but make sure we catch any errors
// that happen in case something with the rotation goes wrong during
// runtime (like running out of disk space or not being allowed to
// create a new logfile for whatever reason).
pr, pw := io.Pipe()
go func() {
err := r.rotator.Run(pr)
err := r.logRotator.Run(pr)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr,
"failed to run file rotator: %v\n", err)
}
}()
r.pipe = pw
r.logWriter.RotatorPipe = pw
return nil
}
// Write writes the byte slice to the log rotator, if present.
func (r *RotatingLogWriter) Write(b []byte) (int, error) {
if r.rotator != nil {
return r.rotator.Write(b)
}
return len(b), nil
}
// Close closes the underlying log rotator if it has already been created.
func (r *RotatingLogWriter) Close() error {
if r.rotator != nil {
return r.rotator.Close()
if r.logRotator != nil {
return r.logRotator.Close()
}
return nil
}
// SubLoggers returns all currently registered subsystem loggers for this log
// writer.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *RotatingLogWriter) SubLoggers() SubLoggers {
return r.subsystemLoggers
}
// SupportedSubsystems returns a sorted string slice of all keys in the
// subsystems map, corresponding to the names of the subsystems.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *RotatingLogWriter) SupportedSubsystems() []string {
// Convert the subsystemLoggers map keys to a string slice.
subsystems := make([]string, 0, len(r.subsystemLoggers))
for subsysID := range r.subsystemLoggers {
subsystems = append(subsystems, subsysID)
}
// Sort the subsystems for stable display.
sort.Strings(subsystems)
return subsystems
}
// SetLogLevel sets the logging level for provided subsystem. Invalid
// subsystems are ignored. Uninitialized subsystems are dynamically created as
// needed.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *RotatingLogWriter) SetLogLevel(subsystemID string, logLevel string) {
// Ignore invalid subsystems.
logger, ok := r.subsystemLoggers[subsystemID]
if !ok {
return
}
// Defaults to info if the log level is invalid.
level, _ := btclog.LevelFromString(logLevel)
logger.SetLevel(level)
}
// SetLogLevels sets the log level for all subsystem loggers to the passed
// level. It also dynamically creates the subsystem loggers as needed, so it
// can be used to initialize the logging system.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *RotatingLogWriter) SetLogLevels(logLevel string) {
// Configure all sub-systems with the new logging level. Dynamically
// create loggers as needed.
for subsystemID := range r.subsystemLoggers {
r.SetLogLevel(subsystemID, logLevel)
}
}

112
build/prefix_log.go Normal file
View File

@ -0,0 +1,112 @@
package build
import "github.com/btcsuite/btclog"
// PrefixLog is a pass-through logger that adds a prefix to every logged line.
type PrefixLog struct {
log btclog.Logger
prefix string
}
// NewPrefixLog instantiates a new prefixed logger.
func NewPrefixLog(prefix string, log btclog.Logger) *PrefixLog {
return &PrefixLog{
prefix: prefix,
log: log,
}
}
// addFormatPrefix prepends the prefix to a format string.
func (p *PrefixLog) addFormatPrefix(s string) string {
return p.prefix + " " + s
}
// addArgsPrefix prepends the prefix to a list of arguments.
func (p *PrefixLog) addArgsPrefix(args []interface{}) []interface{} {
return append([]interface{}{p.prefix}, args...)
}
// Tracef formats message according to format specifier and writes to to log
// with LevelTrace.
func (p *PrefixLog) Tracef(format string, params ...interface{}) {
p.log.Tracef(p.addFormatPrefix(format), params...)
}
// Debugf formats message according to format specifier and writes to log with
// LevelDebug.
func (p *PrefixLog) Debugf(format string, params ...interface{}) {
p.log.Debugf(p.addFormatPrefix(format), params...)
}
// Infof formats message according to format specifier and writes to log with
// LevelInfo.
func (p *PrefixLog) Infof(format string, params ...interface{}) {
p.log.Infof(p.addFormatPrefix(format), params...)
}
// Warnf formats message according to format specifier and writes to to log with
// LevelWarn.
func (p *PrefixLog) Warnf(format string, params ...interface{}) {
p.log.Warnf(p.addFormatPrefix(format), params...)
}
// Errorf formats message according to format specifier and writes to to log
// with LevelError.
func (p *PrefixLog) Errorf(format string, params ...interface{}) {
p.log.Errorf(p.addFormatPrefix(format), params...)
}
// Criticalf formats message according to format specifier and writes to log
// with LevelCritical.
func (p *PrefixLog) Criticalf(format string, params ...interface{}) {
p.log.Criticalf(p.addFormatPrefix(format), params...)
}
// Trace formats message using the default formats for its operands and writes
// to log with LevelTrace.
func (p *PrefixLog) Trace(v ...interface{}) {
p.log.Trace(p.addArgsPrefix(v)...)
}
// Debug formats message using the default formats for its operands and writes
// to log with LevelDebug.
func (p *PrefixLog) Debug(v ...interface{}) {
p.log.Debug(p.addArgsPrefix(v)...)
}
// Info formats message using the default formats for its operands and writes to
// log with LevelInfo.
func (p *PrefixLog) Info(v ...interface{}) {
p.log.Info(p.addArgsPrefix(v)...)
}
// Warn formats message using the default formats for its operands and writes to
// log with LevelWarn.
func (p *PrefixLog) Warn(v ...interface{}) {
p.log.Warn(p.addArgsPrefix(v)...)
}
// Error formats message using the default formats for its operands and writes
// to log with LevelError.
func (p *PrefixLog) Error(v ...interface{}) {
p.log.Error(p.addArgsPrefix(v)...)
}
// Critical formats message using the default formats for its operands and
// writes to log with LevelCritical.
func (p *PrefixLog) Critical(v ...interface{}) {
p.log.Critical(p.addArgsPrefix(v)...)
}
// Level returns the current logging level.
func (p *PrefixLog) Level() btclog.Level {
return p.log.Level()
}
// SetLevel changes the logging level to the passed level.
func (p *PrefixLog) SetLevel(level btclog.Level) {
p.log.SetLevel(level)
}
// Assert that PrefixLog fulfills the btclog.Logger interface.
var _ btclog.Logger = &PrefixLog{}

View File

@ -1,263 +0,0 @@
package build
import (
"fmt"
"sort"
"strings"
"sync"
"github.com/btcsuite/btclog/v2"
)
// SubLogCreator can be used to create a new logger for a particular subsystem.
type SubLogCreator interface {
// Logger returns a new logger for a particular subsystem.
Logger(subsystemTag string) btclog.Logger
}
// SubLoggerManager manages a set of subsystem loggers. Level updates will be
// applied to all the loggers managed by the manager.
type SubLoggerManager struct {
genLogger SubLogCreator
loggers SubLoggers
mu sync.Mutex
}
// A compile time check to ensure SubLoggerManager implements the
// LeveledSubLogger interface.
var _ LeveledSubLogger = (*SubLoggerManager)(nil)
// NewSubLoggerManager constructs a new SubLoggerManager.
func NewSubLoggerManager(handlers ...btclog.Handler) *SubLoggerManager {
return &SubLoggerManager{
loggers: make(SubLoggers),
genLogger: newSubLogGenerator(
newHandlerSet(btclog.LevelInfo, handlers...),
),
}
}
// GenSubLogger creates a new sub-logger and adds it to the set managed by the
// SubLoggerManager. A shutdown callback function is provided to be able to shut
// down in case of a critical error.
func (r *SubLoggerManager) GenSubLogger(subsystem string,
shutdown func()) btclog.Logger {
// Create a new logger with the given subsystem tag.
logger := r.genLogger.Logger(subsystem)
// Wrap the new logger in a Shutdown logger so that the shutdown
// call back is called if a critical log is ever written via this new
// logger.
l := NewShutdownLogger(logger, shutdown)
r.RegisterSubLogger(subsystem, l)
return l
}
// RegisterSubLogger registers the given logger under the given subsystem name.
func (r *SubLoggerManager) RegisterSubLogger(subsystem string,
logger btclog.Logger) {
// Add the new logger to the set of loggers managed by the manager.
r.mu.Lock()
r.loggers[subsystem] = logger
r.mu.Unlock()
}
// SubLoggers returns all currently registered subsystem loggers for this log
// writer.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *SubLoggerManager) SubLoggers() SubLoggers {
r.mu.Lock()
defer r.mu.Unlock()
return r.loggers
}
// SupportedSubsystems returns a sorted string slice of all keys in the
// subsystems map, corresponding to the names of the subsystems.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *SubLoggerManager) SupportedSubsystems() []string {
r.mu.Lock()
defer r.mu.Unlock()
// Convert the subsystemLoggers map keys to a string slice.
subsystems := make([]string, 0, len(r.loggers))
for subsysID := range r.loggers {
subsystems = append(subsystems, subsysID)
}
// Sort the subsystems for stable display.
sort.Strings(subsystems)
return subsystems
}
// SetLogLevel sets the logging level for provided subsystem. Invalid
// subsystems are ignored. Uninitialized subsystems are dynamically created as
// needed.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *SubLoggerManager) SetLogLevel(subsystemID string, logLevel string) {
r.mu.Lock()
defer r.mu.Unlock()
r.setLogLevelUnsafe(subsystemID, logLevel)
}
// setLogLevelUnsafe sets the logging level for provided subsystem. Invalid
// subsystems are ignored. Uninitialized subsystems are dynamically created as
// needed.
//
// NOTE: the SubLoggerManager mutex must be held before calling this method.
func (r *SubLoggerManager) setLogLevelUnsafe(subsystemID string,
logLevel string) {
// Ignore invalid subsystems.
logger, ok := r.loggers[subsystemID]
if !ok {
return
}
// Defaults to info if the log level is invalid.
level, _ := btclog.LevelFromString(logLevel)
logger.SetLevel(level)
}
// SetLogLevels sets the log level for all subsystem loggers to the passed
// level. It also dynamically creates the subsystem loggers as needed, so it
// can be used to initialize the logging system.
//
// NOTE: This is part of the LeveledSubLogger interface.
func (r *SubLoggerManager) SetLogLevels(logLevel string) {
r.mu.Lock()
defer r.mu.Unlock()
// Configure all sub-systems with the new logging level. Dynamically
// create loggers as needed.
for subsystemID := range r.loggers {
r.setLogLevelUnsafe(subsystemID, logLevel)
}
}
// SubLoggers is a type that holds a map of subsystem loggers keyed by their
// subsystem name.
type SubLoggers map[string]btclog.Logger
// LeveledSubLogger provides the ability to retrieve the subsystem loggers of
// a logger and set their log levels individually or all at once.
type LeveledSubLogger interface {
// SubLoggers returns the map of all registered subsystem loggers.
SubLoggers() SubLoggers
// SupportedSubsystems returns a slice of strings containing the names
// of the supported subsystems. Should ideally correspond to the keys
// of the subsystem logger map and be sorted.
SupportedSubsystems() []string
// SetLogLevel assigns an individual subsystem logger a new log level.
SetLogLevel(subsystemID string, logLevel string)
// SetLogLevels assigns all subsystem loggers the same new log level.
SetLogLevels(logLevel string)
}
// ParseAndSetDebugLevels attempts to parse the specified debug level and set
// the levels accordingly on the given logger. An appropriate error is returned
// if anything is invalid.
func ParseAndSetDebugLevels(level string, logger LeveledSubLogger) error {
// Split at the delimiter.
levels := strings.Split(level, ",")
if len(levels) == 0 {
return fmt.Errorf("invalid log level: %v", level)
}
// If the first entry has no =, treat is as the log level for all
// subsystems.
globalLevel := levels[0]
if !strings.Contains(globalLevel, "=") {
// Validate debug log level.
if !validLogLevel(globalLevel) {
str := "the specified debug level [%v] is invalid"
return fmt.Errorf(str, globalLevel)
}
// Change the logging level for all subsystems.
logger.SetLogLevels(globalLevel)
// The rest will target specific subsystems.
levels = levels[1:]
}
// Go through the subsystem/level pairs while detecting issues and
// update the log levels accordingly.
for _, logLevelPair := range levels {
if !strings.Contains(logLevelPair, "=") {
str := "the specified debug level contains an " +
"invalid subsystem/level pair [%v]"
return fmt.Errorf(str, logLevelPair)
}
// Extract the specified subsystem and log level.
fields := strings.Split(logLevelPair, "=")
if len(fields) != 2 {
str := "the specified debug level has an invalid " +
"format [%v] -- use format subsystem1=level1," +
"subsystem2=level2"
return fmt.Errorf(str, logLevelPair)
}
subsysID, logLevel := fields[0], fields[1]
subLoggers := logger.SubLoggers()
// Validate subsystem.
if _, exists := subLoggers[subsysID]; !exists {
str := "the specified subsystem [%v] is invalid -- " +
"supported subsystems are %v"
return fmt.Errorf(
str, subsysID, logger.SupportedSubsystems(),
)
}
// Validate log level.
if !validLogLevel(logLevel) {
str := "the specified debug level [%v] is invalid"
return fmt.Errorf(str, logLevel)
}
logger.SetLogLevel(subsysID, logLevel)
}
return nil
}
// validLogLevel returns whether or not logLevel is a valid debug log level.
func validLogLevel(logLevel string) bool {
switch logLevel {
case "trace":
fallthrough
case "debug":
fallthrough
case "info":
fallthrough
case "warn":
fallthrough
case "error":
fallthrough
case "critical":
fallthrough
case "off":
return true
}
return false
}

View File

@ -6,13 +6,9 @@
package build
import (
"context"
"encoding/hex"
"fmt"
"runtime/debug"
"strings"
"github.com/btcsuite/btclog/v2"
)
var (
@ -44,10 +40,10 @@ const (
AppMajor uint = 0
// AppMinor defines the minor version of this binary.
AppMinor uint = 19
AppMinor uint = 18
// AppPatch defines the application patch for this binary.
AppPatch uint = 3
AppPatch uint = 4
// AppPreRelease MUST only contain characters from semanticAlphabet per
// the semantic versioning spec.
@ -105,22 +101,3 @@ func Tags() []string {
return strings.Split(RawTags, ",")
}
// WithBuildInfo derives a child context with the build information attached as
// attributes. At the moment, this only includes the current build's commit
// hash.
func WithBuildInfo(ctx context.Context, cfg *LogConfig) (context.Context,
error) {
if cfg.NoCommitHash {
return ctx, nil
}
// Convert the commit hash to a byte slice.
commitHash, err := hex.DecodeString(CommitHash)
if err != nil {
return nil, fmt.Errorf("unable to decode commit hash: %w", err)
}
return btclog.WithCtx(ctx, btclog.Hex3("rev", commitHash)), nil
}

View File

@ -1,152 +0,0 @@
# Chainio
`chainio` is a package designed to provide blockchain data access to various
subsystems within `lnd`. When a new block is received, it is encapsulated in a
`Blockbeat` object and disseminated to all registered consumers. Consumers may
receive these updates either concurrently or sequentially, based on their
registration configuration, ensuring that each subsystem maintains a
synchronized view of the current block state.
The main components include:
- `Blockbeat`: An interface that provides information about the block.
- `Consumer`: An interface that specifies how subsystems handle the blockbeat.
- `BlockbeatDispatcher`: The core service responsible for receiving each block
and distributing it to all consumers.
Additionally, the `BeatConsumer` struct provides a partial implementation of
the `Consumer` interface. This struct helps reduce code duplication, allowing
subsystems to avoid re-implementing the `ProcessBlock` method and provides a
commonly used `NotifyBlockProcessed` method.
### Register a Consumer
Consumers within the same queue are notified **sequentially**, while all queues
are notified **concurrently**. A queue consists of a slice of consumers, which
are notified in left-to-right order. Developers are responsible for determining
dependencies in block consumption across subsystems: independent subsystems
should be notified concurrently, whereas dependent subsystems should be
notified sequentially.
To notify the consumers concurrently, put them in different queues,
```go
// consumer1 and consumer2 will be notified concurrently.
queue1 := []chainio.Consumer{consumer1}
blockbeatDispatcher.RegisterQueue(consumer1)
queue2 := []chainio.Consumer{consumer2}
blockbeatDispatcher.RegisterQueue(consumer2)
```
To notify the consumers sequentially, put them in the same queue,
```go
// consumers will be notified sequentially via,
// consumer1 -> consumer2 -> consumer3
queue := []chainio.Consumer{
consumer1,
consumer2,
consumer3,
}
blockbeatDispatcher.RegisterQueue(queue)
```
### Implement the `Consumer` Interface
Implementing the `Consumer` interface is straightforward. Below is an example
of how
[`sweep.TxPublisher`](https://github.com/lightningnetwork/lnd/blob/5cec466fad44c582a64cfaeb91f6d5fd302fcf85/sweep/fee_bumper.go#L310)
implements this interface.
To start, embed the partial implementation `chainio.BeatConsumer`, which
already provides the `ProcessBlock` implementation and commonly used
`NotifyBlockProcessed` method, and exposes `BlockbeatChan` for the consumer to
receive blockbeats.
```go
type TxPublisher struct {
started atomic.Bool
stopped atomic.Bool
chainio.BeatConsumer
...
```
We should also remember to initialize this `BeatConsumer`,
```go
...
// Mount the block consumer.
tp.BeatConsumer = chainio.NewBeatConsumer(tp.quit, tp.Name())
```
Finally, in the main event loop, read from `BlockbeatChan`, process the
received blockbeat, and, crucially, call `tp.NotifyBlockProcessed` to inform
the blockbeat dispatcher that processing is complete.
```go
for {
select {
case beat := <-tp.BlockbeatChan:
// Consume this blockbeat, usually it means updating the subsystem
// using the new block data.
// Notify we've processed the block.
tp.NotifyBlockProcessed(beat, nil)
...
```
### Existing Queues
Currently, we have a single queue of consumers dedicated to handling force
closures. This queue includes `ChainArbitrator`, `UtxoSweeper`, and
`TxPublisher`, with `ChainArbitrator` managing two internal consumers:
`chainWatcher` and `ChannelArbitrator`. The blockbeat flows sequentially
through the chain as follows: `ChainArbitrator => chainWatcher =>
ChannelArbitrator => UtxoSweeper => TxPublisher`. The following diagram
illustrates the flow within the public subsystems.
```mermaid
sequenceDiagram
autonumber
participant bb as BlockBeat
participant cc as ChainArb
participant us as UtxoSweeper
participant tp as TxPublisher
note left of bb: 0. received block x,<br>dispatching...
note over bb,cc: 1. send block x to ChainArb,<br>wait for its done signal
bb->>cc: block x
rect rgba(165, 0, 85, 0.8)
critical signal processed
cc->>bb: processed block
option Process error or timeout
bb->>bb: error and exit
end
end
note over bb,us: 2. send block x to UtxoSweeper, wait for its done signal
bb->>us: block x
rect rgba(165, 0, 85, 0.8)
critical signal processed
us->>bb: processed block
option Process error or timeout
bb->>bb: error and exit
end
end
note over bb,tp: 3. send block x to TxPublisher, wait for its done signal
bb->>tp: block x
rect rgba(165, 0, 85, 0.8)
critical signal processed
tp->>bb: processed block
option Process error or timeout
bb->>bb: error and exit
end
end
```

View File

@ -1,54 +0,0 @@
package chainio
import (
"fmt"
"github.com/btcsuite/btclog/v2"
"github.com/lightningnetwork/lnd/chainntnfs"
)
// Beat implements the Blockbeat interface. It contains the block epoch and a
// customized logger.
//
// TODO(yy): extend this to check for confirmation status - which serves as the
// single source of truth, to avoid the potential race between receiving blocks
// and `GetTransactionDetails/RegisterSpendNtfn/RegisterConfirmationsNtfn`.
type Beat struct {
// epoch is the current block epoch the blockbeat is aware of.
epoch chainntnfs.BlockEpoch
// log is the customized logger for the blockbeat which prints the
// block height.
log btclog.Logger
}
// Compile-time check to ensure Beat satisfies the Blockbeat interface.
var _ Blockbeat = (*Beat)(nil)
// NewBeat creates a new beat with the specified block epoch and a customized
// logger.
func NewBeat(epoch chainntnfs.BlockEpoch) *Beat {
b := &Beat{
epoch: epoch,
}
// Create a customized logger for the blockbeat.
logPrefix := fmt.Sprintf("Height[%6d]:", b.Height())
b.log = clog.WithPrefix(logPrefix)
return b
}
// Height returns the height of the block epoch.
//
// NOTE: Part of the Blockbeat interface.
func (b *Beat) Height() int32 {
return b.epoch.Height
}
// logger returns the logger for the blockbeat.
//
// NOTE: Part of the private blockbeat interface.
func (b *Beat) logger() btclog.Logger {
return b.log
}

View File

@ -1,28 +0,0 @@
package chainio
import (
"errors"
"testing"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/stretchr/testify/require"
)
var errDummy = errors.New("dummy error")
// TestNewBeat tests the NewBeat and Height functions.
func TestNewBeat(t *testing.T) {
t.Parallel()
// Create a testing epoch.
epoch := chainntnfs.BlockEpoch{
Height: 1,
}
// Create the beat and check the internal state.
beat := NewBeat(epoch)
require.Equal(t, epoch, beat.epoch)
// Check the height function.
require.Equal(t, epoch.Height, beat.Height())
}

View File

@ -1,113 +0,0 @@
package chainio
// BeatConsumer defines a supplementary component that should be used by
// subsystems which implement the `Consumer` interface. It partially implements
// the `Consumer` interface by providing the method `ProcessBlock` such that
// subsystems don't need to re-implement it.
//
// While inheritance is not commonly used in Go, subsystems embedding this
// struct cannot pass the interface check for `Consumer` because the `Name`
// method is not implemented, which gives us a "mortise and tenon" structure.
// In addition to reducing code duplication, this design allows `ProcessBlock`
// to work on the concrete type `Beat` to access its internal states.
type BeatConsumer struct {
// BlockbeatChan is a channel to receive blocks from Blockbeat. The
// received block contains the best known height and the txns confirmed
// in this block.
BlockbeatChan chan Blockbeat
// name is the name of the consumer which embeds the BlockConsumer.
name string
// quit is a channel that closes when the BlockConsumer is shutting
// down.
//
// NOTE: this quit channel should be mounted to the same quit channel
// used by the subsystem.
quit chan struct{}
// errChan is a buffered chan that receives an error returned from
// processing this block.
errChan chan error
}
// NewBeatConsumer creates a new BlockConsumer.
func NewBeatConsumer(quit chan struct{}, name string) BeatConsumer {
// Refuse to start `lnd` if the quit channel is not initialized. We
// treat this case as if we are facing a nil pointer dereference, as
// there's no point to return an error here, which will cause the node
// to fail to be started anyway.
if quit == nil {
panic("quit channel is nil")
}
b := BeatConsumer{
BlockbeatChan: make(chan Blockbeat),
name: name,
errChan: make(chan error, 1),
quit: quit,
}
return b
}
// ProcessBlock takes a blockbeat and sends it to the consumer's blockbeat
// channel. It will send it to the subsystem's BlockbeatChan, and block until
// the processed result is received from the subsystem. The subsystem must call
// `NotifyBlockProcessed` after it has finished processing the block.
//
// NOTE: part of the `chainio.Consumer` interface.
func (b *BeatConsumer) ProcessBlock(beat Blockbeat) error {
// Update the current height.
beat.logger().Tracef("set current height for [%s]", b.name)
select {
// Send the beat to the blockbeat channel. It's expected that the
// consumer will read from this channel and process the block. Once
// processed, it should return the error or nil to the beat.Err chan.
case b.BlockbeatChan <- beat:
beat.logger().Tracef("Sent blockbeat to [%s]", b.name)
case <-b.quit:
beat.logger().Debugf("[%s] received shutdown before sending "+
"beat", b.name)
return nil
}
// Check the consumer's err chan. We expect the consumer to call
// `beat.NotifyBlockProcessed` to send the error back here.
select {
case err := <-b.errChan:
beat.logger().Tracef("[%s] processed beat: err=%v", b.name, err)
return err
case <-b.quit:
beat.logger().Debugf("[%s] received shutdown", b.name)
}
return nil
}
// NotifyBlockProcessed signals that the block has been processed. It takes the
// blockbeat being processed and an error resulted from processing it. This
// error is then sent back to the consumer's err chan to unblock
// `ProcessBlock`.
//
// NOTE: This method must be called by the subsystem after it has finished
// processing the block.
func (b *BeatConsumer) NotifyBlockProcessed(beat Blockbeat, err error) {
// Update the current height.
beat.logger().Tracef("[%s]: notifying beat processed", b.name)
select {
case b.errChan <- err:
beat.logger().Tracef("[%s]: notified beat processed, err=%v",
b.name, err)
case <-b.quit:
beat.logger().Debugf("[%s] received shutdown before notifying "+
"beat processed", b.name)
}
}

View File

@ -1,202 +0,0 @@
package chainio
import (
"testing"
"time"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/stretchr/testify/require"
)
// TestNewBeatConsumer tests the NewBeatConsumer function.
func TestNewBeatConsumer(t *testing.T) {
t.Parallel()
quitChan := make(chan struct{})
name := "test"
// Test the NewBeatConsumer function.
b := NewBeatConsumer(quitChan, name)
// Assert the state.
require.Equal(t, quitChan, b.quit)
require.Equal(t, name, b.name)
require.NotNil(t, b.BlockbeatChan)
}
// TestProcessBlockSuccess tests when the block is processed successfully, no
// error is returned.
func TestProcessBlockSuccess(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan.
consumerErrChan := make(chan error, 1)
b.errChan = consumerErrChan
// Call the method under test.
resultChan := make(chan error, 1)
go func() {
resultChan <- b.ProcessBlock(mockBeat)
}()
// Assert the beat is sent to the blockbeat channel.
beat, err := fn.RecvOrTimeout(b.BlockbeatChan, time.Second)
require.NoError(t, err)
require.Equal(t, mockBeat, beat)
// Send nil to the consumer's error channel.
consumerErrChan <- nil
// Assert the result of ProcessBlock is nil.
result, err := fn.RecvOrTimeout(resultChan, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestProcessBlockConsumerQuitBeforeSend tests when the consumer is quit
// before sending the beat, the method returns immediately.
func TestProcessBlockConsumerQuitBeforeSend(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Call the method under test.
resultChan := make(chan error, 1)
go func() {
resultChan <- b.ProcessBlock(mockBeat)
}()
// Instead of reading the BlockbeatChan, close the quit channel.
close(quitChan)
// Assert ProcessBlock returned nil.
result, err := fn.RecvOrTimeout(resultChan, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestProcessBlockConsumerQuitAfterSend tests when the consumer is quit after
// sending the beat, the method returns immediately.
func TestProcessBlockConsumerQuitAfterSend(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan.
consumerErrChan := make(chan error, 1)
b.errChan = consumerErrChan
// Call the method under test.
resultChan := make(chan error, 1)
go func() {
resultChan <- b.ProcessBlock(mockBeat)
}()
// Assert the beat is sent to the blockbeat channel.
beat, err := fn.RecvOrTimeout(b.BlockbeatChan, time.Second)
require.NoError(t, err)
require.Equal(t, mockBeat, beat)
// Instead of sending nil to the consumer's error channel, close the
// quit channel.
close(quitChan)
// Assert ProcessBlock returned nil.
result, err := fn.RecvOrTimeout(resultChan, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestNotifyBlockProcessedSendErr asserts the error can be sent and read by
// the beat via NotifyBlockProcessed.
func TestNotifyBlockProcessedSendErr(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan.
consumerErrChan := make(chan error, 1)
b.errChan = consumerErrChan
// Call the method under test.
done := make(chan error)
go func() {
defer close(done)
b.NotifyBlockProcessed(mockBeat, errDummy)
}()
// Assert the error is sent to the beat's err chan.
result, err := fn.RecvOrTimeout(consumerErrChan, time.Second)
require.NoError(t, err)
require.ErrorIs(t, result, errDummy)
// Assert the done channel is closed.
result, err = fn.RecvOrTimeout(done, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}
// TestNotifyBlockProcessedOnQuit asserts NotifyBlockProcessed exits
// immediately when the quit channel is closed.
func TestNotifyBlockProcessedOnQuit(t *testing.T) {
t.Parallel()
// Create a test consumer.
quitChan := make(chan struct{})
b := NewBeatConsumer(quitChan, "test")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock the consumer's err chan - we don't buffer it so it will block
// on sending the error.
consumerErrChan := make(chan error)
b.errChan = consumerErrChan
// Call the method under test.
done := make(chan error)
go func() {
defer close(done)
b.NotifyBlockProcessed(mockBeat, errDummy)
}()
// Close the quit channel so the method will return.
close(b.quit)
// Assert the done channel is closed.
result, err := fn.RecvOrTimeout(done, time.Second)
require.NoError(t, err)
require.Nil(t, result)
}

View File

@ -1,366 +0,0 @@
package chainio
import (
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
"github.com/btcsuite/btclog/v2"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/lnutils"
"golang.org/x/sync/errgroup"
)
// DefaultProcessBlockTimeout is the timeout value used when waiting for one
// consumer to finish processing the new block epoch.
var DefaultProcessBlockTimeout = 60 * time.Second
// ErrProcessBlockTimeout is the error returned when a consumer takes too long
// to process the block.
var ErrProcessBlockTimeout = errors.New("process block timeout")
// BlockbeatDispatcher is a service that handles dispatching new blocks to
// `lnd`'s subsystems. During startup, subsystems that are block-driven should
// implement the `Consumer` interface and register themselves via
// `RegisterQueue`. When two subsystems are independent of each other, they
// should be registered in different queues so blocks are notified concurrently.
// Otherwise, when living in the same queue, the subsystems are notified of the
// new blocks sequentially, which means it's critical to understand the
// relationship of these systems to properly handle the order.
type BlockbeatDispatcher struct {
wg sync.WaitGroup
// notifier is used to receive new block epochs.
notifier chainntnfs.ChainNotifier
// beat is the latest blockbeat received.
beat Blockbeat
// consumerQueues is a map of consumers that will receive blocks. Its
// key is a unique counter and its value is a queue of consumers. Each
// queue is notified concurrently, and consumers in the same queue is
// notified sequentially.
consumerQueues map[uint32][]Consumer
// counter is used to assign a unique id to each queue.
counter atomic.Uint32
// quit is used to signal the BlockbeatDispatcher to stop.
quit chan struct{}
// queryHeightChan is used to receive queries on the current height of
// the dispatcher.
queryHeightChan chan *query
}
// query is used to fetch the internal state of the dispatcher.
type query struct {
// respChan is used to send back the current height back to the caller.
//
// NOTE: This channel must be buffered.
respChan chan int32
}
// newQuery creates a query to be used to fetch the internal state of the
// dispatcher.
func newQuery() *query {
return &query{
respChan: make(chan int32, 1),
}
}
// NewBlockbeatDispatcher returns a new blockbeat dispatcher instance.
func NewBlockbeatDispatcher(n chainntnfs.ChainNotifier) *BlockbeatDispatcher {
return &BlockbeatDispatcher{
notifier: n,
quit: make(chan struct{}),
consumerQueues: make(map[uint32][]Consumer),
queryHeightChan: make(chan *query, 1),
}
}
// RegisterQueue takes a list of consumers and registers them in the same
// queue.
//
// NOTE: these consumers are notified sequentially.
func (b *BlockbeatDispatcher) RegisterQueue(consumers []Consumer) {
qid := b.counter.Add(1)
b.consumerQueues[qid] = append(b.consumerQueues[qid], consumers...)
clog.Infof("Registered queue=%d with %d blockbeat consumers", qid,
len(consumers))
for _, c := range consumers {
clog.Debugf("Consumer [%s] registered in queue %d", c.Name(),
qid)
}
}
// Start starts the blockbeat dispatcher - it registers a block notification
// and monitors and dispatches new blocks in a goroutine. It will refuse to
// start if there are no registered consumers.
func (b *BlockbeatDispatcher) Start() error {
// Make sure consumers are registered.
if len(b.consumerQueues) == 0 {
return fmt.Errorf("no consumers registered")
}
// Start listening to new block epochs. We should get a notification
// with the current best block immediately.
blockEpochs, err := b.notifier.RegisterBlockEpochNtfn(nil)
if err != nil {
return fmt.Errorf("register block epoch ntfn: %w", err)
}
clog.Infof("BlockbeatDispatcher is starting with %d consumer queues",
len(b.consumerQueues))
defer clog.Debug("BlockbeatDispatcher started")
b.wg.Add(1)
go b.dispatchBlocks(blockEpochs)
return nil
}
// Stop shuts down the blockbeat dispatcher.
func (b *BlockbeatDispatcher) Stop() {
clog.Info("BlockbeatDispatcher is stopping")
defer clog.Debug("BlockbeatDispatcher stopped")
// Signal the dispatchBlocks goroutine to stop.
close(b.quit)
b.wg.Wait()
}
func (b *BlockbeatDispatcher) log() btclog.Logger {
// There's no guarantee that the `b.beat` is initialized when the
// dispatcher shuts down, especially in the case where the node is
// running as a remote signer, which doesn't have a chainbackend. In
// that case we will use the package logger.
if b.beat == nil {
return clog
}
return b.beat.logger()
}
// dispatchBlocks listens to new block epoch and dispatches it to all the
// consumers. Each queue is notified concurrently, and the consumers in the
// same queue are notified sequentially.
//
// NOTE: Must be run as a goroutine.
func (b *BlockbeatDispatcher) dispatchBlocks(
blockEpochs *chainntnfs.BlockEpochEvent) {
defer b.wg.Done()
defer blockEpochs.Cancel()
for {
select {
case blockEpoch, ok := <-blockEpochs.Epochs:
if !ok {
clog.Debugf("Block epoch channel closed")
return
}
// Log a separator so it's easier to identify when a
// new block arrives for subsystems.
clog.Debugf("%v", lnutils.NewSeparatorClosure())
clog.Debugf("Received new block %v at height %d, "+
"notifying consumers...", blockEpoch.Hash,
blockEpoch.Height)
// Record the time it takes the consumer to process
// this block.
start := time.Now()
// Update the current block epoch.
b.beat = NewBeat(*blockEpoch)
// Notify all consumers.
err := b.notifyQueues()
if err != nil {
b.log().Errorf("Notify block failed: %v", err)
}
b.log().Debugf("Notified all consumers on new block "+
"in %v", time.Since(start))
// A query has been made to fetch the current height, we now
// send the height from its current beat.
case query := <-b.queryHeightChan:
// The beat may not be set yet, e.g., during the startup
// the query is made before the block epoch being sent.
height := int32(0)
if b.beat != nil {
height = b.beat.Height()
}
query.respChan <- height
case <-b.quit:
b.log().Debugf("BlockbeatDispatcher quit signal " +
"received")
return
}
}
}
// CurrentHeight returns the current best height known to the dispatcher. 0 is
// returned if the dispatcher is shutting down.
func (b *BlockbeatDispatcher) CurrentHeight() int32 {
query := newQuery()
select {
case b.queryHeightChan <- query:
case <-b.quit:
clog.Debugf("BlockbeatDispatcher quit before query")
return 0
}
select {
case height := <-query.respChan:
clog.Debugf("Responded current height: %v", height)
return height
case <-b.quit:
clog.Debugf("BlockbeatDispatcher quit before response")
return 0
}
}
// notifyQueues notifies each queue concurrently about the latest block epoch.
func (b *BlockbeatDispatcher) notifyQueues() error {
// errChans is a map of channels that will be used to receive errors
// returned from notifying the consumers.
errChans := make(map[uint32]chan error, len(b.consumerQueues))
// Notify each queue in goroutines.
for qid, consumers := range b.consumerQueues {
b.log().Debugf("Notifying queue=%d with %d consumers", qid,
len(consumers))
// Create a signal chan.
errChan := make(chan error, 1)
errChans[qid] = errChan
// Notify each queue concurrently.
go func(qid uint32, c []Consumer, beat Blockbeat) {
// Notify each consumer in this queue sequentially.
errChan <- DispatchSequential(beat, c)
}(qid, consumers, b.beat)
}
// Wait for all consumers in each queue to finish.
for qid, errChan := range errChans {
select {
case err := <-errChan:
if err != nil {
return fmt.Errorf("queue=%d got err: %w", qid,
err)
}
b.log().Debugf("Notified queue=%d", qid)
case <-b.quit:
b.log().Debugf("BlockbeatDispatcher quit signal " +
"received, exit notifyQueues")
return nil
}
}
return nil
}
// DispatchSequential takes a list of consumers and notify them about the new
// epoch sequentially. It requires the consumer to finish processing the block
// within the specified time, otherwise a timeout error is returned.
func DispatchSequential(b Blockbeat, consumers []Consumer) error {
for _, c := range consumers {
// Send the beat to the consumer.
err := notifyAndWait(b, c, DefaultProcessBlockTimeout)
if err != nil {
b.logger().Errorf("Failed to process block: %v", err)
return err
}
}
return nil
}
// DispatchConcurrent notifies each consumer concurrently about the blockbeat.
// It requires the consumer to finish processing the block within the specified
// time, otherwise a timeout error is returned.
func DispatchConcurrent(b Blockbeat, consumers []Consumer) error {
eg := &errgroup.Group{}
// Notify each queue in goroutines.
for _, c := range consumers {
// Notify each consumer concurrently.
eg.Go(func() error {
// Send the beat to the consumer.
err := notifyAndWait(b, c, DefaultProcessBlockTimeout)
// Exit early if there's no error.
if err == nil {
return nil
}
b.logger().Errorf("Consumer=%v failed to process "+
"block: %v", c.Name(), err)
return err
})
}
// Wait for all consumers in each queue to finish.
if err := eg.Wait(); err != nil {
return err
}
return nil
}
// notifyAndWait sends the blockbeat to the specified consumer. It requires the
// consumer to finish processing the block within the specified time, otherwise
// a timeout error is returned.
func notifyAndWait(b Blockbeat, c Consumer, timeout time.Duration) error {
b.logger().Debugf("Waiting for consumer[%s] to process it", c.Name())
// Record the time it takes the consumer to process this block.
start := time.Now()
errChan := make(chan error, 1)
go func() {
errChan <- c.ProcessBlock(b)
}()
// We expect the consumer to finish processing this block under 30s,
// otherwise a timeout error is returned.
select {
case err := <-errChan:
if err == nil {
break
}
return fmt.Errorf("%s got err in ProcessBlock: %w", c.Name(),
err)
case <-time.After(timeout):
return fmt.Errorf("consumer %s: %w", c.Name(),
ErrProcessBlockTimeout)
}
b.logger().Debugf("Consumer[%s] processed block in %v", c.Name(),
time.Since(start))
return nil
}

View File

@ -1,440 +0,0 @@
package chainio
import (
"testing"
"time"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
// TestNotifyAndWaitOnConsumerErr asserts when the consumer returns an error,
// it's returned by notifyAndWait.
func TestNotifyAndWaitOnConsumerErr(t *testing.T) {
t.Parallel()
// Create a mock consumer.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock ProcessBlock to return an error.
consumer.On("ProcessBlock", mockBeat).Return(errDummy).Once()
// Call the method under test.
err := notifyAndWait(mockBeat, consumer, DefaultProcessBlockTimeout)
// We expect the error to be returned.
require.ErrorIs(t, err, errDummy)
}
// TestNotifyAndWaitOnConsumerErr asserts when the consumer successfully
// processed the beat, no error is returned.
func TestNotifyAndWaitOnConsumerSuccess(t *testing.T) {
t.Parallel()
// Create a mock consumer.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock ProcessBlock to return nil.
consumer.On("ProcessBlock", mockBeat).Return(nil).Once()
// Call the method under test.
err := notifyAndWait(mockBeat, consumer, DefaultProcessBlockTimeout)
// We expect a nil error to be returned.
require.NoError(t, err)
}
// TestNotifyAndWaitOnConsumerTimeout asserts when the consumer times out
// processing the block, the timeout error is returned.
func TestNotifyAndWaitOnConsumerTimeout(t *testing.T) {
t.Parallel()
// Set timeout to be 10ms.
processBlockTimeout := 10 * time.Millisecond
// Create a mock consumer.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker")
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Mock ProcessBlock to return nil but blocks on returning.
consumer.On("ProcessBlock", mockBeat).Return(nil).Run(
func(args mock.Arguments) {
// Sleep one second to block on the method.
time.Sleep(processBlockTimeout * 100)
}).Once()
// Call the method under test.
err := notifyAndWait(mockBeat, consumer, processBlockTimeout)
// We expect a timeout error to be returned.
require.ErrorIs(t, err, ErrProcessBlockTimeout)
}
// TestDispatchSequential checks that the beat is sent to the consumers
// sequentially.
func TestDispatchSequential(t *testing.T) {
t.Parallel()
// Create three mock consumers.
consumer1 := &MockConsumer{}
defer consumer1.AssertExpectations(t)
consumer1.On("Name").Return("mocker1")
consumer2 := &MockConsumer{}
defer consumer2.AssertExpectations(t)
consumer2.On("Name").Return("mocker2")
consumer3 := &MockConsumer{}
defer consumer3.AssertExpectations(t)
consumer3.On("Name").Return("mocker3")
consumers := []Consumer{consumer1, consumer2, consumer3}
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// prevConsumer specifies the previous consumer that was called.
var prevConsumer string
// Mock the ProcessBlock on consumers to return immediately.
consumer1.On("ProcessBlock", mockBeat).Return(nil).Run(
func(args mock.Arguments) {
// Check the order of the consumers.
//
// The first consumer should have no previous consumer.
require.Empty(t, prevConsumer)
// Set the consumer as the previous consumer.
prevConsumer = consumer1.Name()
}).Once()
consumer2.On("ProcessBlock", mockBeat).Return(nil).Run(
func(args mock.Arguments) {
// Check the order of the consumers.
//
// The second consumer should see consumer1.
require.Equal(t, consumer1.Name(), prevConsumer)
// Set the consumer as the previous consumer.
prevConsumer = consumer2.Name()
}).Once()
consumer3.On("ProcessBlock", mockBeat).Return(nil).Run(
func(args mock.Arguments) {
// Check the order of the consumers.
//
// The third consumer should see consumer2.
require.Equal(t, consumer2.Name(), prevConsumer)
// Set the consumer as the previous consumer.
prevConsumer = consumer3.Name()
}).Once()
// Call the method under test.
err := DispatchSequential(mockBeat, consumers)
require.NoError(t, err)
// Check the previous consumer is the last consumer.
require.Equal(t, consumer3.Name(), prevConsumer)
}
// TestRegisterQueue tests the RegisterQueue function.
func TestRegisterQueue(t *testing.T) {
t.Parallel()
// Create two mock consumers.
consumer1 := &MockConsumer{}
defer consumer1.AssertExpectations(t)
consumer1.On("Name").Return("mocker1")
consumer2 := &MockConsumer{}
defer consumer2.AssertExpectations(t)
consumer2.On("Name").Return("mocker2")
consumers := []Consumer{consumer1, consumer2}
// Create a mock chain notifier.
mockNotifier := &chainntnfs.MockChainNotifier{}
defer mockNotifier.AssertExpectations(t)
// Create a new dispatcher.
b := NewBlockbeatDispatcher(mockNotifier)
// Register the consumers.
b.RegisterQueue(consumers)
// Assert that the consumers have been registered.
//
// We should have one queue.
require.Len(t, b.consumerQueues, 1)
// The queue should have two consumers.
queue, ok := b.consumerQueues[1]
require.True(t, ok)
require.Len(t, queue, 2)
}
// TestStartDispatcher tests the Start method.
func TestStartDispatcher(t *testing.T) {
t.Parallel()
// Create a mock chain notifier.
mockNotifier := &chainntnfs.MockChainNotifier{}
defer mockNotifier.AssertExpectations(t)
// Create a new dispatcher.
b := NewBlockbeatDispatcher(mockNotifier)
// Start the dispatcher without consumers should return an error.
err := b.Start()
require.Error(t, err)
// Create a consumer and register it.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker1")
b.RegisterQueue([]Consumer{consumer})
// Mock the chain notifier to return an error.
mockNotifier.On("RegisterBlockEpochNtfn",
mock.Anything).Return(nil, errDummy).Once()
// Start the dispatcher now should return the error.
err = b.Start()
require.ErrorIs(t, err, errDummy)
// Mock the chain notifier to return a valid notifier.
blockEpochs := &chainntnfs.BlockEpochEvent{}
mockNotifier.On("RegisterBlockEpochNtfn",
mock.Anything).Return(blockEpochs, nil).Once()
// Start the dispatcher now should not return an error.
err = b.Start()
require.NoError(t, err)
}
// TestDispatchBlocks asserts the blocks are properly dispatched to the queues.
func TestDispatchBlocks(t *testing.T) {
t.Parallel()
// Create a mock chain notifier.
mockNotifier := &chainntnfs.MockChainNotifier{}
defer mockNotifier.AssertExpectations(t)
// Create a new dispatcher.
b := NewBlockbeatDispatcher(mockNotifier)
// Create the beat and attach it to the dispatcher.
epoch := chainntnfs.BlockEpoch{Height: 1}
beat := NewBeat(epoch)
b.beat = beat
// Create a consumer and register it.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker1")
b.RegisterQueue([]Consumer{consumer})
// Mock the consumer to return nil error on ProcessBlock. This
// implicitly asserts that the step `notifyQueues` is successfully
// reached in the `dispatchBlocks` method.
consumer.On("ProcessBlock", mock.Anything).Return(nil).Once()
// Create a test epoch chan.
epochChan := make(chan *chainntnfs.BlockEpoch, 1)
blockEpochs := &chainntnfs.BlockEpochEvent{
Epochs: epochChan,
Cancel: func() {},
}
// Call the method in a goroutine.
done := make(chan struct{})
b.wg.Add(1)
go func() {
defer close(done)
b.dispatchBlocks(blockEpochs)
}()
// Send an epoch.
epoch = chainntnfs.BlockEpoch{Height: 2}
epochChan <- &epoch
// Wait for the dispatcher to process the epoch.
time.Sleep(100 * time.Millisecond)
// Stop the dispatcher.
b.Stop()
// We expect the dispatcher to stop immediately.
_, err := fn.RecvOrTimeout(done, time.Second)
require.NoError(t, err)
}
// TestNotifyQueuesSuccess checks when the dispatcher successfully notifies all
// the queues, no error is returned.
func TestNotifyQueuesSuccess(t *testing.T) {
t.Parallel()
// Create two mock consumers.
consumer1 := &MockConsumer{}
defer consumer1.AssertExpectations(t)
consumer1.On("Name").Return("mocker1")
consumer2 := &MockConsumer{}
defer consumer2.AssertExpectations(t)
consumer2.On("Name").Return("mocker2")
// Create two queues.
queue1 := []Consumer{consumer1}
queue2 := []Consumer{consumer2}
// Create a mock chain notifier.
mockNotifier := &chainntnfs.MockChainNotifier{}
defer mockNotifier.AssertExpectations(t)
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Create a new dispatcher.
b := NewBlockbeatDispatcher(mockNotifier)
// Register the queues.
b.RegisterQueue(queue1)
b.RegisterQueue(queue2)
// Attach the blockbeat.
b.beat = mockBeat
// Mock the consumers to return nil error on ProcessBlock for
// both calls.
consumer1.On("ProcessBlock", mockBeat).Return(nil).Once()
consumer2.On("ProcessBlock", mockBeat).Return(nil).Once()
// Notify the queues. The mockers will be asserted in the end to
// validate the calls.
err := b.notifyQueues()
require.NoError(t, err)
}
// TestNotifyQueuesError checks when one of the queue returns an error, this
// error is returned by the method.
func TestNotifyQueuesError(t *testing.T) {
t.Parallel()
// Create a mock consumer.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker1")
// Create one queue.
queue := []Consumer{consumer}
// Create a mock chain notifier.
mockNotifier := &chainntnfs.MockChainNotifier{}
defer mockNotifier.AssertExpectations(t)
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
// Create a new dispatcher.
b := NewBlockbeatDispatcher(mockNotifier)
// Register the queues.
b.RegisterQueue(queue)
// Attach the blockbeat.
b.beat = mockBeat
// Mock the consumer to return an error on ProcessBlock.
consumer.On("ProcessBlock", mockBeat).Return(errDummy).Once()
// Notify the queues. The mockers will be asserted in the end to
// validate the calls.
err := b.notifyQueues()
require.ErrorIs(t, err, errDummy)
}
// TestCurrentHeight asserts `CurrentHeight` returns the expected block height.
func TestCurrentHeight(t *testing.T) {
t.Parallel()
testHeight := int32(1000)
// Create a mock chain notifier.
mockNotifier := &chainntnfs.MockChainNotifier{}
defer mockNotifier.AssertExpectations(t)
// Create a mock beat.
mockBeat := &MockBlockbeat{}
defer mockBeat.AssertExpectations(t)
mockBeat.On("logger").Return(clog)
mockBeat.On("Height").Return(testHeight).Once()
// Create a mock consumer.
consumer := &MockConsumer{}
defer consumer.AssertExpectations(t)
consumer.On("Name").Return("mocker1")
// Create one queue.
queue := []Consumer{consumer}
// Create a new dispatcher.
b := NewBlockbeatDispatcher(mockNotifier)
// Register the queues.
b.RegisterQueue(queue)
// Attach the blockbeat.
b.beat = mockBeat
// Mock the chain notifier to return a valid notifier.
blockEpochs := &chainntnfs.BlockEpochEvent{
Cancel: func() {},
}
mockNotifier.On("RegisterBlockEpochNtfn",
mock.Anything).Return(blockEpochs, nil).Once()
// Start the dispatcher now should not return an error.
err := b.Start()
require.NoError(t, err)
// Make a query on the current height and assert it equals to
// testHeight.
height := b.CurrentHeight()
require.Equal(t, testHeight, height)
// Stop the dispatcher.
b.Stop()
// Make a query on the current height and assert it equals to 0.
height = b.CurrentHeight()
require.Zero(t, height)
}

View File

@ -1,53 +0,0 @@
package chainio
import "github.com/btcsuite/btclog/v2"
// Blockbeat defines an interface that can be used by subsystems to retrieve
// block data. It is sent by the BlockbeatDispatcher to all the registered
// consumers whenever a new block is received. Once the consumer finishes
// processing the block, it must signal it by calling `NotifyBlockProcessed`.
//
// The blockchain is a state machine - whenever there's a state change, it's
// manifested in a block. The blockbeat is a way to notify subsystems of this
// state change, and to provide them with the data they need to process it. In
// other words, subsystems must react to this state change and should consider
// being driven by the blockbeat in their own state machines.
type Blockbeat interface {
// blockbeat is a private interface that's only used in this package.
blockbeat
// Height returns the current block height.
Height() int32
}
// blockbeat defines a set of private methods used in this package to make
// interaction with the blockbeat easier.
type blockbeat interface {
// logger returns the internal logger used by the blockbeat which has a
// block height prefix.
logger() btclog.Logger
}
// Consumer defines a blockbeat consumer interface. Subsystems that need block
// info must implement it.
type Consumer interface {
// TODO(yy): We should also define the start methods used by the
// consumers such that when implementing the interface, the consumer
// will always be started with a blockbeat. This cannot be enforced at
// the moment as we need refactor all the start methods to only take a
// beat.
//
// Start(beat Blockbeat) error
// Name returns a human-readable string for this subsystem.
Name() string
// ProcessBlock takes a blockbeat and processes it. It should not
// return until the subsystem has updated its state based on the block
// data.
//
// NOTE: The consumer must try its best to NOT return an error. If an
// error is returned from processing the block, it means the subsystem
// cannot react to onchain state changes and lnd will shutdown.
ProcessBlock(b Blockbeat) error
}

View File

@ -1,32 +0,0 @@
package chainio
import (
"github.com/btcsuite/btclog/v2"
"github.com/lightningnetwork/lnd/build"
)
// Subsystem defines the logging code for this subsystem.
const Subsystem = "CHIO"
// clog is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var clog btclog.Logger
// The default amount of logging is none.
func init() {
UseLogger(build.NewSubLogger(Subsystem, nil))
}
// DisableLog disables all library log output. Logging output is disabled by
// default until UseLogger is called.
func DisableLog() {
UseLogger(btclog.Disabled)
}
// UseLogger uses a specified Logger to output package logging info. This
// should be used in preference to SetLogWriter if the caller is also using
// btclog.
func UseLogger(logger btclog.Logger) {
clog = logger
}

View File

@ -1,50 +0,0 @@
package chainio
import (
"github.com/btcsuite/btclog/v2"
"github.com/stretchr/testify/mock"
)
// MockConsumer is a mock implementation of the Consumer interface.
type MockConsumer struct {
mock.Mock
}
// Compile-time constraint to ensure MockConsumer implements Consumer.
var _ Consumer = (*MockConsumer)(nil)
// Name returns a human-readable string for this subsystem.
func (m *MockConsumer) Name() string {
args := m.Called()
return args.String(0)
}
// ProcessBlock takes a blockbeat and processes it. A receive-only error chan
// must be returned.
func (m *MockConsumer) ProcessBlock(b Blockbeat) error {
args := m.Called(b)
return args.Error(0)
}
// MockBlockbeat is a mock implementation of the Blockbeat interface.
type MockBlockbeat struct {
mock.Mock
}
// Compile-time constraint to ensure MockBlockbeat implements Blockbeat.
var _ Blockbeat = (*MockBlockbeat)(nil)
// Height returns the current block height.
func (m *MockBlockbeat) Height() int32 {
args := m.Called()
return args.Get(0).(int32)
}
// logger returns the logger for the blockbeat.
func (m *MockBlockbeat) logger() btclog.Logger {
args := m.Called()
return args.Get(0).(btclog.Logger)
}

View File

@ -15,7 +15,7 @@ import (
"github.com/btcsuite/btcwallet/chain"
"github.com/lightningnetwork/lnd/blockcache"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/queue"
)
@ -139,7 +139,6 @@ func (b *BitcoindNotifier) Stop() error {
// Shutdown the rpc client, this gracefully disconnects from bitcoind,
// and cleans up all related resources.
b.chainConn.Stop()
b.chainConn.WaitForShutdown()
close(b.quit)
b.wg.Wait()
@ -171,8 +170,6 @@ func (b *BitcoindNotifier) Started() bool {
}
func (b *BitcoindNotifier) startNotifier() error {
chainntnfs.Log.Infof("bitcoind notifier starting...")
// Connect to bitcoind, and register for notifications on connected,
// and disconnected blocks.
if err := b.chainConn.Start(); err != nil {
@ -209,8 +206,6 @@ func (b *BitcoindNotifier) startNotifier() error {
// startup.
atomic.StoreInt32(&b.active, 1)
chainntnfs.Log.Debugf("bitcoind notifier started")
return nil
}
@ -260,7 +255,7 @@ out:
// TODO(wilmer): add retry logic if rescan fails?
b.wg.Add(1)
//nolint:ll
//nolint:lll
go func(msg *chainntnfs.HistoricalConfDispatch) {
defer b.wg.Done()
@ -305,7 +300,7 @@ out:
// TODO(wilmer): add retry logic if rescan fails?
b.wg.Add(1)
//nolint:ll
//nolint:lll
go func(msg *chainntnfs.HistoricalSpendDispatch) {
defer b.wg.Done()
@ -495,7 +490,7 @@ out:
func (b *BitcoindNotifier) handleRelevantTx(tx *btcutil.Tx,
mempool bool, height uint32) {
// If this is a mempool spend, we'll ask the mempool notifier to handle
// If this is a mempool spend, we'll ask the mempool notifier to hanlde
// it.
if mempool {
err := b.memNotifier.ProcessRelevantSpendTx(tx)
@ -669,14 +664,8 @@ func (b *BitcoindNotifier) handleBlockConnected(block chainntnfs.BlockEpoch) err
// satisfy any client requests based upon the new block.
b.bestBlock = block
err = b.txNotifier.NotifyHeight(uint32(block.Height))
if err != nil {
return fmt.Errorf("unable to notify height: %w", err)
}
b.notifyBlockEpochs(block.Height, block.Hash, block.BlockHeader)
return nil
return b.txNotifier.NotifyHeight(uint32(block.Height))
}
// notifyBlockEpochs notifies all registered block epoch clients of the newly
@ -833,16 +822,8 @@ func (b *BitcoindNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
return nil, err
}
spentHeight := uint32(blockHeight)
chainntnfs.Log.Debugf("Outpoint(%v) has spent at height %v",
outpoint, spentHeight)
// Since the tx has already been spent at spentHeight, the
// heightHint specified by the caller is no longer relevant. We
// now update the starting height to be the spent height to make
// sure we won't miss it in the rescan.
if spentHeight != ntfn.HistoricalDispatch.StartHeight {
ntfn.HistoricalDispatch.StartHeight = spentHeight
if uint32(blockHeight) > ntfn.HistoricalDispatch.StartHeight {
ntfn.HistoricalDispatch.StartHeight = uint32(blockHeight)
}
}

View File

@ -11,7 +11,6 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/integration/rpctest"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcwallet/chain"
"github.com/lightningnetwork/lnd/blockcache"
"github.com/lightningnetwork/lnd/chainntnfs"
@ -38,7 +37,11 @@ var (
func initHintCache(t *testing.T) *channeldb.HeightHintCache {
t.Helper()
db := channeldb.OpenForTesting(t, t.TempDir())
db, err := channeldb.Open(t.TempDir())
require.NoError(t, err, "unable to create db")
t.Cleanup(func() {
require.NoError(t, db.Close())
})
testCfg := channeldb.CacheConfig{
QueryDisable: false,
@ -104,69 +107,17 @@ func syncNotifierWithMiner(t *testing.T, notifier *BitcoindNotifier,
"err=%v, minerHeight=%v, bitcoindHeight=%v",
err, minerHeight, bitcoindHeight)
}
// Get the num of connections the miner has. We expect it to
// have at least one connection with the chain backend.
count, err := miner.Client.GetConnectionCount()
require.NoError(t, err)
if count != 0 {
continue
}
// Reconnect the miner and the chain backend.
//
// NOTE: The connection should have been made before we perform
// the `syncNotifierWithMiner`. However, due to an unknown
// reason, the miner may refuse to process the inbound
// connection made by the bitcoind node, causing the connection
// to fail. It's possible there's a bug in the handshake between
// the two nodes.
//
// A normal flow is, bitcoind starts a v2 handshake flow, which
// btcd will fail and disconnect. Upon seeing this
// disconnection, bitcoind will try a v1 handshake and succeeds.
// The failed flow is, upon seeing the v2 handshake, btcd
// doesn't seem to perform the disconnect. Instead an EOF
// websocket error is found.
//
// TODO(yy): Fix the above bug in `btcd`. This can be reproduced
// using `make flakehunter-unit pkg=$pkg case=$case`, with,
// `case=TestHistoricalConfDetailsNoTxIndex/rpc_polling_enabled`
// `pkg=chainntnfs/bitcoindnotify`.
// Also need to modify the temp dir logic so we can save the
// debug logs.
// This bug is likely to be fixed when we implement the
// encrypted p2p conn, or when we properly fix the shutdown
// issues in all our RPC conns.
t.Log("Expected to the chain backend to have one conn with " +
"the miner, instead it's disconnected!")
// We now ask the miner to add the chain backend back.
host := fmt.Sprintf(
"127.0.0.1:%s", notifier.chainParams.DefaultPort,
)
// NOTE:AddNode must take a host that has the format
// `host:port`, otherwise the default port will be used. Check
// `normalizeAddress` in btcd for details.
err = miner.Client.AddNode(host, rpcclient.ANAdd)
require.NoError(t, err, "Failed to connect miner to the chain "+
"backend")
}
}
// TestHistoricalConfDetailsTxIndex ensures that we correctly retrieve
// historical confirmation details using the backend node's txindex.
func TestHistoricalConfDetailsTxIndex(t *testing.T) {
success := t.Run("rpc polling enabled", func(st *testing.T) {
t.Run("rpc polling enabled", func(st *testing.T) {
st.Parallel()
testHistoricalConfDetailsTxIndex(st, true)
})
if !success {
return
}
t.Run("rpc polling disabled", func(st *testing.T) {
st.Parallel()
testHistoricalConfDetailsTxIndex(st, false)
@ -179,7 +130,7 @@ func testHistoricalConfDetailsTxIndex(t *testing.T, rpcPolling bool) {
)
bitcoindConn := unittest.NewBitcoindBackend(
t, unittest.NetParams, miner, true, rpcPolling,
t, unittest.NetParams, miner.P2PAddress(), true, rpcPolling,
)
hintCache := initHintCache(t)
@ -189,6 +140,8 @@ func testHistoricalConfDetailsTxIndex(t *testing.T, rpcPolling bool) {
t, bitcoindConn, hintCache, hintCache, blockCache,
)
syncNotifierWithMiner(t, notifier, miner)
// A transaction unknown to the node should not be found within the
// txindex even if it is enabled, so we should not proceed with any
// fallback methods.
@ -258,15 +211,11 @@ func testHistoricalConfDetailsTxIndex(t *testing.T, rpcPolling bool) {
// historical confirmation details using the set of fallback methods when the
// backend node's txindex is disabled.
func TestHistoricalConfDetailsNoTxIndex(t *testing.T) {
success := t.Run("rpc polling enabled", func(st *testing.T) {
t.Run("rpc polling enabled", func(st *testing.T) {
st.Parallel()
testHistoricalConfDetailsNoTxIndex(st, true)
})
if !success {
return
}
t.Run("rpc polling disabled", func(st *testing.T) {
st.Parallel()
testHistoricalConfDetailsNoTxIndex(st, false)
@ -277,15 +226,13 @@ func testHistoricalConfDetailsNoTxIndex(t *testing.T, rpcpolling bool) {
miner := unittest.NewMiner(t, unittest.NetParams, nil, true, 25)
bitcoindConn := unittest.NewBitcoindBackend(
t, unittest.NetParams, miner, false, rpcpolling,
t, unittest.NetParams, miner.P2PAddress(), false, rpcpolling,
)
hintCache := initHintCache(t)
blockCache := blockcache.NewBlockCache(10000)
notifier := setUpNotifier(
t, bitcoindConn, hintCache, hintCache, blockCache,
)
notifier := setUpNotifier(t, bitcoindConn, hintCache, hintCache, blockCache)
// Since the node has its txindex disabled, we fall back to scanning the
// chain manually. A transaction unknown to the network should not be
@ -294,11 +241,7 @@ func testHistoricalConfDetailsNoTxIndex(t *testing.T, rpcpolling bool) {
copy(unknownHash[:], bytes.Repeat([]byte{0x10}, 32))
unknownConfReq, err := chainntnfs.NewConfRequest(&unknownHash, testScript)
require.NoError(t, err, "unable to create conf request")
// Get the current best height.
_, broadcastHeight, err := miner.Client.GetBestBlock()
require.NoError(t, err, "unable to retrieve miner's current height")
broadcastHeight := syncNotifierWithMiner(t, notifier, miner)
_, txStatus, err := notifier.historicalConfDetails(
unknownConfReq, uint32(broadcastHeight), uint32(broadcastHeight),
)

View File

@ -17,7 +17,7 @@ import (
"github.com/btcsuite/btcwallet/chain"
"github.com/lightningnetwork/lnd/blockcache"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/queue"
)
@ -129,6 +129,11 @@ func New(config *rpcclient.ConnConfig, chainParams *chaincfg.Params,
quit: make(chan struct{}),
}
// Disable connecting to btcd within the rpcclient.New method. We
// defer establishing the connection to our .Start() method.
config.DisableConnectOnNew = true
config.DisableAutoReconnect = false
ntfnCallbacks := &rpcclient.NotificationHandlers{
OnBlockConnected: notifier.onBlockConnected,
OnBlockDisconnected: notifier.onBlockDisconnected,
@ -180,7 +185,7 @@ func (b *BtcdNotifier) Stop() error {
// Shutdown the rpc client, this gracefully disconnects from btcd, and
// cleans up all related resources.
b.chainConn.Stop()
b.chainConn.Shutdown()
close(b.quit)
b.wg.Wait()
@ -204,11 +209,7 @@ func (b *BtcdNotifier) Stop() error {
return nil
}
// startNotifier is the main starting point for the BtcdNotifier. It connects
// to btcd and start the main dispatcher goroutine.
func (b *BtcdNotifier) startNotifier() error {
chainntnfs.Log.Infof("btcd notifier starting...")
// Start our concurrent queues before starting the chain connection, to
// ensure onBlockConnected and onRedeemingTx callbacks won't be
// blocked.
@ -223,17 +224,6 @@ func (b *BtcdNotifier) startNotifier() error {
return err
}
// Before we fetch the best block/block height we need to register the
// notifications for connected blocks, otherwise we might think we are
// at an earlier block height because during block notification
// registration we might have already mined some new blocks. Hence we
// will not get notified accordingly.
if err := b.chainConn.NotifyBlocks(); err != nil {
b.txUpdates.Stop()
b.chainUpdates.Stop()
return err
}
currentHash, currentHeight, err := b.chainConn.GetBestBlock()
if err != nil {
b.txUpdates.Stop()
@ -259,6 +249,12 @@ func (b *BtcdNotifier) startNotifier() error {
BlockHeader: &bestBlock.Header,
}
if err := b.chainConn.NotifyBlocks(); err != nil {
b.txUpdates.Stop()
b.chainUpdates.Stop()
return err
}
b.wg.Add(1)
go b.notificationDispatcher()
@ -266,8 +262,6 @@ func (b *BtcdNotifier) startNotifier() error {
// startup.
atomic.StoreInt32(&b.active, 1)
chainntnfs.Log.Debugf("btcd notifier started")
return nil
}
@ -377,7 +371,7 @@ out:
// TODO(wilmer): add retry logic if rescan fails?
b.wg.Add(1)
//nolint:ll
//nolint:lll
go func(msg *chainntnfs.HistoricalConfDispatch) {
defer b.wg.Done()
@ -550,7 +544,7 @@ out:
func (b *BtcdNotifier) handleRelevantTx(tx *btcutil.Tx,
mempool bool, height uint32) {
// If this is a mempool spend, we'll ask the mempool notifier to handle
// If this is a mempool spend, we'll ask the mempool notifier to hanlde
// it.
if mempool {
err := b.memNotifier.ProcessRelevantSpendTx(tx)
@ -736,16 +730,11 @@ func (b *BtcdNotifier) handleBlockConnected(epoch chainntnfs.BlockEpoch) error {
// satisfy any client requests based upon the new block.
b.bestBlock = epoch
err = b.txNotifier.NotifyHeight(uint32(epoch.Height))
if err != nil {
return fmt.Errorf("unable to notify height: %w", err)
}
b.notifyBlockEpochs(
epoch.Height, epoch.Hash, epoch.BlockHeader,
)
return nil
return b.txNotifier.NotifyHeight(uint32(epoch.Height))
}
// notifyBlockEpochs notifies all registered block epoch clients of the newly
@ -933,25 +922,15 @@ func (b *BtcdNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint,
"block %v: %v", blockHash, err)
}
spentHeight := uint32(blockHeader.Height)
chainntnfs.Log.Debugf("Outpoint(%v) has spent at height %v",
outpoint, spentHeight)
// Since the tx has already been spent at spentHeight, the
// heightHint specified by the caller is no longer relevant. We
// now update the starting height to be the spent height to make
// sure we won't miss it in the rescan.
if spentHeight != ntfn.HistoricalDispatch.StartHeight {
if uint32(blockHeader.Height) > ntfn.HistoricalDispatch.StartHeight {
startHash, err = b.chainConn.GetBlockHash(
int64(spentHeight),
int64(blockHeader.Height),
)
if err != nil {
return nil, fmt.Errorf("unable to get block "+
"hash for height %d: %v",
blockHeader.Height, err)
}
ntfn.HistoricalDispatch.StartHeight = spentHeight
}
}

View File

@ -33,7 +33,11 @@ var (
func initHintCache(t *testing.T) *channeldb.HeightHintCache {
t.Helper()
db := channeldb.OpenForTesting(t, t.TempDir())
db, err := channeldb.Open(t.TempDir())
require.NoError(t, err, "unable to create db")
t.Cleanup(func() {
require.NoError(t, db.Close())
})
testCfg := channeldb.CacheConfig{
QueryDisable: false,

View File

@ -13,7 +13,7 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/fn"
)
var (
@ -70,28 +70,28 @@ func (t TxConfStatus) String() string {
}
}
// NotifierOptions is a set of functional options that allow callers to further
// notifierOptions is a set of functional options that allow callers to further
// modify the type of chain event notifications they receive.
type NotifierOptions struct {
// IncludeBlock if true, then the dispatched confirmation notification
type notifierOptions struct {
// includeBlock if true, then the dispatched confirmation notification
// will include the block that mined the transaction.
IncludeBlock bool
includeBlock bool
}
// DefaultNotifierOptions returns the set of default options for the notifier.
func DefaultNotifierOptions() *NotifierOptions {
return &NotifierOptions{}
// defaultNotifierOptions returns the set of default options for the notifier.
func defaultNotifierOptions() *notifierOptions {
return &notifierOptions{}
}
// NotifierOption is a functional option that allows a caller to modify the
// events received from the notifier.
type NotifierOption func(*NotifierOptions)
type NotifierOption func(*notifierOptions)
// WithIncludeBlock is an optional argument that allows the caller to specify
// WithIncludeBlock is an optional argument that allows the calelr to specify
// that the block that mined a transaction should be included in the response.
func WithIncludeBlock() NotifierOption {
return func(o *NotifierOptions) {
o.IncludeBlock = true
return func(o *notifierOptions) {
o.includeBlock = true
}
}
@ -258,9 +258,6 @@ type ConfirmationEvent struct {
// channels.
func NewConfirmationEvent(numConfs uint32, cancel func()) *ConfirmationEvent {
return &ConfirmationEvent{
// We cannot rely on the subscriber to immediately read from
// the channel so we need to create a larger buffer to avoid
// blocking the notifier.
Confirmed: make(chan *TxConfirmation, 1),
Updates: make(chan uint32, numConfs),
NegativeConf: make(chan int32, 1),

View File

@ -1,7 +1,7 @@
package chainntnfs
import (
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

View File

@ -211,7 +211,7 @@ func (m *MempoolNotifier) findRelevantInputs(tx *btcutil.Tx) (inputsWithTx,
// If found, save it to watchedInputs to notify the
// subscriber later.
Log.Debugf("Found input %s, spent in %s", op, txid)
Log.Infof("Found input %s, spent in %s", op, txid)
// Construct the spend details.
details := &SpendDetail{

View File

@ -3,7 +3,7 @@ package chainntnfs
import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/fn"
"github.com/stretchr/testify/mock"
)

View File

@ -168,8 +168,6 @@ func (n *NeutrinoNotifier) Started() bool {
}
func (n *NeutrinoNotifier) startNotifier() error {
chainntnfs.Log.Infof("neutrino notifier starting...")
// Start our concurrent queues before starting the rescan, to ensure
// onFilteredBlockConnected and onRelavantTx callbacks won't be
// blocked.
@ -236,8 +234,6 @@ func (n *NeutrinoNotifier) startNotifier() error {
// startup.
atomic.StoreInt32(&n.active, 1)
chainntnfs.Log.Debugf("neutrino notifier started")
return nil
}
@ -443,7 +439,7 @@ func (n *NeutrinoNotifier) notificationDispatcher() {
// potentially long rescans.
n.wg.Add(1)
//nolint:ll
//nolint:lll
go func(msg *chainntnfs.HistoricalConfDispatch) {
defer n.wg.Done()
@ -693,16 +689,10 @@ func (n *NeutrinoNotifier) handleBlockConnected(newBlock *filteredBlock) error {
n.bestBlock.Height = int32(newBlock.height)
n.bestBlock.BlockHeader = newBlock.header
err = n.txNotifier.NotifyHeight(newBlock.height)
if err != nil {
return fmt.Errorf("unable to notify height: %w", err)
}
n.notifyBlockEpochs(
int32(newBlock.height), &newBlock.hash, newBlock.header,
)
return nil
return n.txNotifier.NotifyHeight(newBlock.height)
}
// getFilteredBlock is a utility to retrieve the full filtered block from a block epoch.

View File

@ -12,15 +12,11 @@ import (
// TestInterfaces executes the generic notifier test suite against a bitcoind
// powered chain notifier.
func TestInterfaces(t *testing.T) {
success := t.Run("bitcoind", func(st *testing.T) {
t.Run("bitcoind", func(st *testing.T) {
st.Parallel()
chainntnfstest.TestInterfaces(st, "bitcoind")
})
if !success {
return
}
t.Run("bitcoind rpc polling", func(st *testing.T) {
st.Parallel()
chainntnfstest.TestInterfaces(st, "bitcoind-rpc-polling")

View File

@ -41,8 +41,9 @@ func testSingleConfirmationNotification(miner *rpctest.Harness,
// function.
txid, pkScript, err := chainntnfs.GetTestTxidAndScript(miner)
require.NoError(t, err, "unable to create test tx")
err = chainntnfs.WaitForMempoolTx(miner, txid)
require.NoError(t, err, "tx not relayed to miner")
if err := chainntnfs.WaitForMempoolTx(miner, txid); err != nil {
t.Fatalf("tx not relayed to miner: %v", err)
}
_, currentHeight, err := miner.Client.GetBestBlock()
require.NoError(t, err, "unable to get current height")
@ -67,11 +68,6 @@ func testSingleConfirmationNotification(miner *rpctest.Harness,
blockHash, err := miner.Client.Generate(1)
require.NoError(t, err, "unable to generate single block")
// Assert the above tx is mined in the block.
block, err := miner.Client.GetBlock(blockHash[0])
require.NoError(t, err)
require.Len(t, block.Transactions, 2, "block does not contain tx")
select {
case confInfo := <-confIntent.Confirmed:
if !confInfo.BlockHash.IsEqual(blockHash[0]) {
@ -1910,8 +1906,10 @@ func TestInterfaces(t *testing.T, targetBackEnd string) {
// Initialize a height hint cache for each notifier.
tempDir := t.TempDir()
db := channeldb.OpenForTesting(t, tempDir)
db, err := channeldb.Open(tempDir)
if err != nil {
t.Fatalf("unable to create db: %v", err)
}
testCfg := channeldb.CacheConfig{
QueryDisable: false,
}
@ -1932,7 +1930,7 @@ func TestInterfaces(t *testing.T, targetBackEnd string) {
case "bitcoind":
var bitcoindConn *chain.BitcoindConn
bitcoindConn = unittest.NewBitcoindBackend(
t, unittest.NetParams, miner, true, false,
t, unittest.NetParams, p2pAddr, true, false,
)
newNotifier = func() (chainntnfs.TestChainNotifier, error) {
return bitcoindnotify.New(
@ -1944,7 +1942,7 @@ func TestInterfaces(t *testing.T, targetBackEnd string) {
case "bitcoind-rpc-polling":
var bitcoindConn *chain.BitcoindConn
bitcoindConn = unittest.NewBitcoindBackend(
t, unittest.NetParams, miner, true, true,
t, unittest.NetParams, p2pAddr, true, true,
)
newNotifier = func() (chainntnfs.TestChainNotifier, error) {
return bitcoindnotify.New(

View File

@ -244,25 +244,20 @@ type ConfNtfn struct {
// notification is to be sent.
NumConfirmations uint32
// Event contains references to the channels that the notifications are
// to be sent over.
// Event contains references to the channels that the notifications are to
// be sent over.
Event *ConfirmationEvent
// HeightHint is the minimum height in the chain that we expect to find
// this txid.
HeightHint uint32
// dispatched is false if the confirmed notification has not been sent
// yet.
// dispatched is false if the confirmed notification has not been sent yet.
dispatched bool
// includeBlock is true if the dispatched notification should also have
// the block included with it.
includeBlock bool
// numConfsLeft is the number of confirmations left to be sent to the
// subscriber.
numConfsLeft uint32
}
// HistoricalConfDispatch parametrizes a manual rescan for a particular
@ -559,7 +554,7 @@ func NewTxNotifier(startHeight uint32, reorgSafetyLimit uint32,
// and register a confirmation notification.
func (n *TxNotifier) newConfNtfn(txid *chainhash.Hash,
pkScript []byte, numConfs, heightHint uint32,
opts *NotifierOptions) (*ConfNtfn, error) {
opts *notifierOptions) (*ConfNtfn, error) {
// An accompanying output script must always be provided.
if len(pkScript) == 0 {
@ -593,8 +588,7 @@ func (n *TxNotifier) newConfNtfn(txid *chainhash.Hash,
n.CancelConf(confRequest, confID)
}),
HeightHint: heightHint,
includeBlock: opts.IncludeBlock,
numConfsLeft: numConfs,
includeBlock: opts.includeBlock,
}, nil
}
@ -616,7 +610,7 @@ func (n *TxNotifier) RegisterConf(txid *chainhash.Hash, pkScript []byte,
default:
}
opts := DefaultNotifierOptions()
opts := defaultNotifierOptions()
for _, optFunc := range optFuncs {
optFunc(opts)
}
@ -670,8 +664,8 @@ func (n *TxNotifier) RegisterConf(txid *chainhash.Hash, pkScript []byte,
// already been found, we'll attempt to deliver them immediately
// to this client.
Log.Debugf("Attempting to dispatch confirmation for %v on "+
"registration since rescan has finished, conf_id=%v",
ntfn.ConfRequest, ntfn.ConfID)
"registration since rescan has finished",
ntfn.ConfRequest)
// The default notification we assigned above includes the
// block along with the rest of the details. However not all
@ -685,13 +679,9 @@ func (n *TxNotifier) RegisterConf(txid *chainhash.Hash, pkScript []byte,
confDetails = &confDetailsCopy
}
// Deliver the details to the whole conf set where this ntfn
// lives in.
for _, subscriber := range confSet.ntfns {
err := n.dispatchConfDetails(subscriber, confDetails)
if err != nil {
return nil, err
}
err := n.dispatchConfDetails(ntfn, confDetails)
if err != nil {
return nil, err
}
return &ConfRegistration{
@ -922,16 +912,10 @@ func (n *TxNotifier) dispatchConfDetails(
// If there are no conf details to dispatch or if the notification has
// already been dispatched, then we can skip dispatching to this
// client.
if details == nil {
Log.Debugf("Skipped dispatching nil conf details for request "+
"%v, conf_id=%v", ntfn.ConfRequest, ntfn.ConfID)
return nil
}
if ntfn.dispatched {
Log.Debugf("Skipped dispatched conf details for request %v "+
"conf_id=%v", ntfn.ConfRequest, ntfn.ConfID)
if details == nil || ntfn.dispatched {
Log.Debugf("Skipping dispatch of conf details(%v) for "+
"request %v, dispatched=%v", details, ntfn.ConfRequest,
ntfn.dispatched)
return nil
}
@ -941,16 +925,16 @@ func (n *TxNotifier) dispatchConfDetails(
// we'll dispatch a confirmation notification to the caller.
confHeight := details.BlockHeight + ntfn.NumConfirmations - 1
if confHeight <= n.currentHeight {
Log.Debugf("Dispatching %v confirmation notification for "+
"conf_id=%v, %v", ntfn.NumConfirmations, ntfn.ConfID,
ntfn.ConfRequest)
Log.Debugf("Dispatching %v confirmation notification for %v",
ntfn.NumConfirmations, ntfn.ConfRequest)
// We'll send a 0 value to the Updates channel,
// indicating that the transaction/output script has already
// been confirmed.
err := n.notifyNumConfsLeft(ntfn, 0)
if err != nil {
return err
select {
case ntfn.Event.Updates <- 0:
case <-n.quit:
return ErrTxNotifierExiting
}
select {
@ -960,8 +944,8 @@ func (n *TxNotifier) dispatchConfDetails(
return ErrTxNotifierExiting
}
} else {
Log.Debugf("Queueing %v confirmation notification for %v at "+
"tip", ntfn.NumConfirmations, ntfn.ConfRequest)
Log.Debugf("Queueing %v confirmation notification for %v at tip ",
ntfn.NumConfirmations, ntfn.ConfRequest)
// Otherwise, we'll keep track of the notification
// request by the height at which we should dispatch the
@ -977,9 +961,10 @@ func (n *TxNotifier) dispatchConfDetails(
// confirmations are left for the transaction/output script to
// be confirmed.
numConfsLeft := confHeight - n.currentHeight
err := n.notifyNumConfsLeft(ntfn, numConfsLeft)
if err != nil {
return err
select {
case ntfn.Event.Updates <- numConfsLeft:
case <-n.quit:
return ErrTxNotifierExiting
}
}
@ -1744,9 +1729,10 @@ func (n *TxNotifier) NotifyHeight(height uint32) error {
continue
}
err := n.notifyNumConfsLeft(ntfn, numConfsLeft)
if err != nil {
return err
select {
case ntfn.Event.Updates <- numConfsLeft:
case <-n.quit:
return ErrTxNotifierExiting
}
}
}
@ -1757,6 +1743,9 @@ func (n *TxNotifier) NotifyHeight(height uint32) error {
for ntfn := range n.ntfnsByConfirmHeight[height] {
confSet := n.confNotifications[ntfn.ConfRequest]
Log.Debugf("Dispatching %v confirmation notification for %v",
ntfn.NumConfirmations, ntfn.ConfRequest)
// The default notification we assigned above includes the
// block along with the rest of the details. However not all
// clients want the block, so we make a copy here w/o the block
@ -1766,20 +1755,6 @@ func (n *TxNotifier) NotifyHeight(height uint32) error {
confDetails.Block = nil
}
// If the `confDetails` has already been sent before, we'll
// skip it and continue processing the next one.
if ntfn.dispatched {
Log.Debugf("Skipped dispatched conf details for "+
"request %v conf_id=%v", ntfn.ConfRequest,
ntfn.ConfID)
continue
}
Log.Debugf("Dispatching %v confirmation notification for "+
"conf_id=%v, %v", ntfn.NumConfirmations, ntfn.ConfID,
ntfn.ConfRequest)
select {
case ntfn.Event.Confirmed <- &confDetails:
ntfn.dispatched = true
@ -1858,9 +1833,6 @@ func (n *TxNotifier) DisconnectTip(blockHeight uint32) error {
default:
}
// We also reset the num of confs update.
ntfn.numConfsLeft = ntfn.NumConfirmations
// Then, we'll check if the current
// transaction/output script was included in the
// block currently being disconnected. If it
@ -2097,30 +2069,3 @@ func (n *TxNotifier) TearDown() {
}
}
}
// notifyNumConfsLeft sends the number of confirmations left to the
// notification subscriber through the Event.Updates channel.
//
// NOTE: must be used with the TxNotifier's lock held.
func (n *TxNotifier) notifyNumConfsLeft(ntfn *ConfNtfn, num uint32) error {
// If the number left is no less than the recorded value, we can skip
// sending it as it means this same value has already been sent before.
if num >= ntfn.numConfsLeft {
Log.Debugf("Skipped dispatched update (numConfsLeft=%v) for "+
"request %v conf_id=%v", num, ntfn.ConfRequest,
ntfn.ConfID)
return nil
}
// Update the number of confirmations left to the notification.
ntfn.numConfsLeft = num
select {
case ntfn.Event.Updates <- num:
case <-n.quit:
return ErrTxNotifierExiting
}
return nil
}

View File

@ -173,7 +173,7 @@ func TestTxNotifierRegistrationValidation(t *testing.T) {
for _, testCase := range testCases {
testCase := testCase
success := t.Run(testCase.name, func(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
hintCache := newMockHintCache()
n := chainntnfs.NewTxNotifier(
10, chainntnfs.ReorgSafetyLimit, hintCache, hintCache,
@ -201,10 +201,6 @@ func TestTxNotifierRegistrationValidation(t *testing.T) {
"\"%v\", got \"%v\"", testCase.err, err)
}
})
if !success {
return
}
}
}

View File

@ -22,14 +22,6 @@ var BitcoinTestNetParams = BitcoinNetParams{
CoinType: keychain.CoinTypeTestnet,
}
// BitcoinTestNet4Params contains parameters specific to the 4th version of the
// test network.
var BitcoinTestNet4Params = BitcoinNetParams{
Params: &bitcoinCfg.TestNet4Params,
RPCPort: "48334",
CoinType: keychain.CoinTypeTestnet,
}
// BitcoinMainNetParams contains parameters specific to the current Bitcoin
// mainnet.
var BitcoinMainNetParams = BitcoinNetParams{
@ -61,9 +53,8 @@ var BitcoinRegTestNetParams = BitcoinNetParams{
CoinType: keychain.CoinTypeTestnet,
}
// IsTestnet tests if the given params correspond to a testnet parameter
// configuration.
// IsTestnet tests if the givern params correspond to a testnet
// parameter configuration.
func IsTestnet(params *BitcoinNetParams) bool {
return params.Params.Net == bitcoinWire.TestNet3 ||
params.Params.Net == bitcoinWire.TestNet4
return params.Params.Net == bitcoinWire.TestNet3
}

View File

@ -23,8 +23,8 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
"github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/kvdb"
@ -222,7 +222,7 @@ type ChainControl struct {
// the parts that can be purely constructed from the passed in global
// configuration and doesn't need any wallet instance yet.
//
//nolint:ll
//nolint:lll
func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
cc := &PartialChainControl{
Cfg: cfg,
@ -385,7 +385,8 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
)
cc.ChainSource = bitcoindConn.NewBitcoindClient()
// Initialize config to connect to bitcoind RPC.
// If we're not in regtest mode, then we'll attempt to use a
// proper fee estimator for testnet.
rpcConfig := &rpcclient.ConnConfig{
Host: bitcoindHost,
User: bitcoindMode.RPCUser,
@ -395,9 +396,7 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
DisableTLS: true,
HTTPPostMode: true,
}
// If feeurl is not provided, use bitcoind's fee estimator.
if cfg.Fee.URL == "" {
if !cfg.Bitcoin.RegTest {
log.Infof("Initializing bitcoind backed fee estimator "+
"in %s mode", bitcoindMode.EstimateMode)
@ -661,8 +660,9 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
return checkOutboundPeers(chainRPC.Client)
}
// If feeurl is not provided, use btcd's fee estimator.
if cfg.Fee.URL == "" {
// If we're not in simnet or regtest mode, then we'll attempt
// to use a proper fee estimator for testnet.
if !cfg.Bitcoin.SimNet && !cfg.Bitcoin.RegTest {
log.Info("Initializing btcd backed fee estimator")
// Finally, we'll re-initialize the fee estimator, as
@ -838,15 +838,6 @@ var (
0x01, 0xea, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00,
})
// BitcoinTestnet4Genesis is the genesis hash of Bitcoin's testnet4
// chain.
BitcoinTestnet4Genesis = chainhash.Hash([chainhash.HashSize]byte{
0x43, 0xf0, 0x8b, 0xda, 0xb0, 0x50, 0xe3, 0x5b,
0x56, 0x7c, 0x86, 0x4b, 0x91, 0xf4, 0x7f, 0x50,
0xae, 0x72, 0x5a, 0xe2, 0xde, 0x53, 0xbc, 0xfb,
0xba, 0xf2, 0x84, 0xda, 0x00, 0x00, 0x00, 0x00,
})
// BitcoinSignetGenesis is the genesis hash of Bitcoin's signet chain.
BitcoinSignetGenesis = chainhash.Hash([chainhash.HashSize]byte{
0xf6, 0x1e, 0xee, 0x3b, 0x63, 0xa3, 0x80, 0xa4,
@ -878,8 +869,8 @@ var (
ChainDNSSeeds = map[chainhash.Hash][][2]string{
BitcoinMainnetGenesis: {
{
"nodes.lightning.wiki",
"soa.nodes.lightning.wiki",
"nodes.lightning.directory",
"soa.nodes.lightning.directory",
},
{
"lseed.bitcoinstats.com",
@ -888,22 +879,14 @@ var (
BitcoinTestnetGenesis: {
{
"test.nodes.lightning.wiki",
"soa.nodes.lightning.wiki",
},
},
BitcoinTestnet4Genesis: {
{
"test4.nodes.lightning.wiki",
"soa.nodes.lightning.wiki",
"test.nodes.lightning.directory",
"soa.nodes.lightning.directory",
},
},
BitcoinSignetGenesis: {
{
"signet.nodes.lightning.wiki",
"soa.nodes.lightning.wiki",
"ln.signet.secp.tech",
},
},
}

View File

@ -1,7 +1,7 @@
package chainreg
import (
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

View File

@ -11,7 +11,7 @@ import (
"github.com/btcsuite/btcwallet/chain"
"github.com/btcsuite/btcwallet/waddrmgr"
"github.com/lightningnetwork/lnd/chainntnfs"
graphdb "github.com/lightningnetwork/lnd/graph/db"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/routing/chainview"
)
@ -94,7 +94,7 @@ func (n *NoChainBackend) DisconnectedBlocks() <-chan *chainview.FilteredBlock {
return make(chan *chainview.FilteredBlock)
}
func (n *NoChainBackend) UpdateFilter([]graphdb.EdgePoint, uint32) error {
func (n *NoChainBackend) UpdateFilter([]channeldb.EdgePoint, uint32) error {
return nil
}

View File

@ -1,7 +1,7 @@
package chanacceptor
import (
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

View File

@ -249,7 +249,7 @@ func (r *RPCAcceptor) sendAcceptRequests(errChan chan error,
acceptRequests := make(map[[32]byte]*chanAcceptInfo)
for {
//nolint:ll
//nolint:lll
select {
// Consume requests passed to us from our Accept() function and
// send them into our stream.

View File

@ -2,10 +2,12 @@ package chanbackup
import (
"fmt"
"net"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/kvdb"
)
// LiveChannelSource is an interface that allows us to query for the set of
@ -17,14 +19,23 @@ type LiveChannelSource interface {
// FetchChannel attempts to locate a live channel identified by the
// passed chanPoint. Optionally an existing db tx can be supplied.
FetchChannel(chanPoint wire.OutPoint) (*channeldb.OpenChannel, error)
FetchChannel(tx kvdb.RTx, chanPoint wire.OutPoint) (
*channeldb.OpenChannel, error)
}
// AddressSource is an interface that allows us to query for the set of
// addresses a node can be connected to.
type AddressSource interface {
// AddrsForNode returns all known addresses for the target node public
// key.
AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error)
}
// assembleChanBackup attempts to assemble a static channel backup for the
// passed open channel. The backup includes all information required to restore
// the channel, as well as addressing information so we can find the peer and
// reconnect to them to initiate the protocol.
func assembleChanBackup(addrSource channeldb.AddrSource,
func assembleChanBackup(addrSource AddressSource,
openChan *channeldb.OpenChannel) (*Single, error) {
log.Debugf("Crafting backup for ChannelPoint(%v)",
@ -32,70 +43,25 @@ func assembleChanBackup(addrSource channeldb.AddrSource,
// First, we'll query the channel source to obtain all the addresses
// that are associated with the peer for this channel.
known, nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
nodeAddrs, err := addrSource.AddrsForNode(openChan.IdentityPub)
if err != nil {
return nil, err
}
if !known {
return nil, fmt.Errorf("node unknown by address source")
}
single := NewSingle(openChan, nodeAddrs)
return &single, nil
}
// buildCloseTxInputs generates inputs needed to force close a channel from
// an open channel. Anyone having these inputs and the signer, can sign the
// force closure transaction. Warning! If the channel state updates, an attempt
// to close the channel using this method with outdated CloseTxInputs can result
// in loss of funds! This may happen if an outdated channel backup is attempted
// to be used to force close the channel.
func buildCloseTxInputs(
targetChan *channeldb.OpenChannel) fn.Option[CloseTxInputs] {
log.Debugf("Crafting CloseTxInputs for ChannelPoint(%v)",
targetChan.FundingOutpoint)
localCommit := targetChan.LocalCommitment
if localCommit.CommitTx == nil {
log.Infof("CommitTx is nil for ChannelPoint(%v), "+
"skipping CloseTxInputs. This is possible when "+
"DLP is active.", targetChan.FundingOutpoint)
return fn.None[CloseTxInputs]()
}
// We need unsigned force close tx and the counterparty's signature.
inputs := CloseTxInputs{
CommitTx: localCommit.CommitTx,
CommitSig: localCommit.CommitSig,
}
// In case of a taproot channel, commit height is needed as well to
// produce verification nonce for the taproot channel using shachain.
if targetChan.ChanType.IsTaproot() {
inputs.CommitHeight = localCommit.CommitHeight
}
// In case of a custom taproot channel, TapscriptRoot is needed as well.
if targetChan.ChanType.HasTapscriptRoot() {
inputs.TapscriptRoot = targetChan.TapscriptRoot
}
return fn.Some(inputs)
}
// FetchBackupForChan attempts to create a plaintext static channel backup for
// the target channel identified by its channel point. If we're unable to find
// the target channel, then an error will be returned.
func FetchBackupForChan(chanPoint wire.OutPoint, chanSource LiveChannelSource,
addrSource channeldb.AddrSource) (*Single, error) {
addrSource AddressSource) (*Single, error) {
// First, we'll query the channel source to see if the channel is known
// and open within the database.
targetChan, err := chanSource.FetchChannel(chanPoint)
targetChan, err := chanSource.FetchChannel(nil, chanPoint)
if err != nil {
// If we can't find the channel, then we return with an error,
// as we have nothing to backup.
@ -115,7 +81,7 @@ func FetchBackupForChan(chanPoint wire.OutPoint, chanSource LiveChannelSource,
// FetchStaticChanBackups will return a plaintext static channel back up for
// all known active/open channels within the passed channel source.
func FetchStaticChanBackups(chanSource LiveChannelSource,
addrSource channeldb.AddrSource) ([]Single, error) {
addrSource AddressSource) ([]Single, error) {
// First, we'll query the backup source for information concerning all
// currently open and available channels.

View File

@ -8,6 +8,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/stretchr/testify/require"
)
@ -39,7 +40,7 @@ func (m *mockChannelSource) FetchAllChannels() ([]*channeldb.OpenChannel, error)
return chans, nil
}
func (m *mockChannelSource) FetchChannel(chanPoint wire.OutPoint) (
func (m *mockChannelSource) FetchChannel(_ kvdb.RTx, chanPoint wire.OutPoint) (
*channeldb.OpenChannel, error) {
if m.failQuery {
@ -61,19 +62,20 @@ func (m *mockChannelSource) addAddrsForNode(nodePub *btcec.PublicKey, addrs []ne
m.addrs[nodeKey] = addrs
}
func (m *mockChannelSource) AddrsForNode(nodePub *btcec.PublicKey) (bool,
[]net.Addr, error) {
func (m *mockChannelSource) AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error) {
if m.failQuery {
return false, nil, fmt.Errorf("fail")
return nil, fmt.Errorf("fail")
}
var nodeKey [33]byte
copy(nodeKey[:], nodePub.SerializeCompressed())
addrs, ok := m.addrs[nodeKey]
if !ok {
return nil, fmt.Errorf("can't find addr")
}
return ok, addrs, nil
return addrs, nil
}
// TestFetchBackupForChan tests that we're able to construct a single channel
@ -156,8 +158,6 @@ func TestFetchStaticChanBackups(t *testing.T) {
chanSource.chans[randomChan2.FundingOutpoint] = randomChan2
chanSource.addAddrsForNode(randomChan1.IdentityPub, []net.Addr{addr1})
chanSource.addAddrsForNode(randomChan2.IdentityPub, []net.Addr{addr2})
chanSource.addAddrsForNode(randomChan2.IdentityPub, []net.Addr{addr3})
chanSource.addAddrsForNode(randomChan2.IdentityPub, []net.Addr{addr4})
// With the channel source populated, we'll now attempt to create a set
// of backups for all the channels. This should succeed, as all items

View File

@ -2,13 +2,10 @@ package chanbackup
import (
"fmt"
"io"
"os"
"path/filepath"
"time"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnrpc"
)
const (
@ -20,10 +17,6 @@ const (
// file that we'll use to atomically update the primary back up file
// when new channel are detected.
DefaultTempBackupFileName = "temp-dont-use.backup"
// DefaultChanBackupArchiveDirName is the default name of the directory
// that we'll use to store old channel backups.
DefaultChanBackupArchiveDirName = "chan-backup-archives"
)
var (
@ -51,40 +44,28 @@ type MultiFile struct {
// tempFile is an open handle to the temp back up file.
tempFile *os.File
// archiveDir is the directory where we'll store old channel backups.
archiveDir string
// noBackupArchive indicates whether old backups should be deleted
// rather than archived.
noBackupArchive bool
}
// NewMultiFile create a new multi-file instance at the target location on the
// file system.
func NewMultiFile(fileName string, noBackupArchive bool) *MultiFile {
func NewMultiFile(fileName string) *MultiFile {
// We'll our temporary backup file in the very same directory as the
// main backup file.
backupFileDir := filepath.Dir(fileName)
tempFileName := filepath.Join(
backupFileDir, DefaultTempBackupFileName,
)
archiveDir := filepath.Join(
backupFileDir, DefaultChanBackupArchiveDirName,
)
return &MultiFile{
fileName: fileName,
tempFileName: tempFileName,
archiveDir: archiveDir,
noBackupArchive: noBackupArchive,
fileName: fileName,
tempFileName: tempFileName,
}
}
// UpdateAndSwap will attempt write a new temporary backup file to disk with
// the newBackup encoded, then atomically swap (via rename) the old file for
// the new file by updating the name of the new file to the old. It also checks
// if the old file should be archived first before swapping it.
// the new file by updating the name of the new file to the old.
func (b *MultiFile) UpdateAndSwap(newBackup PackedMulti) error {
// If the main backup file isn't set, then we can't proceed.
if b.fileName == "" {
@ -136,12 +117,6 @@ func (b *MultiFile) UpdateAndSwap(newBackup PackedMulti) error {
return fmt.Errorf("unable to close file: %w", err)
}
// Archive the old channel backup file before replacing.
if err := b.createArchiveFile(); err != nil {
return fmt.Errorf("unable to archive old channel "+
"backup file: %w", err)
}
// Finally, we'll attempt to atomically rename the temporary file to
// the main back up file. If this succeeds, then we'll only have a
// single file on disk once this method exits.
@ -172,74 +147,3 @@ func (b *MultiFile) ExtractMulti(keyChain keychain.KeyRing) (*Multi, error) {
packedMulti := PackedMulti(multiBytes)
return packedMulti.Unpack(keyChain)
}
// createArchiveFile creates an archive file with a timestamped name in the
// specified archive directory, and copies the contents of the main backup file
// to the new archive file.
func (b *MultiFile) createArchiveFile() error {
// User can skip archiving of old backup files to save disk space.
if b.noBackupArchive {
log.Debug("Skipping archive of old backup file as configured")
return nil
}
// Check for old channel backup file.
oldFileExists := lnrpc.FileExists(b.fileName)
if !oldFileExists {
log.Debug("No old channel backup file to archive")
return nil
}
log.Infof("Archiving old channel backup to %v", b.archiveDir)
// Generate archive file path with timestamped name.
baseFileName := filepath.Base(b.fileName)
timestamp := time.Now().Format("2006-01-02-15-04-05")
archiveFileName := fmt.Sprintf("%s-%s", baseFileName, timestamp)
archiveFilePath := filepath.Join(b.archiveDir, archiveFileName)
oldBackupFile, err := os.Open(b.fileName)
if err != nil {
return fmt.Errorf("unable to open old channel backup file: "+
"%w", err)
}
defer func() {
err := oldBackupFile.Close()
if err != nil {
log.Errorf("unable to close old channel backup file: "+
"%v", err)
}
}()
// Ensure the archive directory exists. If it doesn't we create it.
const archiveDirPermissions = 0o700
err = os.MkdirAll(b.archiveDir, archiveDirPermissions)
if err != nil {
return fmt.Errorf("unable to create archive directory: %w", err)
}
// Create new archive file.
archiveFile, err := os.Create(archiveFilePath)
if err != nil {
return fmt.Errorf("unable to create archive file: %w", err)
}
defer func() {
err := archiveFile.Close()
if err != nil {
log.Errorf("unable to close archive file: %v", err)
}
}()
// Copy contents of old backup to the newly created archive files.
_, err = io.Copy(archiveFile, oldBackupFile)
if err != nil {
return fmt.Errorf("unable to copy to archive file: %w", err)
}
err = archiveFile.Sync()
if err != nil {
return fmt.Errorf("unable to sync archive file: %w", err)
}
return nil
}

View File

@ -45,121 +45,6 @@ func assertFileDeleted(t *testing.T, filePath string) {
}
}
// TestUpdateAndSwapWithArchive test that we're able to properly swap out old
// backups on disk with new ones. In addition, we check for noBackupArchive to
// ensure that the archive file is created when it's set to false, and not
// created when it's set to true.
func TestUpdateAndSwapWithArchive(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
noBackupArchive bool
}{
// Test with noBackupArchive set to true - should not create
// archive.
{
name: "no archive file",
noBackupArchive: true,
},
// Test with noBackupArchive set to false - should create
// archive.
{
name: "with archive file",
noBackupArchive: false,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tempTestDir := t.TempDir()
fileName := filepath.Join(
tempTestDir, DefaultBackupFileName,
)
tempFileName := filepath.Join(
tempTestDir, DefaultTempBackupFileName,
)
backupFile := NewMultiFile(fileName, tc.noBackupArchive)
// To start with, we'll make a random byte slice that'll
// pose as our packed multi backup.
newPackedMulti, err := makeFakePackedMulti()
require.NoError(t, err)
// With our backup created, we'll now attempt to swap
// out this backup, for the old one.
err = backupFile.UpdateAndSwap(newPackedMulti)
require.NoError(t, err)
// If we read out the file on disk, then it should match
// exactly what we wrote. The temp backup file should
// also be gone.
assertBackupMatches(t, fileName, newPackedMulti)
assertFileDeleted(t, tempFileName)
// Now that we know this is a valid test case, we'll
// make a new packed multi to swap out this current one.
newPackedMulti2, err := makeFakePackedMulti()
require.NoError(t, err)
// We'll then attempt to swap the old version for this
// new one.
err = backupFile.UpdateAndSwap(newPackedMulti2)
require.NoError(t, err)
// Once again, the file written on disk should have been
// properly swapped out with the new instance.
assertBackupMatches(t, fileName, newPackedMulti2)
// Additionally, we shouldn't be able to find the temp
// backup file on disk, as it should be deleted each
// time.
assertFileDeleted(t, tempFileName)
// Now check if archive was created when noBackupArchive
// is false.
archiveDir := filepath.Join(
filepath.Dir(fileName),
DefaultChanBackupArchiveDirName,
)
// When noBackupArchive is true, no new archive file
// should be created.
//
// NOTE: In a real environment, the archive directory
// might exist with older backups before the feature is
// disabled, but for test simplicity (since we clean up
// the directory between test cases), we verify the
// directory doesn't exist at all.
if tc.noBackupArchive {
require.NoDirExists(t, archiveDir)
return
}
// Otherwise we expect an archive to be created.
files, err := os.ReadDir(archiveDir)
require.NoError(t, err)
require.Len(t, files, 1)
// Verify the archive contents match the previous
// backup.
archiveFile := filepath.Join(
archiveDir, files[0].Name(),
)
// The archived content should match the previous backup
// (newPackedMulti) that was just swapped out.
assertBackupMatches(t, archiveFile, newPackedMulti)
// Clean up the archive directory.
os.RemoveAll(archiveDir)
})
}
}
// TestUpdateAndSwap test that we're able to properly swap out old backups on
// disk with new ones. Additionally, after a swap operation succeeds, then each
// time we should only have the main backup file on disk, as the temporary file
@ -167,112 +52,114 @@ func TestUpdateAndSwapWithArchive(t *testing.T) {
func TestUpdateAndSwap(t *testing.T) {
t.Parallel()
// Check that when the main file name is blank, an error is returned.
backupFile := NewMultiFile("", false)
err := backupFile.UpdateAndSwap(PackedMulti(nil))
require.ErrorIs(t, err, ErrNoBackupFileExists)
tempTestDir := t.TempDir()
testCases := []struct {
name string
fileName string
tempFileName string
oldTempExists bool
valid bool
}{
// Main file name is blank, should fail.
{
fileName: "",
valid: false,
},
// Old temporary file still exists, should be removed. Only one
// file should remain.
{
name: "remove old temp file",
fileName: filepath.Join(
tempTestDir, DefaultBackupFileName,
),
tempFileName: filepath.Join(
tempTestDir, DefaultTempBackupFileName,
),
oldTempExists: true,
valid: true,
},
// Old temp doesn't exist, should swap out file, only a single
// file remains.
{
name: "swap out file",
oldTempExists: false,
fileName: filepath.Join(
tempTestDir, DefaultBackupFileName,
),
tempFileName: filepath.Join(
tempTestDir, DefaultTempBackupFileName,
),
valid: true,
},
}
for i, testCase := range testCases {
backupFile := NewMultiFile(testCase.fileName)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tempTestDir := t.TempDir()
// To start with, we'll make a random byte slice that'll pose
// as our packed multi backup.
newPackedMulti, err := makeFakePackedMulti()
if err != nil {
t.Fatalf("unable to make test backup: %v", err)
}
fileName := filepath.Join(
tempTestDir, DefaultBackupFileName,
)
tempFileName := filepath.Join(
tempTestDir, DefaultTempBackupFileName,
)
backupFile := NewMultiFile(fileName, false)
// To start with, we'll make a random byte slice that'll
// pose as our packed multi backup.
newPackedMulti, err := makeFakePackedMulti()
require.NoError(t, err)
// If the old temporary file is meant to exist, then
// we'll create it now as an empty file.
if tc.oldTempExists {
f, err := os.Create(tempFileName)
require.NoError(t, err)
require.NoError(t, f.Close())
// TODO(roasbeef): mock out fs calls?
// If the old temporary file is meant to exist, then we'll
// create it now as an empty file.
if testCase.oldTempExists {
f, err := os.Create(testCase.tempFileName)
if err != nil {
t.Fatalf("unable to create temp file: %v", err)
}
require.NoError(t, f.Close())
// With our backup created, we'll now attempt to swap
// out this backup, for the old one.
err = backupFile.UpdateAndSwap(newPackedMulti)
require.NoError(t, err)
// TODO(roasbeef): mock out fs calls?
}
// If we read out the file on disk, then it should match
// exactly what we wrote. The temp backup file should
// also be gone.
assertBackupMatches(t, fileName, newPackedMulti)
assertFileDeleted(t, tempFileName)
// With our backup created, we'll now attempt to swap out this
// backup, for the old one.
err = backupFile.UpdateAndSwap(PackedMulti(newPackedMulti))
switch {
// If this is a valid test case, and we failed, then we'll
// return an error.
case err != nil && testCase.valid:
t.Fatalf("#%v, unable to swap file: %v", i, err)
// Now that we know this is a valid test case, we'll
// make a new packed multi to swap out this current one.
newPackedMulti2, err := makeFakePackedMulti()
require.NoError(t, err)
// If this is an invalid test case, and we passed it, then
// we'll return an error.
case err == nil && !testCase.valid:
t.Fatalf("#%v file swap should have failed: %v", i, err)
}
// We'll then attempt to swap the old version for this
// new one.
err = backupFile.UpdateAndSwap(newPackedMulti2)
require.NoError(t, err)
if !testCase.valid {
continue
}
// Once again, the file written on disk should have been
// properly swapped out with the new instance.
assertBackupMatches(t, fileName, newPackedMulti2)
// If we read out the file on disk, then it should match
// exactly what we wrote. The temp backup file should also be
// gone.
assertBackupMatches(t, testCase.fileName, newPackedMulti)
assertFileDeleted(t, testCase.tempFileName)
// Additionally, we shouldn't be able to find the temp
// backup file on disk, as it should be deleted each
// time.
assertFileDeleted(t, tempFileName)
// Now that we know this is a valid test case, we'll make a new
// packed multi to swap out this current one.
newPackedMulti2, err := makeFakePackedMulti()
if err != nil {
t.Fatalf("unable to make test backup: %v", err)
}
// Now check if archive was created when noBackupArchive
// is false.
archiveDir := filepath.Join(
filepath.Dir(fileName),
DefaultChanBackupArchiveDirName,
)
files, err := os.ReadDir(archiveDir)
require.NoError(t, err)
require.Len(t, files, 1)
// We'll then attempt to swap the old version for this new one.
err = backupFile.UpdateAndSwap(PackedMulti(newPackedMulti2))
if err != nil {
t.Fatalf("unable to swap file: %v", err)
}
// Verify the archive contents match the previous
// backup.
archiveFile := filepath.Join(
archiveDir, files[0].Name(),
)
// Once again, the file written on disk should have been
// properly swapped out with the new instance.
assertBackupMatches(t, testCase.fileName, newPackedMulti2)
// The archived content should match the previous backup
// (newPackedMulti) that was just swapped out.
assertBackupMatches(t, archiveFile, newPackedMulti)
// Clean up the archive directory.
os.RemoveAll(archiveDir)
})
// Additionally, we shouldn't be able to find the temp backup
// file on disk, as it should be deleted each time.
assertFileDeleted(t, testCase.tempFileName)
}
}
@ -351,7 +238,7 @@ func TestExtractMulti(t *testing.T) {
}
for i, testCase := range testCases {
// First, we'll make our backup file with the specified name.
backupFile := NewMultiFile(testCase.fileName, false)
backupFile := NewMultiFile(testCase.fileName)
// With our file made, we'll now attempt to read out the
// multi-file.
@ -387,86 +274,3 @@ func TestExtractMulti(t *testing.T) {
assertMultiEqual(t, &unpackedMulti, freshUnpackedMulti)
}
}
// TestCreateArchiveFile tests that we're able to create an archive file
// with a timestamped name in the specified archive directory, and copy the
// contents of the main backup file to the new archive file.
func TestCreateArchiveFile(t *testing.T) {
t.Parallel()
// First, we'll create a temporary directory for our test files.
tempDir := t.TempDir()
archiveDir := filepath.Join(tempDir, DefaultChanBackupArchiveDirName)
// Next, we'll create a test backup file and write some content to it.
backupFile := filepath.Join(tempDir, DefaultBackupFileName)
testContent := []byte("test backup content")
err := os.WriteFile(backupFile, testContent, 0644)
require.NoError(t, err)
tests := []struct {
name string
setup func()
noBackupArchive bool
wantError bool
}{
{
name: "successful archive",
noBackupArchive: false,
},
{
name: "skip archive when disabled",
noBackupArchive: true,
},
{
name: "invalid archive directory permissions",
setup: func() {
// Create dir with no write permissions.
err := os.MkdirAll(archiveDir, 0500)
require.NoError(t, err)
},
noBackupArchive: false,
wantError: true,
},
}
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
defer os.RemoveAll(archiveDir)
if tc.setup != nil {
tc.setup()
}
multiFile := NewMultiFile(
backupFile, tc.noBackupArchive,
)
err := multiFile.createArchiveFile()
if tc.wantError {
require.Error(t, err)
return
}
require.NoError(t, err)
// If archiving is disabled, verify no archive was
// created.
if tc.noBackupArchive {
require.NoDirExists(t, archiveDir)
return
}
// Verify archive exists and content matches.
files, err := os.ReadDir(archiveDir)
require.NoError(t, err)
require.Len(t, files, 1)
archivedContent, err := os.ReadFile(
filepath.Join(archiveDir, files[0].Name()),
)
require.NoError(t, err)
assertBackupMatches(t, backupFile, archivedContent)
})
}
}

View File

@ -1,7 +1,7 @@
package chanbackup
import (
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

View File

@ -22,9 +22,7 @@ func TestMultiPackUnpack(t *testing.T) {
t.Fatalf("unable to gen channel: %v", err)
}
single := NewSingle(
channel, []net.Addr{addr1, addr2, addr3, addr4},
)
single := NewSingle(channel, []net.Addr{addr1, addr2})
originalSingles = append(originalSingles, single)
multi.StaticBackups = append(multi.StaticBackups, single)

View File

@ -6,7 +6,6 @@ import (
"net"
"os"
"sync"
"sync/atomic"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
@ -49,19 +48,6 @@ type ChannelEvent struct {
NewChans []ChannelWithAddrs
}
// manualUpdate holds a group of channel state updates and an error channel
// to send back an error happened upon update processing or file updating.
type manualUpdate struct {
// singles hold channels backups. They can be either new or known
// channels in the Swapper.
singles []Single
// errChan is the channel to send an error back. If the update handling
// and the subsequent file updating succeeds, nil is sent.
// The channel must have capacity of 1 to prevent Swapper blocking.
errChan chan error
}
// ChannelSubscription represents an intent to be notified of any updates to
// the primary channel state.
type ChannelSubscription struct {
@ -94,12 +80,7 @@ type ChannelNotifier interface {
// be used to implement a system that always keeps the multi-chan backup file
// on disk in a consistent state for safety purposes.
type SubSwapper struct {
// started tracks whether the SubSwapper has been started and ensures
// it can only be started once.
started sync.Once
// stopped tracks whether the SubSwapper has been stopped and ensures
// it can only be stopped once.
stopped sync.Once
// backupState are the set of SCBs for all open channels we know of.
@ -109,8 +90,6 @@ type SubSwapper struct {
// over.
chanEvents *ChannelSubscription
manualUpdates chan manualUpdate
// keyRing is the main key ring that will allow us to pack the new
// multi backup.
keyRing keychain.KeyRing
@ -119,11 +98,6 @@ type SubSwapper struct {
quit chan struct{}
wg sync.WaitGroup
// isActive tracks whether the SubSwapper is active and ready to receive
// messages. It is used to prevent manual updates from being sent to the
// SubSwapper after it has been stopped or not yet started.
isActive atomic.Bool
}
// NewSubSwapper creates a new instance of the SubSwapper given the starting
@ -152,12 +126,11 @@ func NewSubSwapper(startingChans []Single, chanNotifier ChannelNotifier,
}
return &SubSwapper{
backupState: backupState,
chanEvents: chanEvents,
keyRing: keyRing,
Swapper: backupSwapper,
quit: make(chan struct{}),
manualUpdates: make(chan manualUpdate),
backupState: backupState,
chanEvents: chanEvents,
keyRing: keyRing,
Swapper: backupSwapper,
quit: make(chan struct{}),
}, nil
}
@ -173,7 +146,6 @@ func (s *SubSwapper) Start() error {
if err := s.updateBackupFile(); err != nil {
startErr = fmt.Errorf("unable to refresh backup "+
"file: %v", err)
return
}
@ -190,55 +162,9 @@ func (s *SubSwapper) Stop() error {
log.Infof("chanbackup.SubSwapper shutting down...")
defer log.Debug("chanbackup.SubSwapper shutdown complete")
// Mark the SubSwapper as not running.
s.isActive.Store(false)
close(s.quit)
s.wg.Wait()
})
return nil
}
// ManualUpdate inserts/updates channel states into the swapper. The updates
// are processed in another goroutine. The method waits for the updates to be
// fully processed and the file to be updated on-disk before returning.
func (s *SubSwapper) ManualUpdate(singles []Single) error {
if !s.isActive.Load() {
return fmt.Errorf("swapper is not active, cannot perform " +
"manual update")
}
// Create the channel to send an error back. If the update handling
// and the subsequent file updating succeeds, nil is sent.
// The channel must have capacity of 1 to prevent Swapper blocking.
errChan := make(chan error, 1)
// Create the update object to insert into the processing loop.
update := manualUpdate{
singles: singles,
errChan: errChan,
}
select {
case s.manualUpdates <- update:
case <-s.quit:
return fmt.Errorf("swapper stopped when sending manual update")
}
// Wait for processing, block on errChan.
select {
case err := <-errChan:
if err != nil {
return fmt.Errorf("processing of manual update "+
"failed: %w", err)
}
case <-s.quit:
return fmt.Errorf("swapper stopped when waiting for outcome")
}
// Success.
return nil
}
@ -318,8 +244,7 @@ func (s *SubSwapper) updateBackupFile(closedChans ...wire.OutPoint) error {
// backupFileUpdater is the primary goroutine of the SubSwapper which is
// responsible for listening for changes to the channel, and updating the
// persistent multi backup state with a new packed multi of the latest channel
// state. Once active, it will process subscription updates and manual updates
// until the SubSwapper is stopped.
// state.
func (s *SubSwapper) backupUpdater() {
// Ensure that once we exit, we'll cancel our active channel
// subscription.
@ -328,9 +253,6 @@ func (s *SubSwapper) backupUpdater() {
log.Debugf("SubSwapper's backupUpdater is active!")
// Mark the SubSwapper as active.
s.isActive.Store(true)
for {
select {
// The channel state has been modified! We'll evaluate all
@ -345,10 +267,9 @@ func (s *SubSwapper) backupUpdater() {
log.Debugf("Adding channel %v to backup state",
newChan.FundingOutpoint)
single := NewSingle(
s.backupState[newChan.FundingOutpoint] = NewSingle(
newChan.OpenChannel, newChan.Addrs,
)
s.backupState[newChan.FundingOutpoint] = single
}
// For all closed channels, we'll remove the prior
@ -372,45 +293,13 @@ func (s *SubSwapper) backupUpdater() {
"num_old_chans=%v, num_new_chans=%v",
oldStateSize, newStateSize)
// Without new state constructed, we'll, atomically
// With out new state constructed, we'll, atomically
// update the on-disk backup state.
if err := s.updateBackupFile(closedChans...); err != nil {
log.Errorf("unable to update backup file: %v",
err)
}
// We received a manual update. Handle it and update the file.
case manualUpdate := <-s.manualUpdates:
oldStateSize := len(s.backupState)
// For all open channels, we'll create a new SCB given
// the required information.
for _, single := range manualUpdate.singles {
log.Debugf("Manual update of channel %v",
single.FundingOutpoint)
s.backupState[single.FundingOutpoint] = single
}
newStateSize := len(s.backupState)
log.Infof("Updating on-disk multi SCB backup: "+
"num_old_chans=%v, num_new_chans=%v",
oldStateSize, newStateSize)
// Without new state constructed, we'll, atomically
// update the on-disk backup state.
err := s.updateBackupFile()
if err != nil {
log.Errorf("unable to update backup file: %v",
err)
}
// Send the error (or nil) to the caller of
// ManualUpdate. The error channel must have capacity of
// 1 not to block here.
manualUpdate.errChan <- err
// TODO(roasbeef): refresh periodically on a time basis due to
// possible addr changes from node

View File

@ -277,18 +277,4 @@ func TestSubSwapperUpdater(t *testing.T) {
// Verify that the new set of backups, now has one less after the
// sub-swapper switches the new set with the old.
assertExpectedBackupSwap(t, swapper, subSwapper, keyRing, backupSet)
// Check ManualUpdate method.
channel, err := genRandomOpenChannelShell()
require.NoError(t, err)
single := NewSingle(channel, nil)
backupSet[channel.FundingOutpoint] = single
require.NoError(t, subSwapper.ManualUpdate([]Single{single}))
// Verify that the state of the backup is as expected.
assertExpectedBackupSwap(t, swapper, subSwapper, keyRing, backupSet)
// Check the case ManualUpdate returns an error.
swapper.fail = true
require.Error(t, subSwapper.ManualUpdate([]Single{single}))
}

View File

@ -40,11 +40,9 @@ type PeerConnector interface {
// the channel. In addition a LinkNode will be created for each new peer as
// well, in order to expose the addressing information required to locate to
// and connect to each peer in order to initiate the recovery protocol.
// The number of channels that were successfully restored is returned.
func Recover(backups []Single, restorer ChannelRestorer,
peerConnector PeerConnector) (int, error) {
peerConnector PeerConnector) error {
var numRestored int
for i, backup := range backups {
log.Infof("Restoring ChannelPoint(%v) to disk: ",
backup.FundingOutpoint)
@ -59,10 +57,9 @@ func Recover(backups []Single, restorer ChannelRestorer,
continue
}
if err != nil {
return numRestored, err
return err
}
numRestored++
log.Infof("Attempting to connect to node=%x (addrs=%v) to "+
"restore ChannelPoint(%v)",
backup.RemoteNodePub.SerializeCompressed(),
@ -73,7 +70,7 @@ func Recover(backups []Single, restorer ChannelRestorer,
backup.RemoteNodePub, backup.Addresses,
)
if err != nil {
return numRestored, err
return err
}
// TODO(roasbeef): to handle case where node has changed addrs,
@ -83,7 +80,7 @@ func Recover(backups []Single, restorer ChannelRestorer,
// * just to to fresh w/ call to node addrs and de-dup?
}
return numRestored, nil
return nil
}
// TODO(roasbeef): more specific keychain interface?
@ -91,17 +88,16 @@ func Recover(backups []Single, restorer ChannelRestorer,
// UnpackAndRecoverSingles is a one-shot method, that given a set of packed
// single channel backups, will restore the channel state to a channel shell,
// and also reach out to connect to any of the known node addresses for that
// channel. It is assumes that after this method exists, if a connection was
// established, then the PeerConnector will continue to attempt to re-establish
// a persistent connection in the background. The number of channels that were
// successfully restored is returned.
// channel. It is assumes that after this method exists, if a connection we
// able to be established, then then PeerConnector will continue to attempt to
// re-establish a persistent connection in the background.
func UnpackAndRecoverSingles(singles PackedSingles,
keyChain keychain.KeyRing, restorer ChannelRestorer,
peerConnector PeerConnector) (int, error) {
peerConnector PeerConnector) error {
chanBackups, err := singles.Unpack(keyChain)
if err != nil {
return 0, err
return err
}
return Recover(chanBackups, restorer, peerConnector)
@ -110,17 +106,16 @@ func UnpackAndRecoverSingles(singles PackedSingles,
// UnpackAndRecoverMulti is a one-shot method, that given a set of packed
// multi-channel backups, will restore the channel states to channel shells,
// and also reach out to connect to any of the known node addresses for that
// channel. It is assumes that after this method exists, if a connection was
// established, then the PeerConnector will continue to attempt to re-establish
// a persistent connection in the background. The number of channels that were
// successfully restored is returned.
// channel. It is assumes that after this method exists, if a connection we
// able to be established, then then PeerConnector will continue to attempt to
// re-establish a persistent connection in the background.
func UnpackAndRecoverMulti(packedMulti PackedMulti,
keyChain keychain.KeyRing, restorer ChannelRestorer,
peerConnector PeerConnector) (int, error) {
peerConnector PeerConnector) error {
chanBackups, err := packedMulti.Unpack(keyChain)
if err != nil {
return 0, err
return err
}
return Recover(chanBackups.StaticBackups, restorer, peerConnector)

View File

@ -2,7 +2,7 @@ package chanbackup
import (
"bytes"
"errors"
"fmt"
"net"
"testing"
@ -11,12 +11,6 @@ import (
"github.com/stretchr/testify/require"
)
var (
errRestoreFail = errors.New("restore fail")
errConnectFail = errors.New("connect fail")
)
type mockChannelRestorer struct {
fail bool
@ -25,7 +19,7 @@ type mockChannelRestorer struct {
func (m *mockChannelRestorer) RestoreChansFromSingles(...Single) error {
if m.fail {
return errRestoreFail
return fmt.Errorf("fail")
}
m.callCount++
@ -39,11 +33,11 @@ type mockPeerConnector struct {
callCount int
}
func (m *mockPeerConnector) ConnectPeer(_ *btcec.PublicKey,
_ []net.Addr) error {
func (m *mockPeerConnector) ConnectPeer(node *btcec.PublicKey,
addrs []net.Addr) error {
if m.fail {
return errConnectFail
return fmt.Errorf("fail")
}
m.callCount++
@ -65,13 +59,16 @@ func TestUnpackAndRecoverSingles(t *testing.T) {
var packedBackups PackedSingles
for i := 0; i < numSingles; i++ {
channel, err := genRandomOpenChannelShell()
require.NoError(t, err)
if err != nil {
t.Fatalf("unable make channel: %v", err)
}
single := NewSingle(channel, nil)
var b bytes.Buffer
err = single.PackToWriter(&b, keyRing)
require.NoError(t, err)
if err := single.PackToWriter(&b, keyRing); err != nil {
t.Fatalf("unable to pack single: %v", err)
}
backups = append(backups, single)
packedBackups = append(packedBackups, b.Bytes())
@ -86,47 +83,54 @@ func TestUnpackAndRecoverSingles(t *testing.T) {
// If we make the channel restore fail, then the entire method should
// as well
chanRestorer.fail = true
_, err := UnpackAndRecoverSingles(
err := UnpackAndRecoverSingles(
packedBackups, keyRing, &chanRestorer, &peerConnector,
)
require.ErrorIs(t, err, errRestoreFail)
if err == nil {
t.Fatalf("restoration should have failed")
}
chanRestorer.fail = false
// If we make the peer connector fail, then the entire method should as
// well
peerConnector.fail = true
_, err = UnpackAndRecoverSingles(
err = UnpackAndRecoverSingles(
packedBackups, keyRing, &chanRestorer, &peerConnector,
)
require.ErrorIs(t, err, errConnectFail)
if err == nil {
t.Fatalf("restoration should have failed")
}
chanRestorer.callCount--
peerConnector.fail = false
// Next, we'll ensure that if all the interfaces function as expected,
// then the channels will properly be unpacked and restored.
numRestored, err := UnpackAndRecoverSingles(
err = UnpackAndRecoverSingles(
packedBackups, keyRing, &chanRestorer, &peerConnector,
)
require.NoError(t, err)
require.EqualValues(t, numSingles, numRestored)
require.NoError(t, err, "unable to recover chans")
// Both the restorer, and connector should have been called 10 times,
// once for each backup.
require.EqualValues(
t, numSingles, chanRestorer.callCount, "restorer call count",
)
require.EqualValues(
t, numSingles, peerConnector.callCount, "peer call count",
)
if chanRestorer.callCount != numSingles {
t.Fatalf("expected %v calls, instead got %v",
numSingles, chanRestorer.callCount)
}
if peerConnector.callCount != numSingles {
t.Fatalf("expected %v calls, instead got %v",
numSingles, peerConnector.callCount)
}
// If we modify the keyRing, then unpacking should fail.
keyRing.Fail = true
_, err = UnpackAndRecoverSingles(
err = UnpackAndRecoverSingles(
packedBackups, keyRing, &chanRestorer, &peerConnector,
)
require.ErrorContains(t, err, "fail")
if err == nil {
t.Fatalf("unpacking should have failed")
}
// TODO(roasbeef): verify proper call args
}
@ -144,7 +148,9 @@ func TestUnpackAndRecoverMulti(t *testing.T) {
backups := make([]Single, 0, numSingles)
for i := 0; i < numSingles; i++ {
channel, err := genRandomOpenChannelShell()
require.NoError(t, err)
if err != nil {
t.Fatalf("unable make channel: %v", err)
}
single := NewSingle(channel, nil)
@ -156,8 +162,9 @@ func TestUnpackAndRecoverMulti(t *testing.T) {
}
var b bytes.Buffer
err := multi.PackToWriter(&b, keyRing)
require.NoError(t, err)
if err := multi.PackToWriter(&b, keyRing); err != nil {
t.Fatalf("unable to pack multi: %v", err)
}
// Next, we'll pack the set of singles into a packed multi, and also
// create the set of interfaces we need to carry out the remainder of
@ -170,47 +177,54 @@ func TestUnpackAndRecoverMulti(t *testing.T) {
// If we make the channel restore fail, then the entire method should
// as well
chanRestorer.fail = true
_, err = UnpackAndRecoverMulti(
err := UnpackAndRecoverMulti(
packedMulti, keyRing, &chanRestorer, &peerConnector,
)
require.ErrorIs(t, err, errRestoreFail)
if err == nil {
t.Fatalf("restoration should have failed")
}
chanRestorer.fail = false
// If we make the peer connector fail, then the entire method should as
// well
peerConnector.fail = true
_, err = UnpackAndRecoverMulti(
err = UnpackAndRecoverMulti(
packedMulti, keyRing, &chanRestorer, &peerConnector,
)
require.ErrorIs(t, err, errConnectFail)
if err == nil {
t.Fatalf("restoration should have failed")
}
chanRestorer.callCount--
peerConnector.fail = false
// Next, we'll ensure that if all the interfaces function as expected,
// then the channels will properly be unpacked and restored.
numRestored, err := UnpackAndRecoverMulti(
err = UnpackAndRecoverMulti(
packedMulti, keyRing, &chanRestorer, &peerConnector,
)
require.NoError(t, err)
require.EqualValues(t, numSingles, numRestored)
require.NoError(t, err, "unable to recover chans")
// Both the restorer, and connector should have been called 10 times,
// once for each backup.
require.EqualValues(
t, numSingles, chanRestorer.callCount, "restorer call count",
)
require.EqualValues(
t, numSingles, peerConnector.callCount, "peer call count",
)
if chanRestorer.callCount != numSingles {
t.Fatalf("expected %v calls, instead got %v",
numSingles, chanRestorer.callCount)
}
if peerConnector.callCount != numSingles {
t.Fatalf("expected %v calls, instead got %v",
numSingles, peerConnector.callCount)
}
// If we modify the keyRing, then unpacking should fail.
keyRing.Fail = true
_, err = UnpackAndRecoverMulti(
err = UnpackAndRecoverMulti(
packedMulti, keyRing, &chanRestorer, &peerConnector,
)
require.ErrorContains(t, err, "fail")
if err == nil {
t.Fatalf("unpacking should have failed")
}
// TODO(roasbeef): verify proper call args
}

View File

@ -2,7 +2,6 @@ package chanbackup
import (
"bytes"
"errors"
"fmt"
"io"
"net"
@ -12,7 +11,6 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnencrypt"
"github.com/lightningnetwork/lnd/lnwire"
@ -54,55 +52,8 @@ const (
// SimpleTaprootVersion is a version that denotes this channel is using
// the musig2 based taproot commitment format.
SimpleTaprootVersion = 5
// TapscriptRootVersion is a version that denotes this is a MuSig2
// channel with a top level tapscript commitment.
TapscriptRootVersion = 6
// closeTxVersionMask is the byte mask used that is ORed to version byte
// on wire indicating that the backup has CloseTxInputs.
closeTxVersionMask = 1 << 7
)
// Encode returns encoding of the version to put into channel backup.
// Argument "closeTx" specifies if the backup includes force close transaction.
func (v SingleBackupVersion) Encode(closeTx bool) byte {
encoded := byte(v)
// If the backup includes closing transaction, set this bit in the
// encoded version.
if closeTx {
encoded |= closeTxVersionMask
}
return encoded
}
// DecodeVersion decodes the encoding of the version from a channel backup.
// It returns the version and if the backup includes the force close tx.
func DecodeVersion(encoded byte) (SingleBackupVersion, bool) {
// Find if it has a closing transaction by inspecting the bit.
closeTx := (encoded & closeTxVersionMask) != 0
// The version byte also encodes the closeTxVersion feature, so we
// extract it here and return it separately to the backup version.
version := SingleBackupVersion(encoded &^ closeTxVersionMask)
return version, closeTx
}
// IsTaproot returns if this is a backup of a taproot channel. This will also be
// true for simple taproot overlay channels when a version is added.
func (v SingleBackupVersion) IsTaproot() bool {
return v == SimpleTaprootVersion || v == TapscriptRootVersion
}
// HasTapscriptRoot returns true if the channel is using a top level tapscript
// root commitment.
func (v SingleBackupVersion) HasTapscriptRoot() bool {
return v == TapscriptRootVersion
}
// Single is a static description of an existing channel that can be used for
// the purposes of backing up. The fields in this struct allow a node to
// recover the settled funds within a channel in the case of partial or
@ -187,47 +138,11 @@ type Single struct {
//
// - ScriptEnforcedLeaseVersion
LeaseExpiry uint32
// CloseTxInputs contains data needed to produce a force close tx
// using for example the "chantools scbforceclose" command.
//
// The field is optional.
CloseTxInputs fn.Option[CloseTxInputs]
}
// CloseTxInputs contains data needed to produce a force close transaction
// using for example the "chantools scbforceclose" command.
type CloseTxInputs struct {
// CommitTx is the latest version of the commitment state, broadcast
// able by us, but not signed. It can be signed by for example the
// "chantools scbforceclose" command.
CommitTx *wire.MsgTx
// CommitSig is one half of the signature required to fully complete
// the script for the commitment transaction above. This is the
// signature signed by the remote party for our version of the
// commitment transactions.
CommitSig []byte
// CommitHeight is the update number that this ChannelDelta represents
// the total number of commitment updates to this point. This can be
// viewed as sort of a "commitment height" as this number is
// monotonically increasing.
//
// This field is filled only for taproot channels.
CommitHeight uint64
// TapscriptRoot is the root of the tapscript tree that will be used to
// create the funding output. This is an optional field that should
// only be set for overlay taproot channels (HasTapscriptRoot).
TapscriptRoot fn.Option[chainhash.Hash]
}
// NewSingle creates a new static channel backup based on an existing open
// channel. We also pass in the set of addresses that we used in the past to
// connect to the channel peer. If possible, we include the data needed to
// produce a force close transaction from the most recent state using externally
// provided private key.
// connect to the channel peer.
func NewSingle(channel *channeldb.OpenChannel,
nodeAddrs []net.Addr) Single {
@ -303,11 +218,7 @@ func NewSingle(channel *channeldb.OpenChannel,
switch {
case channel.ChanType.IsTaproot():
if channel.ChanType.HasTapscriptRoot() {
single.Version = TapscriptRootVersion
} else {
single.Version = SimpleTaprootVersion
}
single.Version = SimpleTaprootVersion
case channel.ChanType.HasLeaseExpiration():
single.Version = ScriptEnforcedLeaseVersion
@ -326,18 +237,9 @@ func NewSingle(channel *channeldb.OpenChannel,
single.Version = DefaultSingleVersion
}
// Include unsigned force-close transaction for the most recent channel
// state as well as the data needed to produce the signature, given the
// private key is provided separately.
single.CloseTxInputs = buildCloseTxInputs(channel)
return single
}
// errEmptyTapscriptRoot is returned by Serialize if field TapscriptRoot is
// empty, when it should be filled according to the channel version.
var errEmptyTapscriptRoot = errors.New("field TapscriptRoot is not filled")
// Serialize attempts to write out the serialized version of the target
// StaticChannelBackup into the passed io.Writer.
func (s *Single) Serialize(w io.Writer) error {
@ -350,7 +252,6 @@ func (s *Single) Serialize(w io.Writer) error {
case AnchorsZeroFeeHtlcTxCommitVersion:
case ScriptEnforcedLeaseVersion:
case SimpleTaprootVersion:
case TapscriptRootVersion:
default:
return fmt.Errorf("unable to serialize w/ unknown "+
"version: %v", s.Version)
@ -419,60 +320,6 @@ func (s *Single) Serialize(w io.Writer) error {
}
}
// Encode version enum and hasCloseTx flag to version byte.
version := s.Version.Encode(s.CloseTxInputs.IsSome())
// Serialize CloseTxInputs if it is provided. Fill err if it fails.
err := fn.MapOptionZ(s.CloseTxInputs, func(inputs CloseTxInputs) error {
err := inputs.CommitTx.Serialize(&singleBytes)
if err != nil {
return err
}
err = lnwire.WriteElements(
&singleBytes,
uint16(len(inputs.CommitSig)), inputs.CommitSig,
)
if err != nil {
return err
}
if !s.Version.IsTaproot() {
return nil
}
// Write fields needed for taproot channels.
err = lnwire.WriteElements(
&singleBytes, inputs.CommitHeight,
)
if err != nil {
return err
}
if s.Version.HasTapscriptRoot() {
opt := inputs.TapscriptRoot
var tapscriptRoot chainhash.Hash
tapscriptRoot, err = opt.UnwrapOrErr(
errEmptyTapscriptRoot,
)
if err != nil {
return err
}
err = lnwire.WriteElements(
&singleBytes, tapscriptRoot[:],
)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return fmt.Errorf("failed to encode CloseTxInputs: %w", err)
}
// TODO(yy): remove the type assertion when we finished refactoring db
// into using write buffer.
buf, ok := w.(*bytes.Buffer)
@ -482,7 +329,7 @@ func (s *Single) Serialize(w io.Writer) error {
return lnwire.WriteElements(
buf,
version,
byte(s.Version),
uint16(len(singleBytes.Bytes())),
singleBytes.Bytes(),
)
@ -573,9 +420,7 @@ func (s *Single) Deserialize(r io.Reader) error {
return err
}
// Decode version byte to version enum and hasCloseTx flag.
var hasCloseTx bool
s.Version, hasCloseTx = DecodeVersion(version)
s.Version = SingleBackupVersion(version)
switch s.Version {
case DefaultSingleVersion:
@ -584,7 +429,6 @@ func (s *Single) Deserialize(r io.Reader) error {
case AnchorsZeroFeeHtlcTxCommitVersion:
case ScriptEnforcedLeaseVersion:
case SimpleTaprootVersion:
case TapscriptRootVersion:
default:
return fmt.Errorf("unable to de-serialize w/ unknown "+
"version: %v", s.Version)
@ -689,50 +533,6 @@ func (s *Single) Deserialize(r io.Reader) error {
}
}
if !hasCloseTx {
return nil
}
// Deserialize CloseTxInputs if it is present in serialized data.
commitTx := &wire.MsgTx{}
if err := commitTx.Deserialize(r); err != nil {
return err
}
var commitSigLen uint16
if err := lnwire.ReadElement(r, &commitSigLen); err != nil {
return err
}
commitSig := make([]byte, commitSigLen)
if err := lnwire.ReadElement(r, commitSig); err != nil {
return err
}
var commitHeight uint64
if s.Version.IsTaproot() {
err := lnwire.ReadElement(r, &commitHeight)
if err != nil {
return err
}
}
tapscriptRootOpt := fn.None[chainhash.Hash]()
if s.Version.HasTapscriptRoot() {
var tapscriptRoot chainhash.Hash
err := lnwire.ReadElement(r, tapscriptRoot[:])
if err != nil {
return err
}
tapscriptRootOpt = fn.Some(tapscriptRoot)
}
s.CloseTxInputs = fn.Some(CloseTxInputs{
CommitTx: commitTx,
CommitSig: commitSig,
CommitHeight: commitHeight,
TapscriptRoot: tapscriptRootOpt,
})
return nil
}

View File

@ -13,12 +13,10 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnencrypt"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/shachain"
"github.com/lightningnetwork/lnd/tor"
"github.com/stretchr/testify/require"
)
@ -37,15 +35,6 @@ var (
addr1, _ = net.ResolveTCPAddr("tcp", "10.0.0.2:9000")
addr2, _ = net.ResolveTCPAddr("tcp", "10.0.0.3:9000")
addr3 = &tor.OnionAddr{
OnionService: "3g2upl4pq6kufc4m.onion",
Port: 9735,
}
addr4 = &lnwire.OpaqueAddrs{
// The first byte must be an address type we are not yet aware
// of for it to be a valid OpaqueAddrs.
Payload: []byte{math.MaxUint8, 1, 2, 3, 4},
}
)
func assertSingleEqual(t *testing.T, a, b Single) {
@ -106,29 +95,6 @@ func assertSingleEqual(t *testing.T, a, b Single) {
a.Addresses[i], b.Addresses[i])
}
}
// Make sure that CloseTxInputs are present either in both backups,
// or in none of them.
require.Equal(t, a.CloseTxInputs.IsSome(), b.CloseTxInputs.IsSome())
if a.CloseTxInputs.IsSome() {
// Cache CloseTxInputs into short variables.
ai := a.CloseTxInputs.UnwrapOrFail(t)
bi := b.CloseTxInputs.UnwrapOrFail(t)
// Compare serialized unsigned transactions.
var abuf, bbuf bytes.Buffer
require.NoError(t, ai.CommitTx.Serialize(&abuf))
require.NoError(t, bi.CommitTx.Serialize(&bbuf))
aBytes := abuf.Bytes()
bBytes := bbuf.Bytes()
require.Equal(t, aBytes, bBytes)
// Compare counterparty's signature and commit height.
require.Equal(t, ai.CommitSig, bi.CommitSig)
require.Equal(t, ai.CommitHeight, bi.CommitHeight)
require.Equal(t, ai.TapscriptRoot, bi.TapscriptRoot)
}
}
func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
@ -158,7 +124,7 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
isInitiator = true
}
chanType := channeldb.ChannelType(rand.Intn(1 << 12))
chanType := channeldb.ChannelType(rand.Intn(8))
localCfg := channeldb.ChannelConfig{
ChannelStateBounds: channeldb.ChannelStateBounds{},
@ -218,29 +184,6 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
},
}
var localCommit channeldb.ChannelCommitment
if chanType.IsTaproot() {
var commitSig [64]byte
if _, err := rand.Read(commitSig[:]); err != nil {
return nil, err
}
localCommit = channeldb.ChannelCommitment{
CommitTx: sampleCommitTx,
CommitSig: commitSig[:],
CommitHeight: rand.Uint64(),
}
}
var tapscriptRootOption fn.Option[chainhash.Hash]
if chanType.HasTapscriptRoot() {
var tapscriptRoot chainhash.Hash
if _, err := rand.Read(tapscriptRoot[:]); err != nil {
return nil, err
}
tapscriptRootOption = fn.Some(tapscriptRoot)
}
return &channeldb.OpenChannel{
ChainHash: chainHash,
ChanType: chanType,
@ -253,61 +196,10 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
IdentityPub: pub,
LocalChanCfg: localCfg,
RemoteChanCfg: remoteCfg,
LocalCommitment: localCommit,
RevocationProducer: shaChainProducer,
TapscriptRoot: tapscriptRootOption,
}, nil
}
// TestVersionEncoding tests encoding and decoding of version byte.
func TestVersionEncoding(t *testing.T) {
cases := []struct {
version SingleBackupVersion
hasCloseTx bool
versionByte byte
}{
{
version: DefaultSingleVersion,
hasCloseTx: false,
versionByte: DefaultSingleVersion,
},
{
version: DefaultSingleVersion,
hasCloseTx: true,
versionByte: DefaultSingleVersion | closeTxVersionMask,
},
{
version: AnchorsCommitVersion,
hasCloseTx: false,
versionByte: AnchorsCommitVersion,
},
{
version: AnchorsCommitVersion,
hasCloseTx: true,
versionByte: AnchorsCommitVersion | closeTxVersionMask,
},
}
for _, tc := range cases {
gotVersionByte := tc.version.Encode(tc.hasCloseTx)
require.Equal(t, tc.versionByte, gotVersionByte)
gotVersion, gotHasCloseTx := DecodeVersion(tc.versionByte)
require.Equal(t, tc.version, gotVersion)
require.Equal(t, tc.hasCloseTx, gotHasCloseTx)
}
}
var sampleCommitTx = &wire.MsgTx{
TxIn: []*wire.TxIn{
{PreviousOutPoint: wire.OutPoint{Hash: [32]byte{1}}},
},
TxOut: []*wire.TxOut{
{Value: 1e8, PkScript: []byte("1")},
{Value: 2e8, PkScript: []byte("2")},
},
}
// TestSinglePackUnpack tests that we're able to unpack a previously packed
// channel backup.
func TestSinglePackUnpack(t *testing.T) {
@ -319,9 +211,7 @@ func TestSinglePackUnpack(t *testing.T) {
channel, err := genRandomOpenChannelShell()
require.NoError(t, err, "unable to gen open channel")
singleChanBackup := NewSingle(
channel, []net.Addr{addr1, addr2, addr3, addr4},
)
singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2})
keyRing := &lnencrypt.MockKeyRing{}
@ -330,9 +220,6 @@ func TestSinglePackUnpack(t *testing.T) {
// decode/encode the final SCB.
version SingleBackupVersion
// closeTxInputs is the data needed to produce a force close tx.
closeTxInputs fn.Option[CloseTxInputs]
// valid tests us if this test case should pass or not.
valid bool
}{
@ -363,111 +250,16 @@ func TestSinglePackUnpack(t *testing.T) {
valid: true,
},
// The new taproot channel version should
// pack/unpack with no problem.
{
version: SimpleTaprootVersion,
valid: true,
},
// The new tapscript root channel version should pack/unpack
// with no problem.
{
version: TapscriptRootVersion,
valid: true,
},
// A non-default version, atm this should result in a failure.
{
version: 99,
valid: false,
},
// Versions with CloseTxInputs.
{
version: DefaultSingleVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
}),
valid: true,
},
{
version: TweaklessCommitVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
}),
valid: true,
},
{
version: AnchorsCommitVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
}),
valid: true,
},
{
version: ScriptEnforcedLeaseVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
}),
valid: true,
},
{
version: SimpleTaprootVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
CommitHeight: 42,
}),
valid: true,
},
{
version: TapscriptRootVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
CommitHeight: 42,
TapscriptRoot: fn.Some(chainhash.Hash{1}),
}),
valid: true,
},
{
version: 99,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
}),
valid: false,
},
{
version: 99,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
CommitHeight: 42,
}),
valid: false,
},
{
version: TapscriptRootVersion,
closeTxInputs: fn.Some(CloseTxInputs{
CommitTx: sampleCommitTx,
CommitSig: []byte("signature"),
CommitHeight: 42,
// TapscriptRoot is not filled.
}),
valid: false,
},
}
for i, versionCase := range versionTestCases {
// First, we'll re-assign SCB version to what was indicated in
// the test case.
singleChanBackup.Version = versionCase.version
singleChanBackup.CloseTxInputs = versionCase.closeTxInputs
var b bytes.Buffer
@ -646,9 +438,7 @@ func TestSingleUnconfirmedChannel(t *testing.T) {
channel.ShortChannelID.BlockHeight = 0
channel.FundingBroadcastHeight = fundingBroadcastHeight
singleChanBackup := NewSingle(
channel, []net.Addr{addr1, addr2, addr3, addr4},
)
singleChanBackup := NewSingle(channel, []net.Addr{addr1, addr2})
keyRing := &lnencrypt.MockKeyRing{}
// Pack it and then unpack it again to make sure everything is written

View File

@ -1,7 +1,7 @@
package chanfitness
import (
"github.com/btcsuite/btclog/v2"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/build"
)

View File

@ -2,13 +2,24 @@ package lnd
import (
"fmt"
"net"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/chanbackup"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channelnotifier"
)
// addrSource is an interface that allow us to get the addresses for a target
// node. We'll need this in order to be able to properly proxy the
// notifications to create SCBs.
type addrSource interface {
// AddrsForNode returns all known addresses for the target node public
// key.
AddrsForNode(nodePub *btcec.PublicKey) ([]net.Addr, error)
}
// channelNotifier is an implementation of the chanbackup.ChannelNotifier
// interface using the existing channelnotifier.ChannelNotifier struct. This
// implementation allows us to satisfy all the dependencies of the
@ -21,7 +32,7 @@ type channelNotifier struct {
// addrs is an implementation of the addrSource interface that allows
// us to get the latest set of addresses for a given node. We'll need
// this to be able to create an SCB for new channels.
addrs channeldb.AddrSource
addrs addrSource
}
// SubscribeChans requests a new channel subscription relative to the initial
@ -45,7 +56,7 @@ func (c *channelNotifier) SubscribeChans(startingChans map[wire.OutPoint]struct{
// chanUpdates channel to inform subscribers about new pending or
// confirmed channels.
sendChanOpenUpdate := func(newOrPendingChan *channeldb.OpenChannel) {
_, nodeAddrs, err := c.addrs.AddrsForNode(
nodeAddrs, err := c.addrs.AddrsForNode(
newOrPendingChan.IdentityPub,
)
if err != nil {

View File

@ -1,4 +1,4 @@
package graphdb
package channeldb
import (
"encoding/binary"
@ -7,7 +7,6 @@ import (
"io"
"net"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/tor"
)
@ -27,10 +26,6 @@ const (
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
v3OnionAddr addressType = 3
// opaqueAddrs denotes an address (or a set of addresses) that LND was
// not able to parse since LND is not yet aware of the address type.
opaqueAddrs addressType = 4
)
// encodeTCPAddr serializes a TCP address into its compact raw bytes
@ -126,31 +121,10 @@ func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
return nil
}
// encodeOpaqueAddrs serializes the lnwire.OpaqueAddrs type to a raw set of
// bytes that we will persist.
func encodeOpaqueAddrs(w io.Writer, addr *lnwire.OpaqueAddrs) error {
// Write the type byte.
if _, err := w.Write([]byte{byte(opaqueAddrs)}); err != nil {
return err
}
// Write the length of the payload.
var l [2]byte
binary.BigEndian.PutUint16(l[:], uint16(len(addr.Payload)))
if _, err := w.Write(l[:]); err != nil {
return err
}
// Write the payload.
_, err := w.Write(addr.Payload)
return err
}
// DeserializeAddr reads the serialized raw representation of an address and
// deserializeAddr reads the serialized raw representation of an address and
// deserializes it into the actual address. This allows us to avoid address
// resolution within the channeldb package.
func DeserializeAddr(r io.Reader) (net.Addr, error) {
func deserializeAddr(r io.Reader) (net.Addr, error) {
var addrType [1]byte
if _, err := r.Read(addrType[:]); err != nil {
return nil, err
@ -173,7 +147,6 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
IP: net.IP(ip[:]),
Port: int(binary.BigEndian.Uint16(port[:])),
}
case tcp6Addr:
var ip [16]byte
if _, err := r.Read(ip[:]); err != nil {
@ -189,7 +162,6 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
IP: net.IP(ip[:]),
Port: int(binary.BigEndian.Uint16(port[:])),
}
case v2OnionAddr:
var h [tor.V2DecodedLen]byte
if _, err := r.Read(h[:]); err != nil {
@ -209,7 +181,6 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
OnionService: onionService,
Port: port,
}
case v3OnionAddr:
var h [tor.V3DecodedLen]byte
if _, err := r.Read(h[:]); err != nil {
@ -229,24 +200,6 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
OnionService: onionService,
Port: port,
}
case opaqueAddrs:
// Read the length of the payload.
var l [2]byte
if _, err := r.Read(l[:]); err != nil {
return nil, err
}
// Read the payload.
payload := make([]byte, binary.BigEndian.Uint16(l[:]))
if _, err := r.Read(payload); err != nil {
return nil, err
}
address = &lnwire.OpaqueAddrs{
Payload: payload,
}
default:
return nil, ErrUnknownAddressType
}
@ -254,16 +207,14 @@ func DeserializeAddr(r io.Reader) (net.Addr, error) {
return address, nil
}
// SerializeAddr serializes an address into its raw bytes representation so that
// serializeAddr serializes an address into its raw bytes representation so that
// it can be deserialized without requiring address resolution.
func SerializeAddr(w io.Writer, address net.Addr) error {
func serializeAddr(w io.Writer, address net.Addr) error {
switch addr := address.(type) {
case *net.TCPAddr:
return encodeTCPAddr(w, addr)
case *tor.OnionAddr:
return encodeOnionAddr(w, addr)
case *lnwire.OpaqueAddrs:
return encodeOpaqueAddrs(w, addr)
default:
return ErrUnknownAddressType
}

View File

@ -1,83 +0,0 @@
package channeldb
import (
"errors"
"net"
"github.com/btcsuite/btcd/btcec/v2"
)
// AddrSource is an interface that allow us to get the addresses for a target
// node. It may combine the results of multiple address sources.
type AddrSource interface {
// AddrsForNode returns all known addresses for the target node public
// key. The returned boolean must indicate if the given node is unknown
// to the backing source.
AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error)
}
// multiAddrSource is an implementation of AddrSource which gathers all the
// known addresses for a given node from multiple backends and de-duplicates the
// results.
type multiAddrSource struct {
sources []AddrSource
}
// NewMultiAddrSource constructs a new AddrSource which will query all the
// provided sources for a node's addresses and will then de-duplicate the
// results.
func NewMultiAddrSource(sources ...AddrSource) AddrSource {
return &multiAddrSource{
sources: sources,
}
}
// AddrsForNode returns all known addresses for the target node public key. It
// queries all the address sources provided and de-duplicates the results. The
// returned boolean is false only if none of the backing sources know of the
// node.
//
// NOTE: this implements the AddrSource interface.
func (c *multiAddrSource) AddrsForNode(nodePub *btcec.PublicKey) (bool,
[]net.Addr, error) {
if len(c.sources) == 0 {
return false, nil, errors.New("no address sources")
}
// The multiple address sources will likely contain duplicate addresses,
// so we use a map here to de-dup them.
dedupedAddrs := make(map[string]net.Addr)
// known will be set to true if any backing source is aware of the node.
var known bool
// Iterate over all the address sources and query each one for the
// addresses it has for the node in question.
for _, src := range c.sources {
isKnown, addrs, err := src.AddrsForNode(nodePub)
if err != nil {
return false, nil, err
}
if isKnown {
known = true
}
for _, addr := range addrs {
dedupedAddrs[addr.String()] = addr
}
}
// Convert the map into a list we can return.
addrs := make([]net.Addr, 0, len(dedupedAddrs))
for _, addr := range dedupedAddrs {
addrs = append(addrs, addr)
}
return known, addrs, nil
}
// A compile-time check to ensure that multiAddrSource implements the AddrSource
// interface.
var _ AddrSource = (*multiAddrSource)(nil)

View File

@ -1,149 +0,0 @@
package channeldb
import (
"net"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
var (
addr1 = &net.TCPAddr{IP: (net.IP)([]byte{0x1}), Port: 1}
addr2 = &net.TCPAddr{IP: (net.IP)([]byte{0x2}), Port: 2}
addr3 = &net.TCPAddr{IP: (net.IP)([]byte{0x3}), Port: 3}
)
// TestMultiAddrSource tests that the multiAddrSource correctly merges and
// deduplicates the results of a set of AddrSource implementations.
func TestMultiAddrSource(t *testing.T) {
t.Parallel()
var pk1 = newTestPubKey(t)
t.Run("both sources have results", func(t *testing.T) {
t.Parallel()
var (
src1 = newMockAddrSource(t)
src2 = newMockAddrSource(t)
)
t.Cleanup(func() {
src1.AssertExpectations(t)
src2.AssertExpectations(t)
})
// Let source 1 know of 2 addresses (addr 1 and 2) for node 1.
src1.On("AddrsForNode", pk1).Return(
true, []net.Addr{addr1, addr2}, nil,
).Once()
// Let source 2 know of 2 addresses (addr 2 and 3) for node 1.
src2.On("AddrsForNode", pk1).Return(
true, []net.Addr{addr2, addr3}, nil,
[]net.Addr{addr2, addr3}, nil,
).Once()
// Create a multi-addr source that consists of both source 1
// and 2.
multiSrc := NewMultiAddrSource(src1, src2)
// Query it for the addresses known for node 1. The results
// should contain addr 1, 2 and 3.
known, addrs, err := multiSrc.AddrsForNode(pk1)
require.NoError(t, err)
require.True(t, known)
require.ElementsMatch(t, addrs, []net.Addr{addr1, addr2, addr3})
})
t.Run("only once source has results", func(t *testing.T) {
t.Parallel()
var (
src1 = newMockAddrSource(t)
src2 = newMockAddrSource(t)
)
t.Cleanup(func() {
src1.AssertExpectations(t)
src2.AssertExpectations(t)
})
// Let source 1 know of address 1 for node 1.
src1.On("AddrsForNode", pk1).Return(
true, []net.Addr{addr1}, nil,
).Once()
src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
// Create a multi-addr source that consists of both source 1
// and 2.
multiSrc := NewMultiAddrSource(src1, src2)
// Query it for the addresses known for node 1. The results
// should contain addr 1.
known, addrs, err := multiSrc.AddrsForNode(pk1)
require.NoError(t, err)
require.True(t, known)
require.ElementsMatch(t, addrs, []net.Addr{addr1})
})
t.Run("unknown address", func(t *testing.T) {
t.Parallel()
var (
src1 = newMockAddrSource(t)
src2 = newMockAddrSource(t)
)
t.Cleanup(func() {
src1.AssertExpectations(t)
src2.AssertExpectations(t)
})
// Create a multi-addr source that consists of both source 1
// and 2. Neither source known of node 1.
multiSrc := NewMultiAddrSource(src1, src2)
src1.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
src2.On("AddrsForNode", pk1).Return(false, nil, nil).Once()
// Query it for the addresses known for node 1. It should return
// false to indicate that the node is unknown to all backing
// sources.
known, addrs, err := multiSrc.AddrsForNode(pk1)
require.NoError(t, err)
require.False(t, known)
require.Empty(t, addrs)
})
}
type mockAddrSource struct {
t *testing.T
mock.Mock
}
var _ AddrSource = (*mockAddrSource)(nil)
func newMockAddrSource(t *testing.T) *mockAddrSource {
return &mockAddrSource{t: t}
}
func (m *mockAddrSource) AddrsForNode(pub *btcec.PublicKey) (bool, []net.Addr,
error) {
args := m.Called(pub)
if args.Get(1) == nil {
return args.Bool(0), nil, args.Error(2)
}
addrs, ok := args.Get(1).([]net.Addr)
require.True(m.t, ok)
return args.Bool(0), addrs, args.Error(2)
}
func newTestPubKey(t *testing.T) *btcec.PublicKey {
priv, err := btcec.NewPrivateKey()
require.NoError(t, err)
return priv.PubKey()
}

View File

@ -1,4 +1,4 @@
package graphdb
package channeldb
import (
"bytes"
@ -117,7 +117,7 @@ func TestAddrSerialization(t *testing.T) {
var b bytes.Buffer
for _, test := range addrTests {
err := SerializeAddr(&b, test.expAddr)
err := serializeAddr(&b, test.expAddr)
switch {
case err == nil && test.serErr != "":
t.Fatalf("expected serialization err for addr %v",
@ -136,7 +136,7 @@ func TestAddrSerialization(t *testing.T) {
continue
}
addr, err := DeserializeAddr(&b)
addr, err := deserializeAddr(&b)
if err != nil {
t.Fatalf("unable to deserialize address: %v", err)
}

View File

@ -19,9 +19,8 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcwallet/walletdb"
"github.com/lightningnetwork/lnd/fn/v2"
graphdb "github.com/lightningnetwork/lnd/graph/db"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/htlcswitch/hop"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
@ -1331,7 +1330,7 @@ func fetchChanBucket(tx kvdb.RTx, nodeKey *btcec.PublicKey,
// With the bucket for the node and chain fetched, we can now go down
// another level, for this channel itself.
var chanPointBuf bytes.Buffer
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
return nil, err
}
chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
@ -1378,7 +1377,7 @@ func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
// With the bucket for the node and chain fetched, we can now go down
// another level, for this channel itself.
var chanPointBuf bytes.Buffer
if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
return nil, err
}
chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
@ -1423,8 +1422,7 @@ func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
}
var chanPointBuf bytes.Buffer
err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
if err != nil {
if err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint); err != nil {
return err
}
@ -1691,7 +1689,7 @@ var (
// DeriveMusig2Shachain derives a shachain producer for the taproot channel
// from normal shachain revocation root.
func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:ll
func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:lll
// In order to obtain the revocation root hash to create the taproot
// revocation, we'll encode the producer into a buffer, then use that
// to derive the shachain root needed.
@ -3146,7 +3144,7 @@ func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
return nil, err
}
return cd, nil
return cd, err
}
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
@ -3824,7 +3822,7 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
}
var chanPointBuf bytes.Buffer
err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint)
if err != nil {
return err
}
@ -4104,34 +4102,6 @@ func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
return c.ThawHeight, nil
}
// DeriveHeightHint derives the block height for the channel opening.
func (c *OpenChannel) DeriveHeightHint() uint32 {
// As a height hint, we'll try to use the opening height, but if the
// channel isn't yet open, then we'll use the height it was broadcast
// at. This may be an unconfirmed zero-conf channel.
heightHint := c.ShortChanID().BlockHeight
if heightHint == 0 {
heightHint = c.BroadcastHeight()
}
// Since no zero-conf state is stored in a channel backup, the below
// logic will not be triggered for restored, zero-conf channels. Set
// the height hint for zero-conf channels.
if c.IsZeroConf() {
if c.ZeroConfConfirmed() {
// If the zero-conf channel is confirmed, we'll use the
// confirmed SCID's block height.
heightHint = c.ZeroConfRealScid().BlockHeight
} else {
// The zero-conf channel is unconfirmed. We'll need to
// use the FundingBroadcastHeight.
heightHint = c.BroadcastHeight()
}
}
return heightHint
}
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
summary *ChannelCloseSummary, lastChanState *OpenChannel) error {

View File

@ -1,4 +1,4 @@
package graphdb
package channeldb
// channelCache is an in-memory cache used to improve the performance of
// ChanUpdatesInHorizon. It caches the chan info and edge policies for a

View File

@ -1,10 +1,10 @@
package graphdb
package channeldb
import (
"reflect"
"testing"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/channeldb/models"
)
// TestChannelCache checks the behavior of the channelCache with respect to

View File

@ -2,7 +2,6 @@ package channeldb
import (
"bytes"
"encoding/hex"
"math/rand"
"net"
"reflect"
@ -11,22 +10,20 @@ import (
"testing"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
_ "github.com/btcsuite/btcwallet/walletdb/bdb"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/graph/db/models"
"github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnmock"
"github.com/lightningnetwork/lnd/lntest/channels"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/shachain"
"github.com/lightningnetwork/lnd/tlv"
"github.com/stretchr/testify/require"
@ -46,20 +43,8 @@ var (
}
privKey, pubKey = btcec.PrivKeyFromBytes(key[:])
testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571319d18e" +
"949ddfa2965fb6caa1bf0314f882d7")
testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a88121167221b67" +
"00d72a0ead154c03be696a292d24ae")
testRScalar = new(btcec.ModNScalar)
testSScalar = new(btcec.ModNScalar)
_ = testRScalar.SetByteSlice(testRBytes)
_ = testSScalar.SetByteSlice(testSBytes)
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
wireSig, _ = lnwire.NewSigFromSignature(testSig)
testPub = route.Vertex{2, 202, 4}
testClock = clock.NewTestClock(testNow)
// defaultPendingHeight is the default height at which we set
@ -107,10 +92,6 @@ type testChannelParams struct {
// openChannel is set to true if the channel should be fully marked as
// open if this is false, the channel will be left in pending state.
openChannel bool
// closedChannel is set to true if the channel should be marked as
// closed after opening it.
closedChannel bool
}
// testChannelOption is a functional option which can be used to alter the
@ -133,21 +114,6 @@ func openChannelOption() testChannelOption {
}
}
// closedChannelOption is an option which can be used to create a test channel
// that is closed.
func closedChannelOption() testChannelOption {
return func(params *testChannelParams) {
params.closedChannel = true
}
}
// pubKeyOption is an option which can be used to set the remote's pubkey.
func pubKeyOption(pubKey *btcec.PublicKey) testChannelOption {
return func(params *testChannelParams) {
params.channel.IdentityPub = pubKey
}
}
// localHtlcsOption is an option which allows setting of htlcs on the local
// commitment.
func localHtlcsOption(htlcs []HTLC) testChannelOption {
@ -250,17 +216,6 @@ func createTestChannel(t *testing.T, cdb *ChannelStateDB,
err = params.channel.MarkAsOpen(params.channel.ShortChannelID)
require.NoError(t, err, "unable to mark channel open")
if params.closedChannel {
// Set the other public keys so that serialization doesn't
// panic.
err = params.channel.CloseChannel(&ChannelCloseSummary{
RemotePub: params.channel.IdentityPub,
RemoteCurrentRevocation: params.channel.IdentityPub,
RemoteNextRevocation: params.channel.IdentityPub,
})
require.NoError(t, err, "unable to close channel")
}
return params.channel
}

Some files were not shown because too many files have changed in this diff Show More