@@ -2,9 +2,11 @@ package tapsend
22
33import (
44 "bytes"
5+ "cmp"
56 "errors"
67 "fmt"
78 "net/url"
9+ "slices"
810 "sort"
911
1012 "github.com/btcsuite/btcd/btcec/v2"
@@ -389,27 +391,30 @@ func sortPiecesWithProofs(pieces []*piece) {
389391 // Now sort all the proofs within each piece by amount and then script
390392 // key. This will give us a stable order for all asset UTXOs.
391393 for idx := range pieces {
392- sort .Slice (pieces [idx ].proofs , func (i , j int ) bool {
393- assetI := pieces [idx ].proofs [i ].Asset
394- assetJ := pieces [idx ].proofs [j ].Asset
395-
396- // If amounts are equal, sort by script key.
397- if assetI .Amount == assetJ .Amount {
398- keyI := assetI .ScriptKey .PubKey
399- keyJ := assetJ .ScriptKey .PubKey
400- return bytes .Compare (
401- keyI .SerializeCompressed (),
402- keyJ .SerializeCompressed (),
403- ) < 0
404- }
405-
406- // Otherwise, sort by amount, but in reverse order so
407- // that the largest amounts are first.
408- return assetI .Amount > assetJ .Amount
409- })
394+ slices .SortFunc (
395+ pieces [idx ].proofs , func (i , j * proof.Proof ) int {
396+ return AssetSortForInputs (i .Asset , j .Asset )
397+ },
398+ )
410399 }
411400}
412401
402+ // AssetSortForInputs is a comparison function that should be used to sort asset
403+ // inputs by amount (in reverse order) and then by script key. Using this
404+ // function everywhere we sort inputs will ensure that the inputs are always in
405+ // a predictable and stable order.
406+ func AssetSortForInputs (i , j asset.Asset ) int {
407+ return cmp .Or (
408+ // Sort amounts in reverse order so that the largest amounts are
409+ // first.
410+ cmp .Compare (j .Amount , i .Amount ),
411+ bytes .Compare (
412+ i .ScriptKey .PubKey .SerializeCompressed (),
413+ j .ScriptKey .PubKey .SerializeCompressed (),
414+ ),
415+ )
416+ }
417+
413418// DistributeCoins allocates a set of inputs (extracted from the given input
414419// proofs) to virtual outputs as specified by the allocations given. It returns
415420// a list of virtual packets (one for each distinct asset ID) with virtual
0 commit comments