lnwallet: create CommitmentBuilder
We define a new struct CommitmentBuilder that will be used to craft the final commitment transaction based on the current active channel type.
This commit is contained in:
4 files changed
+58
-35
No files matched your search
+7
-7
@@ -1226,10 +1226,6 @@ type LightningChannel struct {
|
|||||||
// Capacity is the total capacity of this channel.
|
// Capacity is the total capacity of this channel.
|
||||||
Capacity btcutil.Amount
|
Capacity btcutil.Amount
|
||||||
|
|
||||||
// stateHintObfuscator is a 48-bit state hint that's used to obfuscate
|
|
||||||
// the current state number on the commitment transactions.
|
|
||||||
stateHintObfuscator [StateHintSize]byte
|
|
||||||
|
|
||||||
// currentHeight is the current height of our local commitment chain.
|
// currentHeight is the current height of our local commitment chain.
|
||||||
// This is also the same as the number of updates to the channel we've
|
// This is also the same as the number of updates to the channel we've
|
||||||
// accepted.
|
// accepted.
|
||||||
@@ -1247,6 +1243,8 @@ type LightningChannel struct {
|
|||||||
|
|
||||||
channelState *channeldb.OpenChannel
|
channelState *channeldb.OpenChannel
|
||||||
|
|
||||||
|
commitBuilder *CommitmentBuilder
|
||||||
|
|
||||||
// [local|remote]Log is a (mostly) append-only log storing all the HTLC
|
// [local|remote]Log is a (mostly) append-only log storing all the HTLC
|
||||||
// updates to this channel. The log is walked backwards as HTLC updates
|
// updates to this channel. The log is walked backwards as HTLC updates
|
||||||
// are applied in order to re-construct a commitment transaction from a
|
// are applied in order to re-construct a commitment transaction from a
|
||||||
@@ -1299,6 +1297,7 @@ func NewLightningChannel(signer input.Signer,
|
|||||||
remoteCommitChain: newCommitmentChain(),
|
remoteCommitChain: newCommitmentChain(),
|
||||||
localCommitChain: newCommitmentChain(),
|
localCommitChain: newCommitmentChain(),
|
||||||
channelState: state,
|
channelState: state,
|
||||||
|
commitBuilder: NewCommitmentBuilder(state),
|
||||||
localUpdateLog: localUpdateLog,
|
localUpdateLog: localUpdateLog,
|
||||||
remoteUpdateLog: remoteUpdateLog,
|
remoteUpdateLog: remoteUpdateLog,
|
||||||
ChanPoint: &state.FundingOutpoint,
|
ChanPoint: &state.FundingOutpoint,
|
||||||
@@ -1322,8 +1321,6 @@ func NewLightningChannel(signer input.Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.createStateHintObfuscator()
|
|
||||||
|
|
||||||
return lc, nil
|
return lc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2208,7 +2205,10 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actually generate unsigned commitment transaction for this view.
|
// Actually generate unsigned commitment transaction for this view.
|
||||||
if err := lc.createCommitmentTx(c, filteredHTLCView, keyRing); err != nil {
|
err := lc.commitBuilder.createCommitmentTx(
|
||||||
|
c, filteredHTLCView, keyRing,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-22
@@ -127,27 +127,48 @@ func DeriveCommitmentKeys(commitPoint *btcec.PublicKey,
|
|||||||
return keyRing
|
return keyRing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommitmentBuilder is a type that wraps the type of channel we are dealing
|
||||||
|
// with, and abstracts the various ways of constructing commitment
|
||||||
|
// transactions.
|
||||||
|
type CommitmentBuilder struct {
|
||||||
|
// chanState is the underlying channels's state struct, used to
|
||||||
|
// determine the type of channel we are dealing with, and relevant
|
||||||
|
// parameters.
|
||||||
|
chanState *channeldb.OpenChannel
|
||||||
|
|
||||||
|
// obfuscator is a 48-bit state hint that's used to obfuscate the
|
||||||
|
// current state number on the commitment transactions.
|
||||||
|
obfuscator [StateHintSize]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCommitmentBuilder creates a new CommitmentBuilder from chanState.
|
||||||
|
func NewCommitmentBuilder(chanState *channeldb.OpenChannel) *CommitmentBuilder {
|
||||||
|
return &CommitmentBuilder{
|
||||||
|
chanState: chanState,
|
||||||
|
obfuscator: createStateHintObfuscator(chanState),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// createStateHintObfuscator derives and assigns the state hint obfuscator for
|
// createStateHintObfuscator derives and assigns the state hint obfuscator for
|
||||||
// the channel, which is used to encode the commitment height in the sequence
|
// the channel, which is used to encode the commitment height in the sequence
|
||||||
// number of commitment transaction inputs.
|
// number of commitment transaction inputs.
|
||||||
func (lc *LightningChannel) createStateHintObfuscator() {
|
func createStateHintObfuscator(state *channeldb.OpenChannel) [StateHintSize]byte {
|
||||||
state := lc.channelState
|
|
||||||
if state.IsInitiator {
|
if state.IsInitiator {
|
||||||
lc.stateHintObfuscator = DeriveStateHintObfuscator(
|
return DeriveStateHintObfuscator(
|
||||||
state.LocalChanCfg.PaymentBasePoint.PubKey,
|
state.LocalChanCfg.PaymentBasePoint.PubKey,
|
||||||
state.RemoteChanCfg.PaymentBasePoint.PubKey,
|
state.RemoteChanCfg.PaymentBasePoint.PubKey,
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
lc.stateHintObfuscator = DeriveStateHintObfuscator(
|
|
||||||
state.RemoteChanCfg.PaymentBasePoint.PubKey,
|
|
||||||
state.LocalChanCfg.PaymentBasePoint.PubKey,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return DeriveStateHintObfuscator(
|
||||||
|
state.RemoteChanCfg.PaymentBasePoint.PubKey,
|
||||||
|
state.LocalChanCfg.PaymentBasePoint.PubKey,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// createCommitmentTx generates the unsigned commitment transaction for a
|
// createCommitmentTx generates the unsigned commitment transaction for a
|
||||||
// commitment view and assigns to txn field.
|
// commitment view and assigns to txn field.
|
||||||
func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
func (cb *CommitmentBuilder) createCommitmentTx(c *commitment,
|
||||||
filteredHTLCView *htlcView, keyRing *CommitmentKeyRing) error {
|
filteredHTLCView *htlcView, keyRing *CommitmentKeyRing) error {
|
||||||
|
|
||||||
ourBalance := c.ourBalance
|
ourBalance := c.ourBalance
|
||||||
@@ -189,16 +210,16 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
|||||||
// initiator. If the initiator is unable to pay the fee fully, then
|
// initiator. If the initiator is unable to pay the fee fully, then
|
||||||
// their entire output is consumed.
|
// their entire output is consumed.
|
||||||
switch {
|
switch {
|
||||||
case lc.channelState.IsInitiator && commitFee > ourBalance.ToSatoshis():
|
case cb.chanState.IsInitiator && commitFee > ourBalance.ToSatoshis():
|
||||||
ourBalance = 0
|
ourBalance = 0
|
||||||
|
|
||||||
case lc.channelState.IsInitiator:
|
case cb.chanState.IsInitiator:
|
||||||
ourBalance -= commitFeeMSat
|
ourBalance -= commitFeeMSat
|
||||||
|
|
||||||
case !lc.channelState.IsInitiator && commitFee > theirBalance.ToSatoshis():
|
case !cb.chanState.IsInitiator && commitFee > theirBalance.ToSatoshis():
|
||||||
theirBalance = 0
|
theirBalance = 0
|
||||||
|
|
||||||
case !lc.channelState.IsInitiator:
|
case !cb.chanState.IsInitiator:
|
||||||
theirBalance -= commitFeeMSat
|
theirBalance -= commitFeeMSat
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,19 +229,19 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Depending on whether the transaction is ours or not, we call
|
// Depending on whether the transaction is ours or not, we call
|
||||||
// CreateCommitTx with parameters mathcing the perspective, to generate
|
// CreateCommitTx with parameters matching the perspective, to generate
|
||||||
// a new commitment transaction with all the latest unsettled/un-timed
|
// a new commitment transaction with all the latest unsettled/un-timed
|
||||||
// out HTLCs.
|
// out HTLCs.
|
||||||
if c.isOurs {
|
if c.isOurs {
|
||||||
commitTx, err = CreateCommitTx(
|
commitTx, err = CreateCommitTx(
|
||||||
fundingTxIn(lc.channelState), keyRing, &lc.channelState.LocalChanCfg,
|
fundingTxIn(cb.chanState), keyRing, &cb.chanState.LocalChanCfg,
|
||||||
&lc.channelState.RemoteChanCfg, ourBalance.ToSatoshis(),
|
&cb.chanState.RemoteChanCfg, ourBalance.ToSatoshis(),
|
||||||
theirBalance.ToSatoshis(),
|
theirBalance.ToSatoshis(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
commitTx, err = CreateCommitTx(
|
commitTx, err = CreateCommitTx(
|
||||||
fundingTxIn(lc.channelState), keyRing, &lc.channelState.RemoteChanCfg,
|
fundingTxIn(cb.chanState), keyRing, &cb.chanState.RemoteChanCfg,
|
||||||
&lc.channelState.LocalChanCfg, theirBalance.ToSatoshis(),
|
&cb.chanState.LocalChanCfg, theirBalance.ToSatoshis(),
|
||||||
ourBalance.ToSatoshis(),
|
ourBalance.ToSatoshis(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -266,7 +287,7 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
|||||||
// Set the state hint of the commitment transaction to facilitate
|
// Set the state hint of the commitment transaction to facilitate
|
||||||
// quickly recovering the necessary penalty state in the case of an
|
// quickly recovering the necessary penalty state in the case of an
|
||||||
// uncooperative broadcast.
|
// uncooperative broadcast.
|
||||||
err = SetStateNumHint(commitTx, c.height, lc.stateHintObfuscator)
|
err = SetStateNumHint(commitTx, c.height, cb.obfuscator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -289,11 +310,11 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
|||||||
for _, txOut := range commitTx.TxOut {
|
for _, txOut := range commitTx.TxOut {
|
||||||
totalOut += btcutil.Amount(txOut.Value)
|
totalOut += btcutil.Amount(txOut.Value)
|
||||||
}
|
}
|
||||||
if totalOut > lc.channelState.Capacity {
|
if totalOut > cb.chanState.Capacity {
|
||||||
return fmt.Errorf("height=%v, for ChannelPoint(%v) attempts "+
|
return fmt.Errorf("height=%v, for ChannelPoint(%v) attempts "+
|
||||||
"to consume %v while channel capacity is %v",
|
"to consume %v while channel capacity is %v",
|
||||||
c.height, lc.channelState.FundingOutpoint,
|
c.height, cb.chanState.FundingOutpoint,
|
||||||
totalOut, lc.channelState.Capacity)
|
totalOut, cb.chanState.Capacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.txn = commitTx
|
c.txn = commitTx
|
||||||
|
|||||||
@@ -324,6 +324,8 @@ func CreateTestChannels(tweaklessCommits bool) (
|
|||||||
}
|
}
|
||||||
alicePool.Start()
|
alicePool.Start()
|
||||||
|
|
||||||
|
obfuscator := createStateHintObfuscator(aliceChannelState)
|
||||||
|
|
||||||
bobPool := NewSigPool(1, bobSigner)
|
bobPool := NewSigPool(1, bobSigner)
|
||||||
channelBob, err := NewLightningChannel(
|
channelBob, err := NewLightningChannel(
|
||||||
bobSigner, bobChannelState, bobPool,
|
bobSigner, bobChannelState, bobPool,
|
||||||
@@ -334,13 +336,13 @@ func CreateTestChannels(tweaklessCommits bool) (
|
|||||||
bobPool.Start()
|
bobPool.Start()
|
||||||
|
|
||||||
err = SetStateNumHint(
|
err = SetStateNumHint(
|
||||||
aliceCommitTx, 0, channelAlice.stateHintObfuscator,
|
aliceCommitTx, 0, obfuscator,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
err = SetStateNumHint(
|
err = SetStateNumHint(
|
||||||
bobCommitTx, 0, channelAlice.stateHintObfuscator,
|
bobCommitTx, 0, obfuscator,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
|||||||
@@ -421,14 +421,14 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
|||||||
// Construct a LightningChannel manually because we don't have nor need all
|
// Construct a LightningChannel manually because we don't have nor need all
|
||||||
// of the dependencies.
|
// of the dependencies.
|
||||||
channel := LightningChannel{
|
channel := LightningChannel{
|
||||||
channelState: &channelState,
|
channelState: &channelState,
|
||||||
Signer: signer,
|
Signer: signer,
|
||||||
|
commitBuilder: NewCommitmentBuilder(&channelState),
|
||||||
}
|
}
|
||||||
err = channel.createSignDesc()
|
err = channel.createSignDesc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to generate channel sign descriptor: %v", err)
|
t.Fatalf("Failed to generate channel sign descriptor: %v", err)
|
||||||
}
|
}
|
||||||
channel.createStateHintObfuscator()
|
|
||||||
|
|
||||||
// The commitmentPoint is technically hidden in the spec, but we need it to
|
// The commitmentPoint is technically hidden in the spec, but we need it to
|
||||||
// generate the correct tweak.
|
// generate the correct tweak.
|
||||||
@@ -803,7 +803,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
|||||||
dustLimit: tc.dustLimit,
|
dustLimit: tc.dustLimit,
|
||||||
isOurs: true,
|
isOurs: true,
|
||||||
}
|
}
|
||||||
err = channel.createCommitmentTx(
|
err = channel.commitBuilder.createCommitmentTx(
|
||||||
commitmentView, theHTLCView, keys,
|
commitmentView, theHTLCView, keys,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in new issue
Block a user