diff --git a/exp/orderbook/search.go b/exp/orderbook/search.go index d701bc9dac..06b0f0f8b9 100644 --- a/exp/orderbook/search.go +++ b/exp/orderbook/search.go @@ -4,6 +4,7 @@ import ( "context" "github.com/stellar/go/price" + "github.com/stellar/go/support/ordered" "github.com/stellar/go/xdr" ) @@ -399,7 +400,7 @@ func (state *buyingGraphSearchState) consumeOffers( ) (xdr.Int64, error) { nextAmount, err := consumeOffersForBuyingAsset(offers, currentAssetAmount) - return max(nextAmount, currentBestAmount), err + return ordered.Max(nextAmount, currentBestAmount), err } func (state *buyingGraphSearchState) considerPools() bool { diff --git a/exp/orderbook/utils.go b/exp/orderbook/utils.go index d1fad24a62..ff0ac671ce 100644 --- a/exp/orderbook/utils.go +++ b/exp/orderbook/utils.go @@ -10,13 +10,6 @@ func getPoolAssets(pool xdr.LiquidityPoolEntry) (xdr.Asset, xdr.Asset) { return params.AssetA, params.AssetB } -func max(a, b xdr.Int64) xdr.Int64 { - if a < b { - return b - } - return a -} - // positiveMin returns the smallest positive value possible func positiveMin(a, b xdr.Int64) xdr.Int64 { if b <= 0 { diff --git a/go.mod b/go.mod index 455a363e42..3f7253aa1e 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/gobuffalo/packr v1.12.1 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.6 // indirect + github.com/google/go-cmp v0.5.8 // indirect github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 // indirect github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect @@ -107,15 +107,16 @@ require ( github.com/ziutek/mymysql v1.5.4 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.4.2 // indirect + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirect golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 - golang.org/x/tools v0.1.4 // indirect + golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 // indirect diff --git a/go.sum b/go.sum index 716ecad796..c714b5fe83 100644 --- a/go.sum +++ b/go.sum @@ -156,8 +156,9 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5 h1:oERTZ1buOUYlpmKaqlO5fYmz8cZ1rYu5DieJzF4ZVmU= github.com/google/go-querystring v0.0.0-20160401233042-9235644dd9e5/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -388,6 +389,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -413,8 +416,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -602,8 +606,9 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4 h1:cVngSRcfgyZCzys3KYOpCFa+4dqX/Oub9tAq00ttGVs= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/historyarchive/range.go b/historyarchive/range.go index 2610bf960e..da79827e24 100644 --- a/historyarchive/range.go +++ b/historyarchive/range.go @@ -6,8 +6,10 @@ package historyarchive import ( "fmt" - "sort" "strings" + + "github.com/stellar/go/support/ordered" + "golang.org/x/exp/slices" ) const DefaultCheckpointFrequency = uint32(64) @@ -54,10 +56,8 @@ func (c CheckpointManager) NextCheckpoint(i uint32) uint32 { freq := uint64(c.checkpointFreq) v := uint64(i) n := (((v + freq) / freq) * freq) - 1 - if n >= 0xffffffff { - return 0xffffffff - } - return uint32(n) + + return uint32(ordered.Min(n, 0xffffffff)) } // GetCheckPoint gets the checkpoint containing information about the given ledger sequence @@ -80,9 +80,7 @@ func (c CheckpointManager) GetCheckpointRange(i uint32) Range { } func (c CheckpointManager) MakeRange(low uint32, high uint32) Range { - if high < low { - high = low - } + high = ordered.Max(high, low) return Range{ Low: c.PrevCheckpoint(low), High: c.NextCheckpoint(high), @@ -90,14 +88,8 @@ func (c CheckpointManager) MakeRange(low uint32, high uint32) Range { } func (r Range) clamp(other Range, cManager CheckpointManager) Range { - low := r.Low - high := r.High - if low < other.Low { - low = other.Low - } - if high > other.High { - high = other.High - } + low := ordered.Max(r.Low, other.Low) + high := ordered.Min(r.High, other.High) return cManager.MakeRange(low, high) } @@ -123,24 +115,17 @@ func (r Range) SizeInCheckPoints(cManager CheckpointManager) int { func (r Range) collapsedString() string { if r.Low == r.High { return fmt.Sprintf("0x%8.8x", r.Low) - } else { - return fmt.Sprintf("[0x%8.8x-0x%8.8x]", r.Low, r.High) } + + return fmt.Sprintf("[0x%8.8x-0x%8.8x]", r.Low, r.High) } func (r Range) InRange(sequence uint32) bool { return sequence >= r.Low && sequence <= r.High } -type byUint32 []uint32 - -func (a byUint32) Len() int { return len(a) } -func (a byUint32) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byUint32) Less(i, j int) bool { return a[i] < a[j] } - func fmtRangeList(vs []uint32, cManager CheckpointManager) string { - - sort.Sort(byUint32(vs)) + slices.Sort(vs) s := make([]string, 0, 10) var curr *Range diff --git a/price/main.go b/price/main.go index 36c064e753..5effcb5d03 100644 --- a/price/main.go +++ b/price/main.go @@ -13,6 +13,7 @@ import ( "regexp" "strconv" + "github.com/stellar/go/support/ordered" "github.com/stellar/go/xdr" ) @@ -163,7 +164,7 @@ func ConvertToBuyingUnits(sellingOfferAmount int64, sellingUnitsNeeded int64, pr } // pathPaymentAmountBought - result = min(result, sellingUnitsNeeded) + result = ordered.Min(result, sellingUnitsNeeded) sellingUnitsExtracted := result // pathPaymentAmountSold @@ -218,11 +219,3 @@ func mulFractionRoundUp(x int64, n int64, d int64) (int64, error) { return int64(q), nil } - -// min impl for int64 -func min(x int64, y int64) int64 { - if x <= y { - return x - } - return y -} diff --git a/services/horizon/docker/verify-range/dependencies b/services/horizon/docker/verify-range/dependencies index fda36fdfe5..fa622f9d2e 100644 --- a/services/horizon/docker/verify-range/dependencies +++ b/services/horizon/docker/verify-range/dependencies @@ -11,8 +11,8 @@ echo "deb https://apt.stellar.org $(lsb_release -cs) stable" | sudo tee -a /etc/ apt-get update apt-get install -y stellar-core=${STELLAR_CORE_VERSION} -wget -q https://dl.google.com/go/go1.17.linux-amd64.tar.gz -tar -C /usr/local -xzf go1.17.linux-amd64.tar.gz +wget -q https://dl.google.com/go/go1.18.linux-amd64.tar.gz +tar -C /usr/local -xzf go1.18.linux-amd64.tar.gz git clone https://github.com/stellar/go.git stellar-go cd stellar-go diff --git a/services/horizon/internal/db2/history/ledger.go b/services/horizon/internal/db2/history/ledger.go index 5abf8eac79..7d367a8464 100644 --- a/services/horizon/internal/db2/history/ledger.go +++ b/services/horizon/internal/db2/history/ledger.go @@ -11,6 +11,7 @@ import ( "github.com/guregu/null" "github.com/stellar/go/services/horizon/internal/db2" "github.com/stellar/go/support/errors" + "github.com/stellar/go/support/ordered" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" ) @@ -153,20 +154,6 @@ func (q *Q) GetLedgerGaps(ctx context.Context) ([]LedgerRange, error) { return gaps, nil } -func max(a, b uint32) uint32 { - if a > b { - return a - } - return b -} - -func min(a, b uint32) uint32 { - if a > b { - return b - } - return a -} - // GetLedgerGapsInRange obtains ingestion gaps in the history_ledgers table within the given range. // Returns the gaps and error. func (q *Q) GetLedgerGapsInRange(ctx context.Context, start, end uint32) ([]LedgerRange, error) { @@ -189,7 +176,7 @@ func (q *Q) GetLedgerGapsInRange(ctx context.Context, start, end uint32) ([]Ledg if start < oldestLedger { result = append(result, LedgerRange{ StartSequence: start, - EndSequence: min(end, oldestLedger-1), + EndSequence: ordered.Min(end, oldestLedger-1), }) } if end <= oldestLedger { @@ -209,14 +196,14 @@ func (q *Q) GetLedgerGapsInRange(ctx context.Context, start, end uint32) ([]Ledg break } result = append(result, LedgerRange{ - StartSequence: max(gap.StartSequence, start), - EndSequence: min(gap.EndSequence, end), + StartSequence: ordered.Max(gap.StartSequence, start), + EndSequence: ordered.Min(gap.EndSequence, end), }) } if latestLedger < end { result = append(result, LedgerRange{ - StartSequence: max(latestLedger+1, start), + StartSequence: ordered.Max(latestLedger+1, start), EndSequence: end, }) } diff --git a/services/horizon/internal/db2/history/ledger_cache.go b/services/horizon/internal/db2/history/ledger_cache.go index 3318048ef7..a88ce5c71a 100644 --- a/services/horizon/internal/db2/history/ledger_cache.go +++ b/services/horizon/internal/db2/history/ledger_cache.go @@ -3,6 +3,7 @@ package history import ( "context" + "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/errors" ) @@ -11,10 +12,10 @@ func (lc *LedgerCache) Queue(seq int32) { lc.lock.Lock() if lc.queued == nil { - lc.queued = map[int32]struct{}{} + lc.queued = set.Set[int32]{} } - lc.queued[seq] = struct{}{} + lc.queued.Add(seq) lc.lock.Unlock() } diff --git a/services/horizon/internal/db2/history/main.go b/services/horizon/internal/db2/history/main.go index 05126f08dd..775f9bb14f 100644 --- a/services/horizon/internal/db2/history/main.go +++ b/services/horizon/internal/db2/history/main.go @@ -19,6 +19,7 @@ import ( "github.com/lib/pq" "github.com/stellar/go/services/horizon/internal/db2" + "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/db" "github.com/stellar/go/support/errors" strtime "github.com/stellar/go/support/time" @@ -580,7 +581,7 @@ type LedgerCache struct { Records map[int32]Ledger lock sync.Mutex - queued map[int32]struct{} + queued set.Set[int32] } type LedgerRange struct { diff --git a/services/horizon/internal/ingest/filters/account.go b/services/horizon/internal/ingest/filters/account.go index 601f67c8ee..b2372ae42d 100644 --- a/services/horizon/internal/ingest/filters/account.go +++ b/services/horizon/internal/ingest/filters/account.go @@ -6,10 +6,11 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/support/collections/set" ) type accountFilter struct { - whitelistedAccountsSet map[string]struct{} + whitelistedAccountsSet set.Set[string] lastModified int64 enabled bool } @@ -21,7 +22,7 @@ type AccountFilter interface { func NewAccountFilter() AccountFilter { return &accountFilter{ - whitelistedAccountsSet: map[string]struct{}{}, + whitelistedAccountsSet: set.Set[string]{}, } } @@ -32,7 +33,7 @@ func (filter *accountFilter) RefreshAccountFilter(filterConfig *history.AccountF logger.Infof("New Account Filter config detected, reloading new config %v ", *filterConfig) filter.enabled = filterConfig.Enabled - filter.whitelistedAccountsSet = listToMap(filterConfig.Whitelist) + filter.whitelistedAccountsSet = listToSet(filterConfig.Whitelist) filter.lastModified = filterConfig.LastModified } @@ -53,7 +54,7 @@ func (f *accountFilter) FilterTransaction(ctx context.Context, transaction inges // NOTE: this assumes that the participant list has a small memory footprint // otherwise, we should be doing the filtering on the DB side for _, p := range participants { - if _, ok := f.whitelistedAccountsSet[p.Address()]; ok { + if f.whitelistedAccountsSet.Contains(p.Address()) { return true, nil } } diff --git a/services/horizon/internal/ingest/filters/asset.go b/services/horizon/internal/ingest/filters/asset.go index f116eacb68..ee7a44deb9 100644 --- a/services/horizon/internal/ingest/filters/asset.go +++ b/services/horizon/internal/ingest/filters/asset.go @@ -3,12 +3,12 @@ package filters import ( "context" + "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/ingest/processors" + "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/log" "github.com/stellar/go/xdr" - - "github.com/stellar/go/ingest" ) var ( @@ -18,7 +18,7 @@ var ( ) type assetFilter struct { - canonicalAssetsLookup map[string]struct{} + canonicalAssetsLookup set.Set[string] lastModified int64 enabled bool } @@ -30,7 +30,7 @@ type AssetFilter interface { func NewAssetFilter() AssetFilter { return &assetFilter{ - canonicalAssetsLookup: map[string]struct{}{}, + canonicalAssetsLookup: set.Set[string]{}, } } @@ -40,7 +40,7 @@ func (filter *assetFilter) RefreshAssetFilter(filterConfig *history.AssetFilterC if filterConfig.LastModified > filter.lastModified { logger.Infof("New Asset Filter config detected, reloading new config %v ", *filterConfig) filter.enabled = filterConfig.Enabled - filter.canonicalAssetsLookup = listToMap(filterConfig.Whitelist) + filter.canonicalAssetsLookup = listToSet(filterConfig.Whitelist) filter.lastModified = filterConfig.LastModified } @@ -130,14 +130,13 @@ func (f assetFilter) filterChangeTrustMatched(operation xdr.Operation) bool { } func (f *assetFilter) assetMatchedFilter(asset *xdr.Asset) bool { - _, found := f.canonicalAssetsLookup[asset.StringCanonical()] - return found + return f.canonicalAssetsLookup.Contains(asset.StringCanonical()) } -func listToMap(list []string) map[string]struct{} { - set := make(map[string]struct{}, len(list)) +func listToSet(list []string) set.Set[string] { + set := set.NewSet[string](len(list)) for i := 0; i < len(list); i++ { - set[list[i]] = struct{}{} + set.Add(list[i]) } return set } diff --git a/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go b/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go index 2481687a57..33c8bfd9c6 100644 --- a/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go +++ b/services/horizon/internal/ingest/processors/claimable_balances_transaction_processor.go @@ -5,6 +5,7 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + set "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -12,22 +13,22 @@ import ( type claimableBalance struct { internalID int64 // Bigint auto-generated by postgres - transactionSet map[int64]struct{} - operationSet map[int64]struct{} + transactionSet set.Set[int64] + operationSet set.Set[int64] } func (b *claimableBalance) addTransactionID(id int64) { if b.transactionSet == nil { - b.transactionSet = map[int64]struct{}{} + b.transactionSet = set.Set[int64]{} } - b.transactionSet[id] = struct{}{} + b.transactionSet.Add(id) } func (b *claimableBalance) addOperationID(id int64) { if b.operationSet == nil { - b.operationSet = map[int64]struct{}{} + b.operationSet = set.Set[int64]{} } - b.operationSet[id] = struct{}{} + b.operationSet.Add(id) } type ClaimableBalancesTransactionProcessor struct { @@ -93,9 +94,9 @@ func claimableBalancesForTransaction( } func dedupeClaimableBalances(in []string) (out []string, err error) { - set := map[string]struct{}{} + set := set.Set[string]{} for _, id := range in { - set[id] = struct{}{} + set.Add(id) } for id := range set { diff --git a/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go b/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go index 91064b89fc..38010ddb51 100644 --- a/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go +++ b/services/horizon/internal/ingest/processors/liquidity_pools_transaction_processor.go @@ -5,6 +5,7 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + set "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -12,22 +13,22 @@ import ( type liquidityPool struct { internalID int64 // Bigint auto-generated by postgres - transactionSet map[int64]struct{} - operationSet map[int64]struct{} + transactionSet set.Set[int64] + operationSet set.Set[int64] } func (b *liquidityPool) addTransactionID(id int64) { if b.transactionSet == nil { - b.transactionSet = map[int64]struct{}{} + b.transactionSet = set.Set[int64]{} } - b.transactionSet[id] = struct{}{} + b.transactionSet.Add(id) } func (b *liquidityPool) addOperationID(id int64) { if b.operationSet == nil { - b.operationSet = map[int64]struct{}{} + b.operationSet = set.Set[int64]{} } - b.operationSet[id] = struct{}{} + b.operationSet.Add(id) } type LiquidityPoolsTransactionProcessor struct { @@ -93,9 +94,9 @@ func liquidityPoolsForTransaction( } func dedupeLiquidityPools(in []string) (out []string, err error) { - set := map[string]struct{}{} + set := set.Set[string]{} for _, id := range in { - set[id] = struct{}{} + set.Add(id) } for id := range set { diff --git a/services/horizon/internal/ingest/processors/participants_processor.go b/services/horizon/internal/ingest/processors/participants_processor.go index 517c253d92..d908f9ac69 100644 --- a/services/horizon/internal/ingest/processors/participants_processor.go +++ b/services/horizon/internal/ingest/processors/participants_processor.go @@ -7,6 +7,7 @@ import ( "github.com/stellar/go/ingest" "github.com/stellar/go/services/horizon/internal/db2/history" + set "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/errors" "github.com/stellar/go/toid" "github.com/stellar/go/xdr" @@ -30,22 +31,22 @@ func NewParticipantsProcessor(participantsQ history.QParticipants, sequence uint type participant struct { accountID int64 - transactionSet map[int64]struct{} - operationSet map[int64]struct{} + transactionSet set.Set[int64] + operationSet set.Set[int64] } func (p *participant) addTransactionID(id int64) { if p.transactionSet == nil { - p.transactionSet = map[int64]struct{}{} + p.transactionSet = set.Set[int64]{} } - p.transactionSet[id] = struct{}{} + p.transactionSet.Add(id) } func (p *participant) addOperationID(id int64) { if p.operationSet == nil { - p.operationSet = map[int64]struct{}{} + p.operationSet = set.Set[int64]{} } - p.operationSet[id] = struct{}{} + p.operationSet.Add(id) } func (p *ParticipantsProcessor) loadAccountIDs(ctx context.Context, participantSet map[string]participant) error { diff --git a/services/horizon/internal/integration/db_test.go b/services/horizon/internal/integration/db_test.go index 46dff40617..ba4c274d87 100644 --- a/services/horizon/internal/integration/db_test.go +++ b/services/horizon/internal/integration/db_test.go @@ -9,21 +9,21 @@ import ( "testing" "time" - "github.com/stellar/go/clients/horizonclient" - "github.com/stellar/go/keypair" - horizon "github.com/stellar/go/services/horizon/internal" - "github.com/stellar/go/services/horizon/internal/db2/history" - "github.com/stellar/go/xdr" - "github.com/stretchr/testify/assert" + "github.com/stellar/go/clients/horizonclient" "github.com/stellar/go/historyarchive" + "github.com/stellar/go/keypair" horizoncmd "github.com/stellar/go/services/horizon/cmd" + horizon "github.com/stellar/go/services/horizon/internal" + "github.com/stellar/go/services/horizon/internal/db2/history" "github.com/stellar/go/services/horizon/internal/db2/schema" "github.com/stellar/go/services/horizon/internal/test/integration" + "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/db" "github.com/stellar/go/support/db/dbtest" "github.com/stellar/go/txnbuild" + "github.com/stellar/go/xdr" ) func submitLiquidityPoolOps(itest *integration.Test, tt *assert.Assertions) (submittedOperations []txnbuild.Operation, lastLedger int32) { @@ -417,9 +417,9 @@ func initializeDBIntegrationTest(t *testing.T) (itest *integration.Test, reached submittedOps = append(submittedOps, ops...) // Make sure all possible operations are covered by reingestion - allOpTypes := map[xdr.OperationType]struct{}{} + allOpTypes := set.Set[xdr.OperationType]{} for typ := range xdr.OperationTypeToStringMap { - allOpTypes[xdr.OperationType(typ)] = struct{}{} + allOpTypes.Add(xdr.OperationType(typ)) } // Inflation is not supported delete(allOpTypes, xdr.OperationTypeInflation) diff --git a/services/keystore/cmd/keystored/main.go b/services/keystore/cmd/keystored/main.go index c5daf9d692..ceb930ffb9 100644 --- a/services/keystore/cmd/keystored/main.go +++ b/services/keystore/cmd/keystored/main.go @@ -18,6 +18,7 @@ import ( migrate "github.com/rubenv/sql-migrate" "github.com/sirupsen/logrus" "github.com/stellar/go/services/keystore" + "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/log" _ "github.com/lib/pq" @@ -247,13 +248,13 @@ func getUnappliedMigrations(db *sql.DB) []string { os.Exit(1) } - unappliedMigrations := make(map[string]struct{}) + unappliedMigrations := set.Set[string]{} for _, m := range migrations { - unappliedMigrations[m.Id] = struct{}{} + unappliedMigrations.Add(m.Id) } for _, r := range records { - if _, ok := unappliedMigrations[r.Id]; !ok { + if unappliedMigrations.Contains(r.Id) { fmt.Fprintf(os.Stdout, "Could not find migration file: %v\n", r.Id) continue } diff --git a/support/collections/set/set.go b/support/collections/set/set.go new file mode 100644 index 0000000000..0cad14dcd4 --- /dev/null +++ b/support/collections/set/set.go @@ -0,0 +1,20 @@ +package set + +type Set[T comparable] map[T]struct{} + +func NewSet[T comparable](capacity int) Set[T] { + return make(map[T]struct{}, capacity) +} + +func (set Set[T]) Add(item T) { + set[item] = struct{}{} +} + +func (set Set[T]) Remove(item T) { + delete(set, item) +} + +func (set Set[T]) Contains(item T) bool { + _, ok := set[item] + return ok +} diff --git a/support/collections/set/set_test.go b/support/collections/set/set_test.go new file mode 100644 index 0000000000..798aeea7d0 --- /dev/null +++ b/support/collections/set/set_test.go @@ -0,0 +1,14 @@ +package set + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSet(t *testing.T) { + s := Set[string]{} + s.Add("sanity") + require.True(t, s.Contains("sanity")) + require.False(t, s.Contains("check")) +} diff --git a/support/ordered/math.go b/support/ordered/math.go new file mode 100644 index 0000000000..a07f7064c4 --- /dev/null +++ b/support/ordered/math.go @@ -0,0 +1,21 @@ +package ordered + +import ( + "golang.org/x/exp/constraints" +) + +// Min returns the smaller of the given items. +func Min[T constraints.Ordered](a, b T) T { + if a <= b { + return a + } + return b +} + +// Min returns the larger of the given items. +func Max[T constraints.Ordered](a, b T) T { + if a > b { + return a + } + return b +} diff --git a/support/ordered/math_test.go b/support/ordered/math_test.go new file mode 100644 index 0000000000..5e5568ded0 --- /dev/null +++ b/support/ordered/math_test.go @@ -0,0 +1,27 @@ +package ordered + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMinMax(t *testing.T) { + t.Run("int", func(tt *testing.T) { + a, b := -5, 10 + require.Equal(tt, Min(a, b), a) + require.Equal(tt, Max(a, b), b) + }) + + t.Run("float", func(tt *testing.T) { + a, b := -5.0, 10.0 + require.Equal(tt, Min(a, b), a) + require.Equal(tt, Max(a, b), b) + }) + + t.Run("unsigned", func(tt *testing.T) { + a, b := uint(5), uint(10) + require.Equal(tt, Min(a, b), a) + require.Equal(tt, Max(a, b), b) + }) +} diff --git a/txnbuild/transaction.go b/txnbuild/transaction.go index 5e4849db6f..ce95bba2ff 100644 --- a/txnbuild/transaction.go +++ b/txnbuild/transaction.go @@ -24,6 +24,7 @@ import ( "github.com/stellar/go/keypair" "github.com/stellar/go/network" "github.com/stellar/go/strkey" + "github.com/stellar/go/support/collections/set" "github.com/stellar/go/support/errors" "github.com/stellar/go/xdr" ) @@ -1302,7 +1303,7 @@ func VerifyChallengeTxSigners(challengeTx, serverAccountID, network, webAuthDoma // Deduplicate the client signers and ensure the server is not included // anywhere we check or output the list of signers. clientSigners := []string{} - clientSignersSeen := map[string]struct{}{} + clientSignersSeen := set.Set[string]{} for _, signer := range signers { // Ignore the server signer if it is in the signers list. It's // important when verifying signers of a challenge transaction that we @@ -1313,7 +1314,7 @@ func VerifyChallengeTxSigners(challengeTx, serverAccountID, network, webAuthDoma continue } // Deduplicate. - if _, seen := clientSignersSeen[signer]; seen { + if clientSignersSeen.Contains(signer) { continue } // Ignore non-G... account/address signers. @@ -1325,7 +1326,7 @@ func VerifyChallengeTxSigners(challengeTx, serverAccountID, network, webAuthDoma continue } clientSigners = append(clientSigners, signer) - clientSignersSeen[signer] = struct{}{} + clientSignersSeen.Add(signer) } // Don't continue if none of the signers provided are in the final list. @@ -1392,7 +1393,7 @@ func verifyTxSignatures(tx *Transaction, network string, signers ...string) ([]s // find and verify signatures signatureUsed := map[int]bool{} - signersFound := map[string]struct{}{} + signersFound := set.Set[string]{} for _, signer := range signers { kp, err := keypair.ParseAddress(signer) if err != nil { @@ -1409,7 +1410,7 @@ func verifyTxSignatures(tx *Transaction, network string, signers ...string) ([]s err := kp.Verify(txHash[:], decSig.Signature) if err == nil { signatureUsed[i] = true - signersFound[signer] = struct{}{} + signersFound.Add(signer) break } } @@ -1417,7 +1418,7 @@ func verifyTxSignatures(tx *Transaction, network string, signers ...string) ([]s signersFoundList := make([]string, 0, len(signersFound)) for _, signer := range signers { - if _, ok := signersFound[signer]; ok { + if signersFound.Contains(signer) { signersFoundList = append(signersFoundList, signer) delete(signersFound, signer) }