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.
This commit is contained in:
eugene
2022-04-04 16:47:05 -04:00
parent 13c15e8038
commit 1aa9626606
19 changed files with 3883 additions and 2697 deletions

View File

@ -1173,6 +1173,46 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
return nil, err
}
// Wrap the DeleteChannelEdges method so that the funding manager can
// use it without depending on several layers of indirection.
deleteAliasEdge := func(scid lnwire.ShortChannelID) (
*channeldb.ChannelEdgePolicy, error) {
info, e1, e2, err := s.graphDB.FetchChannelEdgesByID(
scid.ToUint64(),
)
if err == channeldb.ErrEdgeNotFound {
// This is unlikely but there is a slim chance of this
// being hit if lnd was killed via SIGKILL and the
// funding manager was stepping through the delete
// alias edge logic.
return nil, nil
} else if err != nil {
return nil, err
}
// Grab our key to find our policy.
var ourKey [33]byte
copy(ourKey[:], nodeKeyDesc.PubKey.SerializeCompressed())
var ourPolicy *channeldb.ChannelEdgePolicy
if info != nil && info.NodeKey1Bytes == ourKey {
ourPolicy = e1
} else {
ourPolicy = e2
}
if ourPolicy == nil {
// Something is wrong, so return an error.
return nil, fmt.Errorf("we don't have an edge")
}
err = s.graphDB.DeleteChannelEdges(
false, false, scid.ToUint64(),
)
return ourPolicy, err
}
s.fundingMgr, err = funding.NewFundingManager(funding.Config{
NoWumboChans: !cfg.ProtocolOptions.Wumbo(),
IDKey: nodeKeyDesc.PubKey,
@ -1191,15 +1231,16 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
SendAnnouncement: s.authGossiper.ProcessLocalAnnouncement,
NotifyWhenOnline: s.NotifyWhenOnline,
TempChanIDSeed: chanIDSeed,
FindChannel: func(chanID lnwire.ChannelID) (
*channeldb.OpenChannel, error) {
FindChannel: func(node *btcec.PublicKey,
chanID lnwire.ChannelID) (*channeldb.OpenChannel,
error) {
dbChannels, err := s.chanStateDB.FetchAllChannels()
nodeChans, err := s.chanStateDB.FetchOpenChannels(node)
if err != nil {
return nil, err
}
for _, channel := range dbChannels {
for _, channel := range nodeChans {
if chanID.IsChanPoint(&channel.FundingOutpoint) {
return channel, nil
}
@ -1357,6 +1398,8 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
RegisteredChains: cfg.registeredChains,
MaxAnchorsCommitFeeRate: chainfee.SatPerKVByte(
s.cfg.MaxCommitFeeRateAnchors * 1000).FeePerKWeight(),
DeleteAliasEdge: deleteAliasEdge,
AliasManager: s.aliasMgr,
})
if err != nil {
return nil, err