@@ -617,7 +617,7 @@ func PrepareOutputAssets(ctx context.Context, vPkt *tappsbt.VPacket) error {
617617// signature over the asset transfer, verifying the transfer with the Taproot
618618// Asset VM, and attaching that signature to the new Asset.
619619func SignVirtualTransaction (vPkt * tappsbt.VPacket , signer Signer ,
620- validator TxValidator ) error {
620+ validator WitnessValidator ) error {
621621
622622 inputs := vPkt .Inputs
623623 outputs := vPkt .Outputs
@@ -632,13 +632,35 @@ func SignVirtualTransaction(vPkt *tappsbt.VPacket, signer Signer,
632632 // Identify new output asset. For splits, the new asset that receives
633633 // the signature is the one with the split root set to true.
634634 newAsset := outputs [0 ].Asset
635+ var splitAssets []* commitment.SplitAsset
635636 if isSplit {
636637 splitOut , err := vPkt .SplitRootOutput ()
637638 if err != nil {
638639 return fmt .Errorf ("no split root output found for " +
639640 "split transaction: %w" , err )
640641 }
641642 newAsset = splitOut .Asset
643+
644+ // If the transfer includes an asset split, we have to validate
645+ // each split asset to ensure that our new Asset is committing
646+ // to a valid SplitCommitment.
647+ splitAssets = make ([]* commitment.SplitAsset , len (outputs ))
648+ for idx := range outputs {
649+ splitAssets [idx ] = & commitment.SplitAsset {
650+ Asset : * outputs [idx ].Asset ,
651+ OutputIndex : outputs [idx ].AnchorOutputIndex ,
652+ }
653+
654+ // The output that houses the root asset in case of a
655+ // split has a special field for the split asset, which
656+ // actually contains the split commitment proof. We need
657+ // to use that one for the validation, as the root asset
658+ // is already validated as the newAsset.
659+ if outputs [idx ].Type .IsSplitRoot () {
660+ splitAssets [idx ].Asset =
661+ * outputs [idx ].SplitAsset
662+ }
663+ }
642664 }
643665
644666 // Construct input set from all input assets.
@@ -679,57 +701,32 @@ func SignVirtualTransaction(vPkt *tappsbt.VPacket, signer Signer,
679701 newAsset .PrevWitnesses [idx ].TxWitness = newWitness
680702 }
681703
682- // Create an instance of the Taproot Asset VM and validate the transfer.
683- verifySpend := func (splitAssets []* commitment.SplitAsset ) error {
684- newAssetCopy := newAsset .Copy ()
685- return validator .Execute (newAssetCopy , splitAssets , prevAssets )
686- }
687-
688- // If the transfer contains no asset splits, we only need to validate
689- // the new asset with its witness attached, then we can exit early.
690- if ! isSplit {
691- return verifySpend (nil )
692- }
693-
694- // If the transfer includes an asset split, we have to validate each
695- // split asset to ensure that our new Asset is committing to a valid
696- // SplitCommitment.
697- splitAssets := make ([]* commitment.SplitAsset , len (outputs ))
698- for idx := range outputs {
699- splitAssets [idx ] = & commitment.SplitAsset {
700- Asset : * outputs [idx ].Asset ,
701- OutputIndex : outputs [idx ].AnchorOutputIndex ,
702- }
703-
704- // The output that houses the root asset in case of a split has
705- // a special field for the split asset, which actually contains
706- // the split commitment proof. We need to use that one for the
707- // validation, as the root asset is already validated as the
708- // newAsset.
709- if outputs [idx ].Type .IsSplitRoot () {
710- splitAssets [idx ].Asset = * outputs [idx ].SplitAsset
711- }
712- }
713- if err := verifySpend (splitAssets ); err != nil {
704+ err = validator .ValidateWitnesses (newAsset , splitAssets , prevAssets )
705+ if err != nil {
714706 return err
715707 }
716708
717- // Update each split asset to store the root asset with the witness
718- // attached, so the receiver can verify inclusion of the root asset.
719- for idx := range outputs {
720- splitAsset := outputs [idx ].Asset
721-
722- // The output that houses the root asset in case of a split has
723- // a special field for the split asset. That asset is no longer
724- // needed (and isn't committed to anywhere), but in order for it
725- // to be validated externally, we still want to include it and
726- // therefore also want to update it with the signed root asset.
727- if outputs [idx ].Type .IsSplitRoot () {
728- splitAsset = outputs [idx ].SplitAsset
729- }
709+ if isSplit {
710+ // Update each split asset to store the root asset with the
711+ // witness attached, so the receiver can verify inclusion of the
712+ // root asset.
713+ for idx := range outputs {
714+ splitAsset := outputs [idx ].Asset
715+
716+ // The output that houses the root asset in case of a
717+ // split has a special field for the split asset. That
718+ // asset is no longer needed (and isn't committed to
719+ // anywhere), but in order for it to be validated
720+ // externally, we still want to include it and therefore
721+ // also want to update it with the signed root asset.
722+ if outputs [idx ].Type .IsSplitRoot () {
723+ splitAsset = outputs [idx ].SplitAsset
724+ }
730725
731- splitCommitment := splitAsset .PrevWitnesses [0 ].SplitCommitment
732- splitCommitment .RootAsset = * newAsset .Copy ()
726+ splitCommitment :=
727+ splitAsset .PrevWitnesses [0 ].SplitCommitment
728+ splitCommitment .RootAsset = * newAsset .Copy ()
729+ }
733730 }
734731
735732 return nil
0 commit comments