Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynComms [3/n]: Implement Dynamic Commitments Negotiation #8756

Draft
wants to merge 52 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
94acbe9
fn: add fundamental functional primitives
ProofOfKeags Apr 12, 2024
5902aa5
fn: add concurrent map operation for slices
ProofOfKeags Apr 12, 2024
c3603cc
fn: add FindIdx function
ProofOfKeags Apr 15, 2024
1dd56f1
fn: fix and finish the either API
ProofOfKeags Apr 17, 2024
c4df2f1
fn: reimplement internals of either, add tests
ProofOfKeags Apr 22, 2024
9c30bce
fn: add curried (in)equality functions
ProofOfKeags Apr 27, 2024
fb1437c
fn: add Elem function for set membership
ProofOfKeags Apr 27, 2024
364d79e
fn: add generic version of List
ProofOfKeags Apr 30, 2024
fa2e25d
fn: remove lru dependency
ProofOfKeags Jul 10, 2024
eaa5e4a
fn: remove redundant Reduce function
ProofOfKeags Jul 10, 2024
550e19a
lnwire: add wire type for stfu
ProofOfKeags Dec 7, 2023
7b39cee
lnwire: add Stfu to LinkUpdater interface
ProofOfKeags Dec 11, 2023
7dc83b3
peer: add message summary for Stfu
ProofOfKeags Mar 12, 2024
1f41b97
htlcswitch: define state machine for quiescence
ProofOfKeags Dec 8, 2023
6d54abf
htlcswitch+lnwallet: rename PendingLocalUpdateCount
ProofOfKeags Dec 12, 2023
a8a4b54
lnwallet: complete pending update queries API for LightningChannel
ProofOfKeags Dec 12, 2023
39bf785
htlcswitch: implement stfu response
ProofOfKeags Dec 12, 2023
9957f2c
htlcswitch: bounce packets when quiescent
ProofOfKeags Dec 12, 2023
fa9fff4
htlcswitch: drop connection if link updates after stfu
ProofOfKeags Dec 12, 2023
9388d47
lnwire: signal that we support quiescence
ProofOfKeags Dec 12, 2023
a0140ab
lnrpc add new RPC 'Quiesce' to protobuf definitions
ProofOfKeags Mar 12, 2024
4c930f8
lnd: implement new Quiesce RPC with link operation stub
ProofOfKeags Mar 12, 2024
bf78695
htlcswitch: add link operation for initiating quiescence
ProofOfKeags Mar 12, 2024
25242c4
lnd: finish Quiesce implementation using new link op
ProofOfKeags Mar 12, 2024
73a0de2
htlcswitch: implement InitStfu link operation
ProofOfKeags Mar 12, 2024
92e60f8
itest+lntest: add itest for Quiesce RPC method
ProofOfKeags Mar 12, 2024
259dcbb
htlcswitch: replace errors package implementation
ProofOfKeags Apr 6, 2024
68f4edf
htlcswitch: extract error handling for syncChanStates
ProofOfKeags Apr 5, 2024
aef634f
htlcswitch: defer processRemoteAdds when quiescent
ProofOfKeags Apr 9, 2024
57519bb
htlcswitch: rename for test parameters for accuracy
ProofOfKeags Apr 9, 2024
9345589
htlcswitch: add test for deferred processing remote adds when quiescent
ProofOfKeags Apr 10, 2024
27b754c
lnwallet: move PaymentDescriptor definition to its own file
ProofOfKeags Apr 30, 2024
9f4f602
lnwallet: move updateLog to its own file.
ProofOfKeags Jun 6, 2024
769791f
lnwallet: move commitChain to its own file.
ProofOfKeags Jun 6, 2024
6073ec1
lntypes: Add a ChannelParty type.
ProofOfKeags Apr 23, 2024
bc1f8ed
multi: refactor to replace select uses of bool with `ChannelParty`
ProofOfKeags Apr 24, 2024
39d4abb
lnwallet: refactor channel to use new typed List
ProofOfKeags Apr 30, 2024
3079b9b
multi: break ChannelConstraints into two sub-structures
ProofOfKeags May 9, 2024
7cd95b5
lnwallet: remove unnecessary duplicate definition
ProofOfKeags May 15, 2024
ffeacd4
lnwallet: remove unused parameters in LightningChannel methods
ProofOfKeags May 15, 2024
28c8271
lnwallet: update updateLog.modifiedHtlcs to use fn.Set
ProofOfKeags May 24, 2024
f9ed02a
lntypes: Add Dual[A] primitive type
ProofOfKeags May 22, 2024
a6bd8a5
lnwallet: add ChannelID method to LightningChannel
ProofOfKeags Jun 6, 2024
629081c
lnwallet: track ChannelID on PaymentDescriptor
ProofOfKeags Jun 6, 2024
2f1b33b
htlcswitch+lnwallet: quarantine paymentDescriptor to lnwallet
ProofOfKeags Jun 14, 2024
447443c
lnwallet: fix OnionBlob to 1366 bytes
ProofOfKeags Jun 15, 2024
aeb0bcc
lnwallet: add function to convert paymentDescriptor to LogUpdate
ProofOfKeags Jun 15, 2024
8113434
lnwallet: remove unnecessary chanID argument form unsignedLocalUpdates
ProofOfKeags Jun 15, 2024
5fe2f5a
lnwire: remove Initiator field from DynPropose
ProofOfKeags Apr 17, 2024
e900725
lnwire: implement LinkUpdater for DynPropose
ProofOfKeags Apr 18, 2024
091f283
htlcswitch: create dynamic commit negotiation state machine api
ProofOfKeags Apr 17, 2024
9a13916
wip
ProofOfKeags May 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 62 additions & 57 deletions chanbackup/single_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,64 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {

chanType := channeldb.ChannelType(rand.Intn(8))

localCfg := channeldb.ChannelConfig{
ChannelStateSpaceBounds: channeldb.ChannelStateSpaceBounds{},
CommitmentRenderingParams: channeldb.CommitmentRenderingParams{
CsvDelay: uint16(rand.Int63()),
},
MultiSigKey: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
RevocationBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
PaymentBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
DelayBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
HtlcBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
}

remoteCfg := channeldb.ChannelConfig{
CommitmentRenderingParams: channeldb.CommitmentRenderingParams{
CsvDelay: uint16(rand.Int63()),
},
MultiSigKey: keychain.KeyDescriptor{
PubKey: pub,
},
RevocationBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
PaymentBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
DelayBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
HtlcBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
}

return &channeldb.OpenChannel{
ChainHash: chainHash,
ChanType: chanType,
Expand All @@ -134,63 +192,10 @@ func genRandomOpenChannelShell() (*channeldb.OpenChannel, error) {
ShortChannelID: lnwire.NewShortChanIDFromInt(
uint64(rand.Int63()),
),
ThawHeight: rand.Uint32(),
IdentityPub: pub,
LocalChanCfg: channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
CsvDelay: uint16(rand.Int63()),
},
MultiSigKey: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
RevocationBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
PaymentBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
DelayBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
HtlcBasePoint: keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(rand.Int63()),
Index: uint32(rand.Int63()),
},
},
},
RemoteChanCfg: channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{
CsvDelay: uint16(rand.Int63()),
},
MultiSigKey: keychain.KeyDescriptor{
PubKey: pub,
},
RevocationBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
PaymentBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
DelayBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
HtlcBasePoint: keychain.KeyDescriptor{
PubKey: pub,
},
},
ThawHeight: rand.Uint32(),
IdentityPub: pub,
LocalChanCfg: localCfg,
RemoteChanCfg: remoteCfg,
RevocationProducer: shaChainProducer,
}, nil
}
Expand Down
63 changes: 41 additions & 22 deletions channeldb/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/shachain"
"github.com/lightningnetwork/lnd/tlv"
Expand Down Expand Up @@ -394,19 +395,11 @@ func (c ChannelType) IsTaproot() bool {
return c&SimpleTaprootFeatureBit == SimpleTaprootFeatureBit
}

