Skip to content

Commit 129dd06

Browse files
committed
tapchannel: support group key based channel funding
1 parent 8b3eac8 commit 129dd06

File tree

1 file changed

+73
-55
lines changed

1 file changed

+73
-55
lines changed

tapchannel/aux_funding_controller.go

+73-55
Original file line numberDiff line numberDiff line change
@@ -819,48 +819,49 @@ func (f *FundingController) sendInputOwnershipProofs(peerPub btcec.PublicKey,
819819
log.Infof("Generating input ownership proofs for %v packets",
820820
len(vPackets))
821821

822-
// TODO(guggero): Remove once we add group key support.
823-
if len(vPackets) > 1 {
824-
return fmt.Errorf("only one vPacket supported for now")
825-
}
826-
vPkt := vPackets[0]
827-
828822
// For each of the inputs we selected, we'll create a new ownership
829823
// proof for each of them. We'll send this to the peer, so they can
830824
// verify that we actually own the inputs we're using to fund
831825
// the channel.
832-
for _, assetInput := range vPkt.Inputs {
833-
// First, we'll grab the proof for the asset input, then
834-
// generate the challenge witness to place in the proof so it
835-
challengeWitness, err := f.cfg.AssetWallet.SignOwnershipProof(
836-
assetInput.Asset(), fn.None[[32]byte](),
837-
)
838-
if err != nil {
839-
return fmt.Errorf("error signing ownership proof: %w",
840-
err)
841-
}
826+
for _, vPkt := range vPackets {
827+
for _, assetInput := range vPkt.Inputs {
828+
// First, we'll grab the proof for the asset input, then
829+
// generate the challenge witness to place in the proof
830+
// so it can be sent over.
831+
wallet := f.cfg.AssetWallet
832+
challengeWitness, err := wallet.SignOwnershipProof(
833+
assetInput.Asset(), fn.None[[32]byte](),
834+
)
835+
if err != nil {
836+
return fmt.Errorf("error signing ownership "+
837+
"proof: %w", err)
838+
}
842839

843-
// TODO(roasbeef): use the temp chan ID above? as part of
844-
// challenge
840+
// TODO(roasbeef): use the temp chan ID above? as part
841+
// of challenge
845842

846-
// With the witness obtained, we'll emplace it, then add this
847-
// to our set of relevant input proofs. But we create a copy of
848-
// the proof first, to make sure we don't modify the vPacket.
849-
var proofBuf bytes.Buffer
850-
err = assetInput.Proof.Encode(&proofBuf)
851-
if err != nil {
852-
return fmt.Errorf("error serializing proof: %w", err)
853-
}
843+
// With the witness obtained, we'll emplace it, then add
844+
// this to our set of relevant input proofs. But we
845+
// create a copy of the proof first, to make sure we
846+
// don't modify the vPacket.
847+
var proofBuf bytes.Buffer
848+
err = assetInput.Proof.Encode(&proofBuf)
849+
if err != nil {
850+
return fmt.Errorf("error serializing proof: %w",
851+
err)
852+
}
854853

855-
proofCopy := &proof.Proof{}
856-
if err := proofCopy.Decode(&proofBuf); err != nil {
857-
return fmt.Errorf("error decoding proof: %w", err)
858-
}
854+
proofCopy := &proof.Proof{}
855+
if err := proofCopy.Decode(&proofBuf); err != nil {
856+
return fmt.Errorf("error decoding proof: %w",
857+
err)
858+
}
859859

860-
proofCopy.ChallengeWitness = challengeWitness
861-
fundingState.inputProofs = append(
862-
fundingState.inputProofs, proofCopy,
863-
)
860+
proofCopy.ChallengeWitness = challengeWitness
861+
fundingState.inputProofs = append(
862+
fundingState.inputProofs, proofCopy,
863+
)
864+
}
864865
}
865866

866867
// With all our proofs assembled, we'll now send each of them to the
@@ -903,32 +904,42 @@ func (f *FundingController) sendInputOwnershipProofs(peerPub btcec.PublicKey,
903904
// Now that we've sent the proofs for the input assets, we'll send them
904905
// a fully signed asset funding output. We can send this safely as they
905906
// can't actually broadcast this without our signed Bitcoin inputs.
906-
signedInputs, err := f.cfg.AssetWallet.SignVirtualPacket(vPkt)
907-
if err != nil {
908-
return fmt.Errorf("unable to sign funding inputs: %w", err)
909-
}
910-
if len(signedInputs) != len(vPkt.Inputs) {
911-
return fmt.Errorf("expected %v signed inputs, got %v",
912-
len(vPkt.Inputs), len(signedInputs))
907+
for idx := range vPackets {
908+
vPkt := vPackets[idx]
909+
signedInputs, err := f.cfg.AssetWallet.SignVirtualPacket(vPkt)
910+
if err != nil {
911+
return fmt.Errorf("unable to sign funding inputs: %w",
912+
err)
913+
}
914+
if len(signedInputs) != len(vPkt.Inputs) {
915+
return fmt.Errorf("expected %v signed inputs, got %v",
916+
len(vPkt.Inputs), len(signedInputs))
917+
}
913918
}
914919

915920
// We'll now send the signed inputs to the remote party.
916-
//
917-
// TODO(roasbeef): generalize for multi-asset
918-
fundingOut, err := vPkt.FirstNonSplitRootOutput()
919-
if err != nil {
920-
return fmt.Errorf("unable to get funding asset: %w", err)
921-
}
922-
assetOutputMsg := cmsg.NewTxAssetOutputProof(
923-
fundingState.pid, *fundingOut.Asset, true,
924-
)
921+
for idx, vPkt := range vPackets {
922+
fundingOut, err := vPkt.FirstNonSplitRootOutput()
923+
if err != nil {
924+
return fmt.Errorf("unable to get funding asset: %w",
925+
err)
926+
}
925927

926-
log.Debugf("Sending TLV for funding asset output to remote party: %v",
927-
limitSpewer.Sdump(fundingOut.Asset))
928+
assetOutputMsg := cmsg.NewTxAssetOutputProof(
929+
fundingState.pid, *fundingOut.Asset,
930+
idx == len(vPackets)-1,
931+
)
928932

929-
err = f.cfg.PeerMessenger.SendMessage(ctx, peerPub, assetOutputMsg)
930-
if err != nil {
931-
return fmt.Errorf("unable to send proof to peer: %w", err)
933+
log.Debugf("Sending TLV for funding asset output to remote "+
934+
"party: %v", limitSpewer.Sdump(fundingOut.Asset))
935+
936+
err = f.cfg.PeerMessenger.SendMessage(
937+
ctx, peerPub, assetOutputMsg,
938+
)
939+
if err != nil {
940+
return fmt.Errorf("unable to send proof to peer: %w",
941+
err)
942+
}
932943
}
933944

934945
return nil
@@ -2008,6 +2019,13 @@ func (f *FundingController) validateWitness(outAsset asset.Asset,
20082019
// the prev output fetcher for Bitcoin.
20092020
prevAssets := make(commitment.InputSet)
20102021
for _, p := range inputAssetProofs {
2022+
// We validate on the individual vPSBT level, so we will only
2023+
// use the inputs that actually match the current output's asset
2024+
// ID.
2025+
if outAsset.ID() != p.Asset.ID() {
2026+
continue
2027+
}
2028+
20112029
prevID := asset.PrevID{
20122030
OutPoint: p.OutPoint(),
20132031
ID: p.Asset.ID(),

0 commit comments

Comments
 (0)