@@ -44,7 +44,6 @@ import (
44
44
"github.com/btcsuite/btcd/btcutil"
45
45
"github.com/btcsuite/btcd/btcutil/hdkeychain"
46
46
"github.com/btcsuite/btcd/chaincfg"
47
- "github.com/btcsuite/btcd/chaincfg/chainhash"
48
47
"github.com/btcsuite/btcd/wire"
49
48
"github.com/sirupsen/logrus"
50
49
)
@@ -772,19 +771,55 @@ func (account *Account) CanVerifyAddresses() (bool, bool, error) {
772
771
return keystore .CanVerifyAddress (account .Coin ())
773
772
}
774
773
775
- type byValue struct {
776
- outputs []* SpendableOutput
774
+ // addressOutputsSum holds the address and sum of outputs for that address.
775
+ type addressOutputsSum struct {
776
+ address string
777
+ sum int64
777
778
}
778
779
779
- func (p * byValue ) Len () int { return len (p .outputs ) }
780
- func (p * byValue ) Less (i , j int ) bool {
781
- if p .outputs [i ].TxOut .Value == p .outputs [j ].TxOut .Value {
782
- // Secondary sort to make coin selection deterministic.
783
- return chainhash .HashH (p .outputs [i ].TxOut .PkScript ).String () < chainhash .HashH (p .outputs [j ].TxOut .PkScript ).String ()
780
+ // sortByAddresses sorts the outputs by grouping them based on their addresses and then sorting each group
781
+ // from outputs with the biggest amounts to those with the lowest amounts.
782
+ func sortByAddresses (result []* SpendableOutput ) []* SpendableOutput {
783
+ // Create a map to store outputs grouped by address
784
+ grouped := make (map [string ][]* SpendableOutput )
785
+
786
+ // Group outputs by address
787
+ for _ , output := range result {
788
+ grouped [output .Address .String ()] = append (grouped [output .Address .String ()], output )
784
789
}
785
- return p .outputs [i ].TxOut .Value < p .outputs [j ].TxOut .Value
790
+
791
+ // Create a slice to store the sums of outputs and addresses
792
+ sums := make ([]addressOutputsSum , 0 , len (grouped ))
793
+
794
+ // Calculate sums of values for each group and store in the sums slice
795
+ for address , outputs := range grouped {
796
+ var sum int64
797
+ for _ , output := range outputs {
798
+ sum += output .TxOut .Value
799
+ }
800
+ sums = append (sums , addressOutputsSum {
801
+ address : address ,
802
+ sum : sum ,
803
+ })
804
+ }
805
+
806
+ // Sort the sums slice by the sum of values in descending order
807
+ sort .Slice (sums , func (i , j int ) bool {
808
+ return sums [i ].sum > sums [j ].sum
809
+ })
810
+
811
+ // Create a new result grouped by addresses, sort them by value
812
+ newResult := make ([]* SpendableOutput , 0 , len (result ))
813
+ for _ , s := range sums {
814
+ outputs := grouped [s .address ]
815
+ sort .Slice (outputs , func (i , j int ) bool {
816
+ return outputs [i ].Value > outputs [j ].Value
817
+ })
818
+ newResult = append (newResult , outputs ... )
819
+ }
820
+
821
+ return newResult
786
822
}
787
- func (p * byValue ) Swap (i , j int ) { p .outputs [i ], p .outputs [j ] = p .outputs [j ], p .outputs [i ] }
788
823
789
824
// SpendableOutput is an unspent coin.
790
825
type SpendableOutput struct {
@@ -811,8 +846,7 @@ func (account *Account) SpendableOutputs() []*SpendableOutput {
811
846
Address : account .getAddress (blockchain .NewScriptHashHex (txOut .TxOut .PkScript )),
812
847
})
813
848
}
814
- sort .Sort (sort .Reverse (& byValue {result }))
815
- return result
849
+ return sortByAddresses (result )
816
850
}
817
851
818
852
// VerifyExtendedPublicKey verifies an account's public key. Returns false, nil if no secure output
0 commit comments