Skip to content

Commit 9233d13

Browse files
committed
tapchannel: ensure the root commit asset has a valid witness
In this commit, we fix a very subtle issue related to split witnesses and root assets. Before this commit, when we went to sign a second level txn, which is a split, we would create a virtual txn, which will commit to the _entire_ witness of the root asset in the vIn. Note that this bypasses the normal segwit encoding logic, as that currently doesn't apply to the root asset encoded in the split commit proof. In the future, we may want to expand the segwit encoding semantics to root assets after careful consideration. In this commit, we fix a bug that would cause an invalid 2nd level sig by ensuring that before we create the output commitments, we update the root asset witness in each split, to the funding witness script, which is just OP_TRUE.
1 parent 1672d2a commit 9233d13

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

tapchannel/commitment.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,15 @@ func GenerateCommitmentAllocations(prevState *cmsg.Commitment,
528528
err)
529529
}
530530

531+
// The root asset of the split commitment will still commit to the full
532+
// witness value. Therefore, we need to update the root asset witness to
533+
// what it would be at broadcast time.
534+
fundingWitness, err := fundingSpendWitness().Unpack()
535+
if err != nil {
536+
return nil, nil, fmt.Errorf("unable to make funding "+
537+
"witness: %w", err)
538+
}
539+
531540
// Prepare the output assets for each virtual packet, then create the
532541
// output commitments.
533542
ctx := context.Background()
@@ -537,6 +546,23 @@ func GenerateCommitmentAllocations(prevState *cmsg.Commitment,
537546
return nil, nil, fmt.Errorf("unable to prepare output "+
538547
"assets: %w", err)
539548
}
549+
550+
// With the packets prepared, we'll swap in the correct witness
551+
// for each of them.
552+
for outIdx := range vPackets[idx].Outputs {
553+
outAsset := vPackets[idx].Outputs[outIdx].Asset
554+
555+
// There is always only a single input, as we're
556+
// sweeping a single contract w/ each vPkt.
557+
const inputIndex = 0
558+
err := outAsset.UpdateTxWitness(
559+
inputIndex, fundingWitness,
560+
)
561+
if err != nil {
562+
return nil, nil, fmt.Errorf("error updating "+
563+
"witness: %w", err)
564+
}
565+
}
540566
}
541567

542568
outCommitments, err := tapsend.CreateOutputCommitments(vPackets)

0 commit comments

Comments
 (0)