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:
parent
13a108e578
commit
613d771daf
@ -1226,10 +1226,6 @@ type LightningChannel struct {
|
||||
// Capacity is the total capacity of this channel.
|
||||
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.
|
||||
// This is also the same as the number of updates to the channel we've
|
||||
// accepted.
|
||||
@ -1247,6 +1243,8 @@ type LightningChannel struct {
|
||||
|
||||
channelState *channeldb.OpenChannel
|
||||
|
||||
commitBuilder *CommitmentBuilder
|
||||
|
||||
// [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
|
||||
// are applied in order to re-construct a commitment transaction from a
|
||||
@ -1299,6 +1297,7 @@ func NewLightningChannel(signer input.Signer,
|
||||
remoteCommitChain: newCommitmentChain(),
|
||||
localCommitChain: newCommitmentChain(),
|
||||
channelState: state,
|
||||
commitBuilder: NewCommitmentBuilder(state),
|
||||
localUpdateLog: localUpdateLog,
|
||||
remoteUpdateLog: remoteUpdateLog,
|
||||
ChanPoint: &state.FundingOutpoint,
|
||||
@ -1322,8 +1321,6 @@ func NewLightningChannel(signer input.Signer,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lc.createStateHintObfuscator()
|
||||
|
||||
return lc, nil
|
||||
}
|
||||
|
||||
@ -2208,7 +2205,10 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -127,27 +127,48 @@ func DeriveCommitmentKeys(commitPoint *btcec.PublicKey,
|
||||
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
|
||||
// the channel, which is used to encode the commitment height in the sequence
|
||||
// number of commitment transaction inputs.
|
||||
func (lc *LightningChannel) createStateHintObfuscator() {
|
||||
state := lc.channelState
|
||||
func createStateHintObfuscator(state *channeldb.OpenChannel) [StateHintSize]byte {
|
||||
if state.IsInitiator {
|
||||
lc.stateHintObfuscator = DeriveStateHintObfuscator(
|
||||
return DeriveStateHintObfuscator(
|
||||
state.LocalChanCfg.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
|
||||
// commitment view and assigns to txn field.
|
||||
func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
||||
func (cb *CommitmentBuilder) createCommitmentTx(c *commitment,
|
||||
filteredHTLCView *htlcView, keyRing *CommitmentKeyRing) error {
|
||||
|
||||
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
|
||||
// their entire output is consumed.
|
||||
switch {
|
||||
case lc.channelState.IsInitiator && commitFee > ourBalance.ToSatoshis():
|
||||
case cb.chanState.IsInitiator && commitFee > ourBalance.ToSatoshis():
|
||||
ourBalance = 0
|
||||
|
||||
case lc.channelState.IsInitiator:
|
||||
case cb.chanState.IsInitiator:
|
||||
ourBalance -= commitFeeMSat
|
||||
|
||||
case !lc.channelState.IsInitiator && commitFee > theirBalance.ToSatoshis():
|
||||
case !cb.chanState.IsInitiator && commitFee > theirBalance.ToSatoshis():
|
||||
theirBalance = 0
|
||||
|
||||
case !lc.channelState.IsInitiator:
|
||||
case !cb.chanState.IsInitiator:
|
||||
theirBalance -= commitFeeMSat
|
||||
}
|
||||
|
||||
@ -208,19 +229,19 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
||||
)
|
||||
|
||||
// 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
|
||||
// out HTLCs.
|
||||
if c.isOurs {
|
||||
commitTx, err = CreateCommitTx(
|
||||
fundingTxIn(lc.channelState), keyRing, &lc.channelState.LocalChanCfg,
|
||||
&lc.channelState.RemoteChanCfg, ourBalance.ToSatoshis(),
|
||||
fundingTxIn(cb.chanState), keyRing, &cb.chanState.LocalChanCfg,
|
||||
&cb.chanState.RemoteChanCfg, ourBalance.ToSatoshis(),
|
||||
theirBalance.ToSatoshis(),
|
||||
)
|
||||
} else {
|
||||
commitTx, err = CreateCommitTx(
|
||||
fundingTxIn(lc.channelState), keyRing, &lc.channelState.RemoteChanCfg,
|
||||
&lc.channelState.LocalChanCfg, theirBalance.ToSatoshis(),
|
||||
fundingTxIn(cb.chanState), keyRing, &cb.chanState.RemoteChanCfg,
|
||||
&cb.chanState.LocalChanCfg, theirBalance.ToSatoshis(),
|
||||
ourBalance.ToSatoshis(),
|
||||
)
|
||||
}
|
||||
@ -266,7 +287,7 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
||||
// Set the state hint of the commitment transaction to facilitate
|
||||
// quickly recovering the necessary penalty state in the case of an
|
||||
// uncooperative broadcast.
|
||||
err = SetStateNumHint(commitTx, c.height, lc.stateHintObfuscator)
|
||||
err = SetStateNumHint(commitTx, c.height, cb.obfuscator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -289,11 +310,11 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
||||
for _, txOut := range commitTx.TxOut {
|
||||
totalOut += btcutil.Amount(txOut.Value)
|
||||
}
|
||||
if totalOut > lc.channelState.Capacity {
|
||||
if totalOut > cb.chanState.Capacity {
|
||||
return fmt.Errorf("height=%v, for ChannelPoint(%v) attempts "+
|
||||
"to consume %v while channel capacity is %v",
|
||||
c.height, lc.channelState.FundingOutpoint,
|
||||
totalOut, lc.channelState.Capacity)
|
||||
c.height, cb.chanState.FundingOutpoint,
|
||||
totalOut, cb.chanState.Capacity)
|
||||
}
|
||||
|
||||
c.txn = commitTx
|
||||
|
@ -324,6 +324,8 @@ func CreateTestChannels(tweaklessCommits bool) (
|
||||
}
|
||||
alicePool.Start()
|
||||
|
||||
obfuscator := createStateHintObfuscator(aliceChannelState)
|
||||
|
||||
bobPool := NewSigPool(1, bobSigner)
|
||||
channelBob, err := NewLightningChannel(
|
||||
bobSigner, bobChannelState, bobPool,
|
||||
@ -334,13 +336,13 @@ func CreateTestChannels(tweaklessCommits bool) (
|
||||
bobPool.Start()
|
||||
|
||||
err = SetStateNumHint(
|
||||
aliceCommitTx, 0, channelAlice.stateHintObfuscator,
|
||||
aliceCommitTx, 0, obfuscator,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
err = SetStateNumHint(
|
||||
bobCommitTx, 0, channelAlice.stateHintObfuscator,
|
||||
bobCommitTx, 0, obfuscator,
|
||||
)
|
||||
if err != nil {
|
||||
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
|
||||
// of the dependencies.
|
||||
channel := LightningChannel{
|
||||
channelState: &channelState,
|
||||
Signer: signer,
|
||||
channelState: &channelState,
|
||||
Signer: signer,
|
||||
commitBuilder: NewCommitmentBuilder(&channelState),
|
||||
}
|
||||
err = channel.createSignDesc()
|
||||
if err != nil {
|
||||
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
|
||||
// generate the correct tweak.
|
||||
@ -803,7 +803,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
||||
dustLimit: tc.dustLimit,
|
||||
isOurs: true,
|
||||
}
|
||||
err = channel.createCommitmentTx(
|
||||
err = channel.commitBuilder.createCommitmentTx(
|
||||
commitmentView, theHTLCView, keys,
|
||||
)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user