input: update CommitSpendNoDelay to be aware of tweakless commits, add new witness type

In this commit, we update the `CommitSpendNoDelay` method to be aware of
the alternate spending mechanism for commitments that don't have a tweak
for the remote party's non-delay output. We also add a new witness type
so callers can convey their expected signing path.
This commit is contained in:
Olaoluwa Osuntokun 2019-07-31 20:02:52 -07:00
parent a9541b8f6a
commit bee777ab5f
No known key found for this signature in database
GPG Key ID: BC13F65E2DC84465
3 changed files with 42 additions and 9 deletions

@ -902,13 +902,15 @@ func CommitSpendRevoke(signer Signer, signDesc *SignDescriptor,
} }
// CommitSpendNoDelay constructs a valid witness allowing a node to spend their // CommitSpendNoDelay constructs a valid witness allowing a node to spend their
// settled no-delay output on the counterparty's commitment transaction. // settled no-delay output on the counterparty's commitment transaction. If the
// tweakless field is true, then we'll omit the set where we tweak the pubkey
// with a random set of bytes, and use it directly in the witness stack.
// //
// NOTE: The passed SignDescriptor should include the raw (untweaked) public // NOTE: The passed SignDescriptor should include the raw (untweaked) public
// key of the receiver and also the proper single tweak value based on the // key of the receiver and also the proper single tweak value based on the
// current commitment point. // current commitment point.
func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor, func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor,
sweepTx *wire.MsgTx) (wire.TxWitness, error) { sweepTx *wire.MsgTx, tweakless bool) (wire.TxWitness, error) {
if signDesc.KeyDesc.PubKey == nil { if signDesc.KeyDesc.PubKey == nil {
return nil, fmt.Errorf("cannot generate witness with nil " + return nil, fmt.Errorf("cannot generate witness with nil " +
@ -923,15 +925,26 @@ func CommitSpendNoDelay(signer Signer, signDesc *SignDescriptor,
} }
// Finally, we'll manually craft the witness. The witness here is the // Finally, we'll manually craft the witness. The witness here is the
// exact same as a regular p2wkh witness, but we'll need to ensure that // exact same as a regular p2wkh witness, depending on the value of the
// we use the tweaked public key as the last item in the witness stack // tweakless bool.
// which was originally used to created the pkScript we're spending.
witness := make([][]byte, 2) witness := make([][]byte, 2)
witness[0] = append(sweepSig, byte(signDesc.HashType)) witness[0] = append(sweepSig, byte(signDesc.HashType))
switch tweakless {
// If we're tweaking the key, then we use the tweaked public key as the
// last item in the witness stack which was originally used to created
// the pkScript we're spending.
case false:
witness[1] = TweakPubKeyWithTweak( witness[1] = TweakPubKeyWithTweak(
signDesc.KeyDesc.PubKey, signDesc.SingleTweak, signDesc.KeyDesc.PubKey, signDesc.SingleTweak,
).SerializeCompressed() ).SerializeCompressed()
// Otherwise, we can just use the raw pubkey, since there's no random
// value to be combined.
case true:
witness[1] = signDesc.KeyDesc.PubKey.SerializeCompressed()
}
return witness, nil return witness, nil
} }

@ -79,6 +79,11 @@ const (
// output that sends to a nested P2SH script that pays to a key solely // output that sends to a nested P2SH script that pays to a key solely
// under our control. The witness generated needs to include the // under our control. The witness generated needs to include the
NestedWitnessKeyHash WitnessType = 11 NestedWitnessKeyHash WitnessType = 11
// CommitSpendNoDelayTweakless is similar to the CommitSpendNoDelay
// type, but it omits the tweak that randomizes the key we need to
// spend with a channel peer supplied set of randomness.
CommitSpendNoDelayTweakless = 12
) )
// Stirng returns a human readable version of the target WitnessType. // Stirng returns a human readable version of the target WitnessType.
@ -90,6 +95,9 @@ func (wt WitnessType) String() string {
case CommitmentNoDelay: case CommitmentNoDelay:
return "CommitmentNoDelay" return "CommitmentNoDelay"
case CommitSpendNoDelayTweakless:
return "CommitmentNoDelayTweakless"
case CommitmentRevoke: case CommitmentRevoke:
return "CommitmentRevoke" return "CommitmentRevoke"
@ -153,7 +161,17 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
}, nil }, nil
case CommitmentNoDelay: case CommitmentNoDelay:
witness, err := CommitSpendNoDelay(signer, desc, tx) witness, err := CommitSpendNoDelay(signer, desc, tx, false)
if err != nil {
return nil, err
}
return &Script{
Witness: witness,
}, nil
case CommitSpendNoDelayTweakless:
witness, err := CommitSpendNoDelay(signer, desc, tx, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -259,6 +259,8 @@ func getInputWitnessSizeUpperBound(inp input.Input) (int, bool, error) {
switch inp.WitnessType() { switch inp.WitnessType() {
// Outputs on a remote commitment transaction that pay directly to us. // Outputs on a remote commitment transaction that pay directly to us.
case input.CommitSpendNoDelayTweakless:
fallthrough
case input.WitnessKeyHash: case input.WitnessKeyHash:
fallthrough fallthrough
case input.CommitmentNoDelay: case input.CommitmentNoDelay: