@@ -466,7 +466,9 @@ func (s *sendPackage) prepareForStorage(currentHeight uint32) (*OutboundParcel,
466466 // In any other case we expect an active asset transfer to be
467467 // committed to.
468468 case vOut .Asset != nil :
469- proofSuffix , err := s .createProofSuffix (idx )
469+ proofSuffix , err := CreateProofSuffix (
470+ s .AnchorTx , s .VirtualPacket , idx , nil ,
471+ )
470472 if err != nil {
471473 return nil , fmt .Errorf ("unable to create " +
472474 "proof %d: %w" , idx , err )
@@ -513,33 +515,51 @@ func (s *sendPackage) prepareForStorage(currentHeight uint32) (*OutboundParcel,
513515 return parcel , nil
514516}
515517
516- // createProofSuffix creates the new proof for the given output. This is the
518+ // CreateProofSuffix creates the new proof for the given output. This is the
517519// final state transition that will be added to the proofs of the receiver. The
518520// proof returned will have all the Taproot Asset level proof information, but
519521// contains dummy data for the on-chain part.
520- func (s * sendPackage ) createProofSuffix (outIndex int ) (* proof.Proof , error ) {
521- inputPrevID := s .VirtualPacket .Inputs [0 ].PrevID
522+ func CreateProofSuffix (anchorTx * AnchorTransaction , vPacket * tappsbt.VPacket ,
523+ outIndex int , allAnchoredVPackets []* tappsbt.VPacket ) (* proof.Proof ,
524+ error ) {
525+
526+ inputPrevID := vPacket .Inputs [0 ].PrevID
522527
523- params , err := proofParams (s .AnchorTx , s .VirtualPacket , outIndex )
528+ params , err := proofParams (
529+ anchorTx , vPacket , outIndex , allAnchoredVPackets ,
530+ )
524531 if err != nil {
525532 return nil , err
526533 }
527534
528- // We also need to account for any P2TR change outputs.
529- if len (s .AnchorTx .FundedPsbt .Pkt .UnsignedTx .TxOut ) > 1 {
530- isAnchor := func (idx uint32 ) bool {
531- for outIdx := range s .VirtualPacket .Outputs {
532- vOut := s .VirtualPacket .Outputs [outIdx ]
533- if vOut .AnchorOutputIndex == idx {
535+ isAnchor := func (anchorOutputIndex uint32 ) bool {
536+ // Does the current virtual packet anchor into this output?
537+ for outIdx := range vPacket .Outputs {
538+ vOut := vPacket .Outputs [outIdx ]
539+ if vOut .AnchorOutputIndex == anchorOutputIndex {
540+ return true
541+ }
542+ }
543+
544+ // Maybe any of the other anchored virtual packets anchor into
545+ // this output?
546+ for _ , vPkt := range allAnchoredVPackets {
547+ for _ , vOut := range vPkt .Outputs {
548+ if vOut .AnchorOutputIndex == anchorOutputIndex {
534549 return true
535550 }
536551 }
537-
538- return false
539552 }
540553
554+ // No virtual packet anchors into this output, it must be a
555+ // pure BTC output.
556+ return false
557+ }
558+
559+ // We also need to account for any P2TR change outputs.
560+ if len (anchorTx .FundedPsbt .Pkt .UnsignedTx .TxOut ) > 1 {
541561 err := proof .AddExclusionProofs (
542- & params .BaseProofParams , s . AnchorTx .FundedPsbt .Pkt ,
562+ & params .BaseProofParams , anchorTx .FundedPsbt .Pkt ,
543563 isAnchor ,
544564 )
545565 if err != nil {
@@ -585,7 +605,8 @@ func newParams(anchorTx *AnchorTransaction, a *asset.Asset, outputIndex int,
585605// proofParams creates the set of parameters that will be used to create the
586606// proofs for the sender and receiver.
587607func proofParams (anchorTx * AnchorTransaction , vPkt * tappsbt.VPacket ,
588- outIndex int ) (* proof.TransitionParams , error ) {
608+ outIndex int ,
609+ allAnchoredVPackets []* tappsbt.VPacket ) (* proof.TransitionParams , error ) {
589610
590611 outputCommitments := anchorTx .OutputCommitments
591612
@@ -594,6 +615,13 @@ func proofParams(anchorTx *AnchorTransaction, vPkt *tappsbt.VPacket,
594615 return nil , err
595616 }
596617
618+ allVirtualOutputs := append ([]* tappsbt.VOutput {}, vPkt .Outputs ... )
619+ for _ , otherVPkt := range allAnchoredVPackets {
620+ allVirtualOutputs = append (
621+ allVirtualOutputs , otherVPkt .Outputs ... ,
622+ )
623+ }
624+
597625 // Is this the split root? Then we need exclusion proofs from all the
598626 // split outputs. We can also use this path for interactive full value
599627 // send case, where we also just commit to an asset that has a TX
@@ -612,11 +640,8 @@ func proofParams(anchorTx *AnchorTransaction, vPkt *tappsbt.VPacket,
612640
613641 // Add exclusion proofs for all the other outputs.
614642 err = addOtherOutputExclusionProofs (
615- vPkt . Outputs , rootOut .Asset , rootParams ,
643+ allVirtualOutputs , rootOut .Asset , rootParams ,
616644 outputCommitments ,
617- func (i int , _ * tappsbt.VOutput ) bool {
618- return i == outIndex
619- },
620645 )
621646 if err != nil {
622647 return nil , err
@@ -668,16 +693,8 @@ func proofParams(anchorTx *AnchorTransaction, vPkt *tappsbt.VPacket,
668693
669694 // Add exclusion proofs for all the other outputs.
670695 err = addOtherOutputExclusionProofs (
671- vPkt .Outputs , splitOut .Asset , splitParams , outputCommitments ,
672- func (i int , vOut * tappsbt.VOutput ) bool {
673- // We don't need exclusion proofs for:
674- // - The split output itself.
675- // - The split root output.
676- // - Any output that is committed to the same
677- // anchor output as our split output.
678- return i == outIndex || vOut == splitRootOut ||
679- vOut .AnchorOutputIndex == splitIndex
680- },
696+ allVirtualOutputs , splitOut .Asset , splitParams ,
697+ outputCommitments ,
681698 )
682699 if err != nil {
683700 return nil , err
@@ -691,14 +708,14 @@ func proofParams(anchorTx *AnchorTransaction, vPkt *tappsbt.VPacket,
691708// return false for not yet processed outputs, otherwise they'll be skipped).
692709func addOtherOutputExclusionProofs (outputs []* tappsbt.VOutput ,
693710 asset * asset.Asset , params * proof.TransitionParams ,
694- outputCommitments map [uint32 ]* commitment.TapCommitment ,
695- skip func (int , * tappsbt.VOutput ) bool ) error {
711+ outputCommitments map [uint32 ]* commitment.TapCommitment ) error {
696712
697713 for idx := range outputs {
698714 vOut := outputs [idx ]
699715
700- haveProof := params .HaveExclusionProof (vOut .AnchorOutputIndex )
701- if skip (idx , vOut ) || haveProof {
716+ haveIProof := params .HaveInclusionProof (vOut .AnchorOutputIndex )
717+ haveEProof := params .HaveExclusionProof (vOut .AnchorOutputIndex )
718+ if haveIProof || haveEProof {
702719 continue
703720 }
704721
@@ -772,9 +789,7 @@ func (s *sendPackage) createReAnchorProof(
772789 // BTC level outputs.
773790 err = addOtherOutputExclusionProofs (
774791 s .VirtualPacket .Outputs , passiveOut .Asset , passiveParams ,
775- outputCommitments , func (i int , vOut * tappsbt.VOutput ) bool {
776- return vOut .AnchorOutputIndex == passiveOutputIndex
777- },
792+ outputCommitments ,
778793 )
779794 if err != nil {
780795 return nil , err
0 commit comments