// ChannelConstraints represents a set of constraints meant to allow a node to
// limit their exposure, enact flow control and ensure that all HTLCs are
// economically relevant. This struct will be mirrored for both sides of the
// channel, as each side will enforce various constraints that MUST be adhered
// to for the life time of the channel. The parameters for each of these
// constraints are static for the duration of the channel, meaning the channel
// must be torn down for them to change.
type ChannelConstraints struct {
// DustLimit is the threshold (in satoshis) below which any outputs
// should be trimmed. When an output is trimmed, it isn't materialized
// as an actual output, but is instead burned to miner's fees.
DustLimit btcutil.Amount

// ChannelStateSpaceBounds are the parameters from OpenChannel and AcceptChannel
// that are responsible for providing bounds on the state space of the abstract
// channel state. These values must be remembered for normal channl operation
// but they do not impact how we compute the commitment transactions themselves.
type ChannelStateSpaceBounds struct {
// ChanReserve is an absolute reservation on the channel for the
// owner of this set of constraints. This means that the current
// settled balance for this node CANNOT dip below the reservation
Expand All @@ -432,6 +425,19 @@ type ChannelConstraints struct {
// acted upon in the case of a unilateral channel closure or a contract
// breach.
MaxAcceptedHtlcs uint16
}

// CommitmentRenderingParams are the parameters from OpenChannel and
// AcceptChannel that are required to render an abstract channel state to a
// concrete commitment transaction. These values are necessary to (re)compute
// the commitment transaction. We treat these differently than the state space
// bounds because their history needs to be stored in order to properly handle
// chain resolution.
type CommitmentRenderingParams struct {
// DustLimit is the threshold (in satoshis) below which any outputs
// should be trimmed. When an output is trimmed, it isn't materialized
// as an actual output, but is instead burned to miner's fees.
DustLimit btcutil.Amount

// CsvDelay is the relative time lock delay expressed in blocks. Any
// settled outputs that pay to the owner of this channel configuration
Expand All @@ -447,12 +453,17 @@ type ChannelConstraints struct {
// nature of HTLC's allotted, the keys to be used for delivery, and relative
// time lock parameters.
type ChannelConfig struct {
// ChannelConstraints is the set of constraints that must be upheld for
// the duration of the channel for the owner of this channel
// ChannelStateSpaceBounds is the set of constraints that must be
// upheld for the duration of the channel for the owner of this channel
// configuration. Constraints govern a number of flow control related
// parameters, also including the smallest HTLC that will be accepted
// by a participant.
ChannelConstraints
ChannelStateSpaceBounds

// CommitmentRenderingParams is an embedding of the parameters
// required to render an abstract channel state into a concrete
// commitment transaction.
CommitmentRenderingParams

// MultiSigKey is the key to be used within the 2-of-2 output script
// for the owner of this channel config.
Expand Down Expand Up @@ -1690,11 +1701,11 @@ func (c *OpenChannel) isBorked(chanBucket kvdb.RBucket) (bool, error) {
// republish this tx at startup to ensure propagation, and we should still
// handle the case where a different tx actually hits the chain.
func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx,
locallyInitiated bool) error {
closer lntypes.ChannelParty) error {

return c.markBroadcasted(
ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
locallyInitiated,
closer,
)
}

Expand All @@ -1706,11 +1717,11 @@ func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx,
// ensure propagation, and we should still handle the case where a different tx
// actually hits the chain.
func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
locallyInitiated bool) error {
closer lntypes.ChannelParty) error {

return c.markBroadcasted(
ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
locallyInitiated,
closer,
)
}

Expand All @@ -1719,7 +1730,7 @@ func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
// which should specify either a coop or force close. It adds a status which
// indicates the party that initiated the channel close.
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
closeTx *wire.MsgTx, locallyInitiated bool) error {
closeTx *wire.MsgTx, closer lntypes.ChannelParty) error {

c.Lock()
defer c.Unlock()
Expand All @@ -1741,7 +1752,7 @@ func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
// Add the initiator status to the status provided. These statuses are
// set in addition to the broadcast status so that we do not need to
// migrate the original logic which does not store initiator.
if locallyInitiated {
if closer == lntypes.Local {
status |= ChanStatusLocalCloseInitiator
} else {
status |= ChanStatusRemoteCloseInitiator
Expand Down Expand Up @@ -4486,6 +4497,14 @@ func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
}
}

func (i ShutdownInfo) Closer() lntypes.ChannelParty {
if i.LocalInitiator.Val {
return lntypes.Local
}

return lntypes.Remote
}

// encode serialises the ShutdownInfo to the given io.Writer.
func (s *ShutdownInfo) encode(w io.Writer) error {
records := []tlv.Record{
Expand Down
64 changes: 42 additions & 22 deletions channeldb/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"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/shachain"
"github.com/lightningnetwork/lnd/tlv"
Expand Down Expand Up @@ -234,15 +235,21 @@ func createTestChannelState(t *testing.T, cdb *ChannelStateDB) *OpenChannel {
}
}

localStateBounds := ChannelStateSpaceBounds{
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
ChanReserve: btcutil.Amount(rand.Int63()),
MinHTLC: lnwire.MilliSatoshi(rand.Int63()),
MaxAcceptedHtlcs: uint16(rand.Int31()),
}

localRenderingParams := CommitmentRenderingParams{
DustLimit: btcutil.Amount(rand.Int63()),
CsvDelay: uint16(rand.Int31()),
}

localCfg := ChannelConfig{
ChannelConstraints: ChannelConstraints{
DustLimit: btcutil.Amount(rand.Int63()),
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
ChanReserve: btcutil.Amount(rand.Int63()),
MinHTLC: lnwire.MilliSatoshi(rand.Int63()),
MaxAcceptedHtlcs: uint16(rand.Int31()),
CsvDelay: uint16(rand.Int31()),
},
ChannelStateSpaceBounds: localStateBounds,
CommitmentRenderingParams: localRenderingParams,
MultiSigKey: keychain.KeyDescriptor{
PubKey: privKey.PubKey(),
},
Expand All @@ -259,15 +266,22 @@ func createTestChannelState(t *testing.T, cdb *ChannelStateDB) *OpenChannel {
PubKey: privKey.PubKey(),
},
}

remoteStateBounds := ChannelStateSpaceBounds{
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
ChanReserve: btcutil.Amount(rand.Int63()),
MinHTLC: lnwire.MilliSatoshi(rand.Int63()),
MaxAcceptedHtlcs: uint16(rand.Int31()),
}

remoteRenderingParams := CommitmentRenderingParams{
DustLimit: btcutil.Amount(rand.Int63()),
CsvDelay: uint16(rand.Int31()),
}

remoteCfg := ChannelConfig{
ChannelConstraints: ChannelConstraints{
DustLimit: btcutil.Amount(rand.Int63()),
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
ChanReserve: btcutil.Amount(rand.Int63()),
MinHTLC: lnwire.MilliSatoshi(rand.Int63()),
MaxAcceptedHtlcs: uint16(rand.Int31()),
CsvDelay: uint16(rand.Int31()),
},
ChannelStateSpaceBounds: remoteStateBounds,
CommitmentRenderingParams: remoteRenderingParams,
MultiSigKey: keychain.KeyDescriptor{
PubKey: privKey.PubKey(),
KeyLocator: keychain.KeyLocator{
Expand Down Expand Up @@ -1084,13 +1098,17 @@ func TestFetchWaitingCloseChannels(t *testing.T) {
},
)

if err := channel.MarkCommitmentBroadcasted(closeTx, true); err != nil {
if err := channel.MarkCommitmentBroadcasted(
closeTx, lntypes.Local,
); err != nil {
t.Fatalf("unable to mark commitment broadcast: %v", err)
}

// Now try to marking a coop close with a nil tx. This should
// succeed, but it shouldn't exit when queried.
if err = channel.MarkCoopBroadcasted(nil, true); err != nil {
if err = channel.MarkCoopBroadcasted(
nil, lntypes.Local,
); err != nil {
t.Fatalf("unable to mark nil coop broadcast: %v", err)
}
_, err := channel.BroadcastedCooperative()
Expand All @@ -1102,7 +1120,9 @@ func TestFetchWaitingCloseChannels(t *testing.T) {
// it as coop closed. Later we will test that distinct
// transactions are returned for both coop and force closes.
closeTx.TxIn[0].PreviousOutPoint.Index ^= 1
if err := channel.MarkCoopBroadcasted(closeTx, true); err != nil {
if err := channel.MarkCoopBroadcasted(
closeTx, lntypes.Local,
); err != nil {
t.Fatalf("unable to mark coop broadcast: %v", err)
}
}
Expand Down Expand Up @@ -1324,7 +1344,7 @@ func TestCloseInitiator(t *testing.T) {
// by the local party.
updateChannel: func(c *OpenChannel) error {
return c.MarkCoopBroadcasted(
&wire.MsgTx{}, true,
&wire.MsgTx{}, lntypes.Local,
)
},
expectedStatuses: []ChannelStatus{
Expand All @@ -1338,7 +1358,7 @@ func TestCloseInitiator(t *testing.T) {
// by the remote party.
updateChannel: func(c *OpenChannel) error {
return c.MarkCoopBroadcasted(
&wire.MsgTx{}, false,
&wire.MsgTx{}, lntypes.Remote,
)
},
expectedStatuses: []ChannelStatus{
Expand All @@ -1352,7 +1372,7 @@ func TestCloseInitiator(t *testing.T) {
// local initiator.
updateChannel: func(c *OpenChannel) error {
return c.MarkCommitmentBroadcasted(
&wire.MsgTx{}, true,
&wire.MsgTx{}, lntypes.Local,
)
},
expectedStatuses: []ChannelStatus{
Expand Down
Loading
Loading