diff --git a/go.mod b/go.mod index 17ebad9..31e8226 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/ice-blockchain/eskimo v1.326.0 github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb - github.com/ice-blockchain/wintr v1.140.0 + github.com/ice-blockchain/wintr v1.141.0 github.com/imroc/req/v3 v3.43.7 github.com/oklog/ulid/v2 v2.1.0 github.com/pkg/errors v0.9.1 @@ -110,7 +110,7 @@ require ( github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.4 // indirect + github.com/googleapis/gax-go/v2 v2.12.5 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -207,7 +207,7 @@ require ( golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.22.0 // indirect - google.golang.org/api v0.184.0 // indirect + google.golang.org/api v0.185.0 // indirect google.golang.org/appengine/v2 v2.0.6 // indirect google.golang.org/genproto v0.0.0-20240617180043-68d350f18fd4 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect diff --git a/go.sum b/go.sum index f56599c..ebac65c 100644 --- a/go.sum +++ b/go.sum @@ -273,8 +273,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= @@ -304,8 +304,8 @@ github.com/ice-blockchain/eskimo v1.326.0 h1:MNey0egcmR42Lsmi2A4nnl3h2nYKWkyQIry github.com/ice-blockchain/eskimo v1.326.0/go.mod h1:ACvCKV6SSS+B/AudcS1zHzQ8BiMpsgk1PyeokF4ybxY= github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb h1:8TnFP3mc7O+tc44kv2e0/TpZKnEVUaKH+UstwfBwRkk= github.com/ice-blockchain/go-tarantool-client v0.0.0-20230327200757-4fc71fa3f7bb/go.mod h1:ZsQU7i3mxhgBBu43Oev7WPFbIjP4TniN/b1UPNGbrq8= -github.com/ice-blockchain/wintr v1.140.0 h1:OGjjZHCD5WWcJ8BRQ5Dmv1xGSPe8DvqSuPwtpXZxUC4= -github.com/ice-blockchain/wintr v1.140.0/go.mod h1:TFymLSdt+kCAydDS9qmt37+quPUS6Amd5RMvV/4q77g= +github.com/ice-blockchain/wintr v1.141.0 h1:JkQkjXoXLmnLh3hoRzr1SbiVXvdzNaWrkHjRxQqS1yQ= +github.com/ice-blockchain/wintr v1.141.0/go.mod h1:6INwquKAzF28T1DwAh/n3fPTpuyGQQz9cSUbDjxSCAY= github.com/imroc/req/v3 v3.43.7 h1:dOcNb9n0X83N5/5/AOkiU+cLhzx8QFXjv5MhikazzQA= github.com/imroc/req/v3 v3.43.7/go.mod h1:SQIz5iYop16MJxbo8ib+4LnostGCok8NQf8ToyQc2xA= github.com/ip2location/ip2location-go/v9 v9.7.0 h1:ipwl67HOWcrw+6GOChkEXcreRQR37NabqBd2ayYa4Q0= @@ -674,8 +674,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -google.golang.org/api v0.184.0 h1:dmEdk6ZkJNXy1JcDhn/ou0ZUq7n9zropG2/tR4z+RDg= -google.golang.org/api v0.184.0/go.mod h1:CeDTtUEiYENAf8PPG5VZW2yNp2VM3VWbCeTioAZBTBA= +google.golang.org/api v0.185.0 h1:ENEKk1k4jW8SmmaT6RE+ZasxmxezCrD5Vw4npvr+pAU= +google.golang.org/api v0.185.0/go.mod h1:HNfvIkJGlgrIlrbYkAm9W9IdkmKZjOTVh33YltygGbg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine/v2 v2.0.6 h1:LvPZLGuchSBslPBp+LAhihBeGSiRh1myRoYK4NtuBIw= diff --git a/miner/metrics.go b/miner/metrics.go index b8f9e57..44ca834 100644 --- a/miner/metrics.go +++ b/miner/metrics.go @@ -19,7 +19,7 @@ func init() { type telemetry struct { registry metrics.Registry - steps [10]string + steps [11]string currentStepName string cfg config } @@ -31,7 +31,7 @@ func (t *telemetry) mustInit(cfg config) *telemetry { ) t.cfg = cfg t.registry = metrics.NewRegistry() - t.steps = [10]string{"mine[full iteration]", "mine", "get_users", "get_referrals", "send_messages", "get_history", "sync_quiz_status", "insert_history", "collect_coin_distributions", "update_users"} //nolint:lll // . + t.steps = [11]string{"mine[full iteration]", "mine", "get_users", "get_referrals", "get_t1_rankings", "send_messages", "get_history", "sync_quiz_status", "insert_history", "collect_coin_distributions", "update_users"} //nolint:lll // . for ix := range &t.steps { if ix > 1 { t.steps[ix] = fmt.Sprintf("[%v]mine.%v", ix-1, t.steps[ix]) diff --git a/miner/miner.go b/miner/miner.go index 31bebe9..35b2208 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -167,6 +167,7 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { t0Referrals, tMinus1Referrals = make(map[int64]*referral, batchSize), make(map[int64]*referral, batchSize) t1ReferralsToIncrementActiveValue, t2ReferralsToIncrementActiveValue = make(map[int64]int32, batchSize), make(map[int64]int32, batchSize) t1ReferralsThatStoppedMining, t2ReferralsThatStoppedMining = make(map[int64]uint32, batchSize), make(map[int64]uint32, batchSize) + activeReferralsOfT0, activeReferralsOfT0RankingKeys = make(map[int64]map[int64]struct{}, batchSize), make(map[string]int64, batchSize) balanceT1EthereumIncr, balanceT2EthereumIncr = make(map[int64]float64, batchSize), make(map[int64]float64, batchSize) pendingBalancesForTMinus1, pendingBalancesForT0 = make(map[int64]float64, batchSize), make(map[int64]float64, batchSize) referralsThatStoppedMining = make([]*referralThatStoppedMining, 0, batchSize) @@ -246,6 +247,12 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { for k := range t2ReferralsToIncrementActiveValue { delete(t2ReferralsToIncrementActiveValue, k) } + for k := range activeReferralsOfT0RankingKeys { + delete(activeReferralsOfT0RankingKeys, k) + } + for k := range activeReferralsOfT0 { + delete(activeReferralsOfT0, k) + } for k := range balanceT1EthereumIncr { delete(balanceT1EthereumIncr, k) } @@ -327,10 +334,6 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { go m.telemetry.collectElapsed(3, *before.Time) } - /****************************************************************************************************************************************************** - 3. Mining for the users. - ******************************************************************************************************************************************************/ - for _, ref := range referralResults { if !isAdvancedTeamDisabled(ref.LatestDevice) { if _, found := tMinus1Referrals[ref.ID]; found { @@ -341,6 +344,65 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { t0Referrals[ref.ID] = ref } } + + /****************************************************************************************************************************************************** + 3. Fetch ranking of active T1 referrals (N most recent active), to update ForT0Balance for them + ******************************************************************************************************************************************************/ + for idT0 := range t0Referrals { + t0Ref := t0Referrals[idT0] + if t0Ref.MiningBoostLevelIndex != nil { + activeReferralsOfT0RankingKeys[fmt.Sprintf("%v_active_t1_referrals_ranking", idT0)] = idT0 + } + } + if len(activeReferralsOfT0RankingKeys) > 0 { + before = time.Now() + reqCtx, reqCancel = context.WithTimeout(context.Background(), requestDeadline) + if zRangeResult, zErr := m.db.Pipelined(reqCtx, func(pipeliner redis.Pipeliner) error { + for key, t0Id := range activeReferralsOfT0RankingKeys { + t0Ref := t0Referrals[t0Id] + rangeBy := &redis.ZRangeBy{Min: "0", Max: "+inf", Offset: int64(0), Count: int64((*cfg.miningBoostLevels.Load())[int(*t0Ref.MiningBoostLevelIndex)].MaxT1Referrals)} + if _, err := pipeliner.ZRevRangeByScore(ctx, key, rangeBy).Result(); err != nil { + return err + } + } + return nil + }); zErr != nil { + log.Error(errors.Wrapf(zErr, "[miner] failed to get active T1 referrals ranking for batchNumber:%v,workerNumber:%v", batchNumber, workerNumber)) + reqCancel() + resetVars(false) + + continue + } else { + reqCancel() + for _, cmdRes := range zRangeResult { + if cmdRes.Err() != nil { + errs = append(errs, errors.Wrapf(cmdRes.Err(), "failed to fetch active referrals ranking %#v for batchNumber:%v,workerNumber:%v", cmdRes.Args(), batchNumber, workerNumber)) + continue + } + sliceRes := cmdRes.(*redis.StringSliceCmd) + key := sliceRes.Args()[1].(string) + ids := make(map[int64]struct{}, 0) + for _, v := range sliceRes.Val() { + id, _ := strconv.Atoi(v) + ids[int64(id)] = struct{}{} + } + activeReferralsOfT0[activeReferralsOfT0RankingKeys[key]] = ids + } + if cmdErr := multierror.Append(nil, errs...).ErrorOrNil(); cmdErr != nil { + log.Error(errors.Wrapf(cmdErr, "[miner] failed to get active T1 referrals ranking for batchNumber:%v,workerNumber:%v", batchNumber, workerNumber)) + reqCancel() + resetVars(false) + + continue + } + } + go m.telemetry.collectElapsed(4, *before.Time) + } + + /****************************************************************************************************************************************************** + 4. Mining for the users. + ******************************************************************************************************************************************************/ + shouldSynchronizeBalance := shouldSynchronizeBalanceFunc(uint64(batchNumber)) for _, usr := range userResults { if usr.UserID == "" { @@ -362,7 +424,13 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { if isAdvancedTeamDisabled(usr.LatestDevice) { usr.ActiveT2Referrals = 0 } - updatedUser, shouldGenerateHistory, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(now, usr, t0Ref, tMinus1Ref) + userFittingToT0RefLimit := false + if t0Ref != nil { + if t0ActiveRefs, t0HasActiveRefs := activeReferralsOfT0[t0Ref.ID]; t0HasActiveRefs { + _, userFittingToT0RefLimit = t0ActiveRefs[usr.ID] + } + } + updatedUser, shouldGenerateHistory, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(now, usr, t0Ref, tMinus1Ref, userFittingToT0RefLimit) if shouldGenerateHistory { syncQuizUserIDs = append(syncQuizUserIDs, usr.UserID) userHistoryKeys = append(userHistoryKeys, usr.Key()) @@ -433,11 +501,14 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { } /****************************************************************************************************************************************************** - 4. Sending messages to the broker. + 5. Sending messages to the broker. ******************************************************************************************************************************************************/ before = time.Now() reqCtx, reqCancel = context.WithTimeout(context.Background(), requestDeadline) + if len(errs) != 0 { + errs = errs[:0] + } for _, message := range msgs { m.mb.SendMessage(reqCtx, message, msgResponder) } @@ -453,11 +524,11 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { } reqCancel() if len(msgs) > 0 { - go m.telemetry.collectElapsed(4, *before.Time) + go m.telemetry.collectElapsed(5, *before.Time) } /****************************************************************************************************************************************************** - 5. Fetching all relevant fields that will be added to the history/bookkeeping. + 6. Fetching all relevant fields that will be added to the history/bookkeeping. ******************************************************************************************************************************************************/ before = time.Now() @@ -472,11 +543,11 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { reqCancel() if len(userHistoryKeys) > 0 { - go m.telemetry.collectElapsed(5, *before.Time) + go m.telemetry.collectElapsed(6, *before.Time) } /****************************************************************************************************************************************************** - 6. Syncing quiz state + 7. Syncing quiz state ******************************************************************************************************************************************************/ before = time.Now() if false && (len(syncQuizUserIDs) > 0 && len(histories) > 0) { @@ -498,12 +569,12 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { histories[i].KYCQuizCompleted = quizSync.KYCQuizCompleted } } - go m.telemetry.collectElapsed(6, *before.Time) + go m.telemetry.collectElapsed(7, *before.Time) } } /****************************************************************************************************************************************************** - 7. Inserting history/bookkeeping data. + 8. Inserting history/bookkeeping data. ******************************************************************************************************************************************************/ before = time.Now() @@ -517,11 +588,11 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { } reqCancel() if len(histories) > 0 { - go m.telemetry.collectElapsed(7, *before.Time) + go m.telemetry.collectElapsed(8, *before.Time) } /****************************************************************************************************************************************************** - 8. Processing Ethereum Coin Distributions for eligible users. + 9. Processing Ethereum Coin Distributions for eligible users. ******************************************************************************************************************************************************/ before = time.Now() @@ -535,11 +606,11 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { } reqCancel() if len(coinDistributions) > 0 { - go m.telemetry.collectElapsed(8, *before.Time) + go m.telemetry.collectElapsed(9, *before.Time) } /****************************************************************************************************************************************************** - 9. Persisting the mining progress for the users. + 10. Persisting the mining progress for the users. ******************************************************************************************************************************************************/ for _, usr := range referralsThatStoppedMining { @@ -667,7 +738,7 @@ func (m *miner) mine(ctx context.Context, workerNumber int64) { } } if transactional || len(updatedUsers) > 0 { - go m.telemetry.collectElapsed(9, *before.Time) + go m.telemetry.collectElapsed(10, *before.Time) } batchNumber++ diff --git a/miner/mining.go b/miner/mining.go index 685ed2b..64be805 100644 --- a/miner/mining.go +++ b/miner/mining.go @@ -9,7 +9,7 @@ import ( "github.com/ice-blockchain/wintr/time" ) -func mine(now *time.Time, usr *user, t0Ref, tMinus1Ref *referral) (updatedUser *user, shouldGenerateHistory, IDT0Changed bool, pendingAmountForTMinus1, pendingAmountForT0 float64) { +func mine(now *time.Time, usr *user, t0Ref, tMinus1Ref *referral, userFittingToT0RefLimit bool) (updatedUser *user, shouldGenerateHistory, IDT0Changed bool, pendingAmountForTMinus1, pendingAmountForT0 float64) { if usr == nil || usr.MiningSessionSoloStartedAt.IsNil() || usr.MiningSessionSoloEndedAt.IsNil() { return nil, false, false, 0, 0 } @@ -119,7 +119,9 @@ func mine(now *time.Time, usr *user, t0Ref, tMinus1Ref *referral) (updatedUser * } if t0Ref != nil && !t0Ref.MiningSessionSoloEndedAt.IsNil() && t0Ref.MiningSessionSoloEndedAt.After(*now.Time) { rate := 25 * baseMiningRate * elapsedTimeFraction / 100 - updatedUser.BalanceForT0 += rate + if userFittingToT0RefLimit { + updatedUser.BalanceForT0 += rate + } updatedUser.BalanceT0 += rate mintedAmount += rate diff --git a/miner/mining_test.go b/miner/mining_test.go index 6a5dc5f..bc625d5 100644 --- a/miner/mining_test.go +++ b/miner/mining_test.go @@ -48,7 +48,7 @@ func testSoloMiningNoExtraBonus(t *testing.T) { t.Run("No referrals", func(t *testing.T) { m := newUser() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, testMiningBase, m.BalanceSolo) require.False(t, IDT0Changed) @@ -61,7 +61,7 @@ func testSoloMiningNoExtraBonus(t *testing.T) { m := newUser() ref := newRef() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -72,12 +72,27 @@ func testSoloMiningNoExtraBonus(t *testing.T) { require.EqualValues(t, 0, pendingAmountForTMinus1) require.EqualValues(t, 0, pendingAmountForT0) }) + t.Run("With T0 but user is not active for T0 (out of ref limit)", func(t *testing.T) { + m := newUser() + ref := newRef() + + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, false) + require.NotNil(t, m) + require.EqualValues(t, 16, m.BalanceSolo) + require.EqualValues(t, 4, m.BalanceT0) + require.EqualValues(t, 0, m.BalanceForT0) + require.False(t, IDT0Changed) + require.EqualValues(t, 0, m.IDT0) + require.EqualValues(t, 0, m.IDTMinus1) + require.EqualValues(t, 0, pendingAmountForTMinus1) + require.EqualValues(t, 0, pendingAmountForT0) + }) t.Run("For tMinus1", func(t *testing.T) { m := newUser() ref := newRef() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) @@ -96,7 +111,7 @@ func testSoloMiningNoExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 8, m.BalanceT1) @@ -114,7 +129,7 @@ func testSoloMiningNoExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, tMinus1Ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, tMinus1Ref, true) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -133,7 +148,7 @@ func testSoloMiningNoExtraBonus(t *testing.T) { m := newUser() m.ActiveT2Referrals = 20 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 16, m.BalanceT2) @@ -154,7 +169,7 @@ func testSoloMiningNoExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, tMinus1Ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, tMinus1Ref, true) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -178,7 +193,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { m.ExtraBonusStartedAt = timeDelta(stdlibtime.Hour) m.ExtraBonus = 100 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.False(t, IDT0Changed) @@ -196,7 +211,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { m.ExtraBonus = 100 ref := newRef() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -216,7 +231,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { m.ExtraBonus = 100 ref := newRef() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 0.8, m.BalanceForTMinus1) @@ -237,7 +252,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 8, m.BalanceT1) @@ -258,7 +273,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -278,7 +293,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { m.ExtraBonusStartedAt = timeDelta(stdlibtime.Hour) m.ExtraBonus = 100 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 16, m.BalanceT2) @@ -301,7 +316,7 @@ func testSoloMiningWithExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, refMinus) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, refMinus, true) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -325,7 +340,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { m.PreStakingBonus = 200 m.PreStakingAllocation = 50 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.False(t, IDT0Changed) @@ -342,7 +357,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { m.PreStakingAllocation = 50 ref := newRef() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -363,7 +378,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 0.8, m.BalanceForTMinus1) @@ -383,7 +398,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 8, m.BalanceT1) @@ -404,7 +419,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -426,7 +441,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 16, m.BalanceT2) @@ -449,7 +464,7 @@ func testSoloMiningWithPreStaking(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, refMinus) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, refMinus, true) require.NotNil(t, m) require.EqualValues(t, 16, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -475,7 +490,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { m.ExtraBonus = 100 m.ExtraBonusStartedAt = timeDelta(stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.False(t, IDT0Changed) @@ -494,7 +509,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { m.ExtraBonusStartedAt = timeDelta(stdlibtime.Hour) ref := newRef() - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -517,7 +532,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 0.8, m.BalanceForTMinus1) @@ -539,7 +554,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 8, m.BalanceT1) @@ -562,7 +577,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -586,7 +601,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 16, m.BalanceT2) @@ -611,7 +626,7 @@ func testSoloMiningWithPreStakingAndExtraBonus(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, refMinus) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, refMinus, true) require.NotNil(t, m) require.EqualValues(t, 32, m.BalanceSolo) require.EqualValues(t, 4, m.BalanceT0) @@ -653,7 +668,7 @@ func testNegativeMiningSoloSlashing(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(1) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m1, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m1, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.Nil(t, m1) require.EqualValues(t, 0, pendingAmountForTMinus1) @@ -665,7 +680,7 @@ func testNegativeMiningSoloSlashing(t *testing.T) { m.MiningSessionSoloEndedAt = timeDelta(-168 * stdlibtime.Hour) m.MiningBoostLevelIndex = nil - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 6, m.SlashingRateSolo) @@ -701,7 +716,7 @@ func testNegativeMiningT0Slashing(t *testing.T) { ref.MiningSessionSoloStartedAt = timeDelta(-25 * stdlibtime.Hour) ref.MiningSessionSoloEndedAt = timeDelta(-stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 0, m.SlashingRateSolo) @@ -723,7 +738,7 @@ func testNegativeMiningT0Slashing(t *testing.T) { ref.MiningSessionSoloStartedAt = timeDelta(-192 * stdlibtime.Hour) ref.MiningSessionSoloEndedAt = timeDelta(-168 * stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, ref, nil, true) require.EqualValues(t, 0, m.SlashingRateSolo) require.EqualValues(t, 6, m.SlashingRateT0) @@ -756,7 +771,7 @@ func testNegativeMiningT0SlashingSoloSlashing(t *testing.T) { ref.MiningSessionSoloStartedAt = timeDelta(-25 * stdlibtime.Hour) ref.MiningSessionSoloEndedAt = timeDelta(-stdlibtime.Hour) - m1, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil) + m1, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, ref, nil, true) require.Nil(t, m1) require.EqualValues(t, 0, pendingAmountForTMinus1) @@ -772,7 +787,7 @@ func testNegativeMiningT0SlashingSoloSlashing(t *testing.T) { ref.MiningSessionSoloEndedAt = timeDelta(-168 * stdlibtime.Hour) m.MiningBoostLevelIndex = nil - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 6, m.SlashingRateSolo) @@ -808,7 +823,7 @@ func testNegativeMiningT1minusSlashingSoloMining(t *testing.T) { ref.MiningSessionSoloStartedAt = timeDelta(-25 * stdlibtime.Hour) ref.MiningSessionSoloEndedAt = timeDelta(-stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 0, m.SlashingRateSolo) @@ -830,7 +845,7 @@ func testNegativeMiningT1minusSlashingSoloMining(t *testing.T) { m.IDT0 = testIDT0 m.IDTMinus1 = testIDTMinus1 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 6.066666666666666, m.SlashingRateSolo) @@ -865,7 +880,7 @@ func testMiningResurrectT0(t *testing.T) { t0Ref.MiningSessionSoloPreviouslyEndedAt = timeDelta(-24 * 10 * stdlibtime.Hour) t0Ref.ResurrectSoloUsedAt = timeDelta(stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, t0Ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, t0Ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 3840, m.BalanceForT0) @@ -892,7 +907,7 @@ func testMiningResurrectT0ResetSlashing(t *testing.T) { t0Ref.MiningSessionSoloPreviouslyEndedAt = timeDelta(-24 * 10 * stdlibtime.Hour) m.ResurrectT0UsedAt = timeDelta(stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, t0Ref, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, t0Ref, nil, true) require.NotNil(t, m) require.EqualValues(t, 0, m.SlashingRateForT0) require.False(t, IDT0Changed) @@ -917,7 +932,7 @@ func testMiningResurrectTMinus1ResetSlashing(t *testing.T) { ref.MiningSessionSoloPreviouslyEndedAt = timeDelta(-24 * 10 * stdlibtime.Hour) m.ResurrectTMinus1UsedAt = timeDelta(stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 0, m.SlashingRateForTMinus1) require.False(t, IDT0Changed) @@ -938,7 +953,7 @@ func testMiningResurrectSolo(t *testing.T) { m.BalanceForT0 = 1440 m.BalanceForTMinus1 = 1440 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 2400, m.BalanceSolo) require.EqualValues(t, 0, m.SlashingRateSolo) @@ -964,7 +979,7 @@ func testMiningResurrectT1(t *testing.T) { ref.MiningSessionSoloPreviouslyEndedAt = timeDelta(-24 * 10 * stdlibtime.Hour) ref.ResurrectSoloUsedAt = timeDelta(stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, ref, false) require.NotNil(t, m) require.EqualValues(t, 3840, m.BalanceForTMinus1) require.EqualValues(t, 0, m.SlashingRateForTMinus1) @@ -999,7 +1014,7 @@ func Test_BalancePositive(t *testing.T) { func Test_MinerNil(t *testing.T) { t.Parallel() - m, h, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, nil, nil, nil) + m, h, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, nil, nil, nil, false) require.Nil(t, m) require.False(t, h) require.False(t, IDT0Changed) @@ -1023,7 +1038,7 @@ func Test_MinerPending(t *testing.T) { m.BalanceForTMinus1 = 1440 m.BalanceSolo = 1440 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 2.0, m.BalanceT1PendingApplied) require.EqualValues(t, 2.0, m.BalanceT2PendingApplied) @@ -1054,7 +1069,7 @@ func Test_MinerPending(t *testing.T) { m.BalanceForTMinus1 = 1440 m.BalanceSolo = 1440 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, -4, m.BalanceT1PendingApplied) require.EqualValues(t, -4, m.BalanceT2PendingApplied) @@ -1083,7 +1098,7 @@ func Test_MinerPending(t *testing.T) { m.BalanceForT0 = 1440 m.BalanceForTMinus1 = 1440 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, -4, m.BalanceT1PendingApplied) require.EqualValues(t, -4, m.BalanceT2PendingApplied) @@ -1110,7 +1125,7 @@ func Test_MinerPending(t *testing.T) { m.BalanceForT0 = 1440 m.BalanceForTMinus1 = 1440 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.Nil(t, m) require.False(t, IDT0Changed) require.EqualValues(t, 0, pendingAmountForTMinus1) @@ -1126,7 +1141,7 @@ func Test_MinerWithHistory(t *testing.T) { m.BalanceForT0 = 1440 m.BalanceForTMinus1 = 1440 - m, h, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, h, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.False(t, h) @@ -1145,7 +1160,7 @@ func Test_MinerWithHistory(t *testing.T) { m.BalanceForT0 = 1440 m.BalanceForTMinus1 = 1440 - m, h, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, nil) + m, h, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.True(t, h) @@ -1175,7 +1190,7 @@ func Test_MinerNegativeBalance(t *testing.T) { m.ActiveT1Referrals = -7 m.ActiveT2Referrals = -8 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.Zero(t, m.BalanceSolo) @@ -1207,7 +1222,7 @@ func testMinerPendingSlashingSolo(t *testing.T) { m.BalanceForT0 = 1440 m.BalanceForTMinus1 = 1440 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1., m.BalanceSoloPendingApplied) require.False(t, IDT0Changed) @@ -1229,7 +1244,7 @@ func testMinerPendingSlashingT1(t *testing.T) { m.BalanceT1Pending = 1 m.BalanceT1PendingApplied = 3 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1., m.BalanceT1PendingApplied) require.False(t, IDT0Changed) @@ -1249,7 +1264,7 @@ func testMinerPendingSlashingT2(t *testing.T) { m.BalanceT2Pending = 1 m.BalanceT2PendingApplied = 3 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1., m.BalanceT2PendingApplied) require.False(t, IDT0Changed) @@ -1283,7 +1298,7 @@ func testMinerPendingSlashingSolo_BonusPrizeCase(t *testing.T) { ref.MiningSessionSoloStartedAt = timeDelta(-192 * stdlibtime.Hour) ref.MiningSessionSoloEndedAt = timeDelta(-168 * stdlibtime.Hour) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 6, m.SlashingRateSolo) require.EqualValues(t, 0, m.SlashingRateT0) @@ -1305,7 +1320,7 @@ func testMinerPendingSlashingSolo_BonusPrizeCase(t *testing.T) { require.EqualValues(t, 0, m.IDTMinus1) m.BalanceSoloPending += 5000 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 6314, m.BalanceSolo) require.EqualValues(t, 26.833333333333332, m.SlashingRateSolo) @@ -1327,7 +1342,7 @@ func testMinerPendingSlashingSolo_BonusPrizeCase(t *testing.T) { require.EqualValues(t, testIDT0, m.IDT0) require.EqualValues(t, 0, m.IDTMinus1) - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(time.New(testTime.Add(-1*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(time.New(testTime.Add(-1*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 6287.166666666667, m.BalanceSolo) require.EqualValues(t, 26.833333333333332, m.SlashingRateSolo) @@ -1352,7 +1367,7 @@ func testMinerPendingSlashingSolo_BonusPrizeCase(t *testing.T) { m.BalanceSoloPending = 5000. m.BalanceSoloPendingApplied = 5000. - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 = mine(testTime, m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 6260.333333333334, m.BalanceSolo) require.EqualValues(t, 26.833333333333332, m.SlashingRateSolo) @@ -1396,7 +1411,7 @@ func testT0NotChanged(t *testing.T) { m.IDT0 = testIDT0 m.IDTMinus1 = testIDTMinus1 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 318., m.BalanceSolo) require.EqualValues(t, 1440, m.BalanceT2) @@ -1426,7 +1441,7 @@ func testT0Changed(t *testing.T) { m.IDT0 = -testIDT0 m.IDTMinus1 = -testIDTMinus1 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 318., m.BalanceSolo) require.EqualValues(t, 1440, m.BalanceT2) @@ -1456,7 +1471,7 @@ func testOnlyTMinus1Changed(t *testing.T) { m.IDT0 = testIDT0 m.IDTMinus1 = -testIDTMinus1 - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 318., m.BalanceSolo) require.EqualValues(t, 1440, m.BalanceT2) @@ -1597,7 +1612,7 @@ func testMinerTier1Limit_0(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1456., m.BalanceSolo) require.EqualValues(t, 1440., m.BalanceT1) @@ -1629,7 +1644,7 @@ func testMinerTier1Limit_1(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1456., m.BalanceSolo) require.EqualValues(t, 1444., m.BalanceT1) @@ -1661,7 +1676,7 @@ func testMinerTier1Limit_2(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1456., m.BalanceSolo) require.EqualValues(t, 1448., m.BalanceT1) @@ -1693,7 +1708,7 @@ func testMinerTier1Limit_1000(t *testing.T) { slashingDisabledMiningBoostIx := model.FlexibleUint64(2) m.MiningBoostLevelIndex = &slashingDisabledMiningBoostIx - m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil) + m, _, IDT0Changed, pendingAmountForTMinus1, pendingAmountForT0 := mine(time.New(testTime.Add(-2*stdlibtime.Hour)), m, nil, nil, false) require.NotNil(t, m) require.EqualValues(t, 1456., m.BalanceSolo) require.EqualValues(t, 1448., m.BalanceT1) diff --git a/tokenomics/mining_sessions.go b/tokenomics/mining_sessions.go index 10fb364..21e64c6 100644 --- a/tokenomics/mining_sessions.go +++ b/tokenomics/mining_sessions.go @@ -294,9 +294,62 @@ func (s *miningSessionsTableSource) Process(ctx context.Context, msg *messagebro return multierror.Append( //nolint:wrapcheck // Not needed. errors.Wrapf(s.incrementTotalActiveUsers(ctx, ms), "failed to incrementTotalActiveUsers for %#v", ms), errors.Wrapf(s.incrementActiveReferralCountForT0AndTMinus1(ctx, ms), "failed to incrementActiveReferralCountForT0AndTMinus1 for %#v", ms), + errors.Wrapf(s.rankActiveT1Referrals(ctx, ms), "failed to rank active T1 referrals %#v", ms), ).ErrorOrNil() } +//nolint:funlen //. +func (s *miningSessionsTableSource) rankActiveT1Referrals(ctx context.Context, ms *MiningSession) (err error) { + if ctx.Err() != nil || !ms.LastNaturalMiningStartedAt.Equal(*ms.StartedAt.Time) { + return errors.Wrap(ctx.Err(), "unexpected deadline") + } + duplGuardKey := ms.duplGuardKey(s.repository, "rank_active_t1_guard") + if set, dErr := s.db.SetNX(ctx, duplGuardKey, "", s.cfg.MiningSessionDuration.Min).Result(); dErr != nil || !set { + if dErr == nil { + dErr = ErrDuplicate + } + + return errors.Wrapf(dErr, "SetNX failed for rank_active_t1_guard, miningSession: %#v", ms) + } + defer func() { + if err != nil { + undoCtx, cancelUndo := context.WithTimeout(context.Background(), requestDeadline) + defer cancelUndo() + err = multierror.Append( //nolint:wrapcheck // . + err, + errors.Wrapf(s.db.Del(undoCtx, duplGuardKey).Err(), "failed to del rank_active_t1_guard key"), + ).ErrorOrNil() + } + }() + id, err := GetOrInitInternalID(ctx, s.db, *ms.UserID) + if err != nil { + return errors.Wrapf(err, "failed to getOrInitInternalID for userID:%v", *ms.UserID) + } + referee, err := storage.Get[struct { + model.UserIDField + model.DeserializedUsersKey + model.MiningSessionSoloEndedAtField + model.IDT0Field + }](ctx, s.db, model.SerializedUsersKey(id)) + if err != nil || len(referee) == 0 || (referee[0].IDT0 == 0) { + return errors.Wrapf(err, "failed to get referees for id:%v, userID:%v", id, *ms.UserID) + } + if referee[0].IDT0 < 0 { + referee[0].IDT0 *= -1 + } + if err != nil || len(referee) == 0 || (referee[0].IDT0 == 0) { + return errors.Wrapf(err, "failed to get referees for id:%v, userID:%v", id, *ms.UserID) + } + rankKey := fmt.Sprintf("%v_active_t1_referrals_ranking", referee[0].IDT0) + zRank := redis.Z{ + Score: float64(referee[0].MiningSessionSoloEndedAt.UnixNano()), + Member: id, + } + zErr := s.db.ZAdd(ctx, rankKey, zRank) + + return errors.Wrapf(zErr.Err(), "failed to ZAdd activeT1Refs for id:%v, userID:%v, ref:%#v", id, *ms.UserID, referee[0]) +} + //nolint:funlen,revive,gocognit // . func (s *miningSessionsTableSource) incrementActiveReferralCountForT0AndTMinus1(ctx context.Context, ms *MiningSession) (err error) { if ctx.Err() != nil || !ms.LastNaturalMiningStartedAt.Equal(*ms.StartedAt.Time) {