diff --git a/cmd/config-utils.go b/cmd/config-utils.go index d4e856cd7..6fde89832 100644 --- a/cmd/config-utils.go +++ b/cmd/config-utils.go @@ -209,8 +209,8 @@ func (*UtilsStruct) GetMultiplier() (float32, error) { //This function returns the buffer percent func (*UtilsStruct) GetBufferPercent() (int32, error) { const ( - MinBufferPercent = 10 - MaxBufferPercent = 30 + MinBufferPercent = 0 + MaxBufferPercent = 5 ) bufferPercent, err := getConfigValue("buffer", "int32", core.DefaultBufferPercent, "buffer") @@ -228,7 +228,7 @@ func (*UtilsStruct) GetBufferPercent() (int32, error) { // If bufferPercent is 0, use the default value. if bufferPercentInt32 == 0 { - log.Debugf("BufferPercent is unset, using default value %d", core.DefaultBufferPercent) + log.Debugf("BufferPercent is unset or set to 0, using its default %d value", core.DefaultBufferPercent) return core.DefaultBufferPercent, nil } @@ -238,8 +238,8 @@ func (*UtilsStruct) GetBufferPercent() (int32, error) { //This function returns the wait time func (*UtilsStruct) GetWaitTime() (int32, error) { const ( - MinWaitTime = 1 // Minimum wait time in seconds - MaxWaitTime = 30 // Maximum wait time in seconds + MinWaitTime = 1 // Minimum wait time in seconds + MaxWaitTime = 5 // Maximum wait time in seconds ) waitTime, err := getConfigValue("wait", "int32", core.DefaultWaitTime, "wait") @@ -335,7 +335,7 @@ func (*UtilsStruct) GetGasLimitOverride() (uint64, error) { func (*UtilsStruct) GetRPCTimeout() (int64, error) { const ( MinRPCTimeout = 10 // Minimum RPC timeout in seconds - MaxRPCTimeout = 60 // Maximum RPC timeout in seconds + MaxRPCTimeout = 20 // Maximum RPC timeout in seconds ) rpcTimeout, err := getConfigValue("rpcTimeout", "int64", core.DefaultRPCTimeout, "rpcTimeout") @@ -357,7 +357,7 @@ func (*UtilsStruct) GetRPCTimeout() (int64, error) { func (*UtilsStruct) GetHTTPTimeout() (int64, error) { const ( MinHTTPTimeout = 10 // Minimum HTTP timeout in seconds - MaxHTTPTimeout = 60 // Maximum HTTP timeout in seconds + MaxHTTPTimeout = 20 // Maximum HTTP timeout in seconds ) httpTimeout, err := getConfigValue("httpTimeout", "int64", core.DefaultHTTPTimeout, "httpTimeout") diff --git a/cmd/config-utils_test.go b/cmd/config-utils_test.go index 736c3b9ac..da9e80f42 100644 --- a/cmd/config-utils_test.go +++ b/cmd/config-utils_test.go @@ -260,9 +260,9 @@ func TestGetBufferPercent(t *testing.T) { name: "Test 1: When buffer percent is fetched from root flag", args: args{ isFlagSet: true, - bufferPercent: 15, + bufferPercent: 5, }, - want: 15, + want: 5, wantErr: nil, }, { @@ -278,9 +278,9 @@ func TestGetBufferPercent(t *testing.T) { name: "Test 3: When buffer value is fetched from config", useDummyConfigFile: true, args: args{ - bufferInTestConfig: 30, + bufferInTestConfig: 1, }, - want: 30, + want: 1, wantErr: nil, }, { @@ -1130,9 +1130,9 @@ func TestGetWaitTime(t *testing.T) { name: "Test 1: When wait time is fetched from root flag", args: args{ isFlagSet: true, - waitTime: 10, + waitTime: 2, }, - want: 10, + want: 2, wantErr: nil, }, { @@ -1148,9 +1148,9 @@ func TestGetWaitTime(t *testing.T) { name: "Test 3: When wait time value is fetched from config", useDummyConfigFile: true, args: args{ - waitInTestConfig: 20, + waitInTestConfig: 3, }, - want: 20, + want: 3, wantErr: nil, }, { diff --git a/cmd/vote.go b/cmd/vote.go index 865c3b0c3..682390769 100644 --- a/cmd/vote.go +++ b/cmd/vote.go @@ -93,6 +93,8 @@ func (*UtilsStruct) ExecuteVote(flagSet *pflag.FlagSet) { err = cmdUtils.InitAssetCache(client) utils.CheckError("Error in initializing asset cache: ", err) + go utils.HandleResetCache(client, config.BufferPercent) + log.Debugf("Calling Vote() with arguments rogueData = %+v, account address = %s, backup node actions to ignore = %s", rogueData, account.Address, backupNodeActionsToIgnore) if err := cmdUtils.Vote(context.Background(), config, client, rogueData, account, backupNodeActionsToIgnore); err != nil { log.Errorf("%v\n", err) @@ -126,22 +128,10 @@ func (*UtilsStruct) HandleExit() { //This function handles all the states of voting func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error { - assetCacheTicker := time.NewTicker(time.Second * time.Duration(core.AssetCacheExpiry)) header, err := clientUtils.GetLatestBlockWithRetry(client) utils.CheckError("Error in getting block: ", err) for { select { - case <-assetCacheTicker.C: - log.Info("ASSET CACHE EXPIRED!") - log.Info("INITIALIZING JOBS AND COLLECTIONS CACHE AGAIN...") - if err := utils.InitJobsCache(client); err != nil { - log.Error("Error in initializing jobs cache: ", err) - continue - } - if err := utils.InitCollectionsCache(client); err != nil { - log.Error("Error in initializing collections cache: ", err) - continue - } case <-ctx.Done(): return nil default: @@ -319,8 +309,8 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, } } case -1: - if config.WaitTime > 5 { - timeUtils.Sleep(5 * time.Second) + if config.WaitTime >= core.BufferStateSleepTime { + timeUtils.Sleep(time.Second * time.Duration(core.BufferStateSleepTime)) return } } @@ -529,7 +519,7 @@ func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Config if revealTxn != core.NilHash { waitForBlockCompletionErr := razorUtils.WaitForBlockCompletion(client, revealTxn.Hex()) if waitForBlockCompletionErr != nil { - log.Error("Error in WaitForBlockCompletionErr for reveal: ", err) + log.Error("Error in WaitForBlockCompletionErr for reveal: ", waitForBlockCompletionErr) return err } } diff --git a/config.sh b/config.sh index c5b6e40a4..4d8c884fb 100644 --- a/config.sh +++ b/config.sh @@ -19,10 +19,10 @@ then GAS_MULTIPLIER=1.0 fi -read -rp "Buffer Percent: (20) " BUFFER +read -rp "Buffer Percent: (0) " BUFFER if [ -z "$BUFFER" ]; then - BUFFER=20 + BUFFER=0 fi read -rp "Wait Time: (1) " WAIT_TIME @@ -30,9 +30,9 @@ if [ -z "$WAIT_TIME" ]; then WAIT_TIME=1 fi -read -rp "Gas Price: (1) " GAS_PRICE +read -rp "Gas Price: (0) " GAS_PRICE if [ -z "$GAS_PRICE" ]; then - GAS_PRICE=1 + GAS_PRICE=0 fi read -rp "Gas Limit Increment : (2) " GAS_LIMIT diff --git a/core/constants.go b/core/constants.go index f8a2051a4..c182bf5d2 100644 --- a/core/constants.go +++ b/core/constants.go @@ -21,7 +21,7 @@ var BlockCompletionTimeout = 30 //Following are the default config values for all the config parameters var DefaultGasMultiplier float32 = 1.0 -var DefaultBufferPercent int32 = 20 +var DefaultBufferPercent int32 = 0 var DefaultGasPrice int32 = 0 var DefaultWaitTime int32 = 1 var DefaultGasLimit float32 = 2 @@ -30,6 +30,9 @@ var DefaultRPCTimeout int64 = 10 var DefaultHTTPTimeout int64 = 10 var DefaultLogLevel = "" +//BufferStateSleepTime is the sleeping time whenever buffer state hits +var BufferStateSleepTime int32 = 2 + //Following are the default logFile parameters in config var DefaultLogFileMaxSize = 200 diff --git a/utils/asset.go b/utils/asset.go index 4eb8cc893..383ebe9c9 100644 --- a/utils/asset.go +++ b/utils/asset.go @@ -531,6 +531,49 @@ func (*UtilsStruct) HandleOfficialJobsFromJSONFile(client *ethclient.Client, col return overrideJobs, overriddenJobIds } +func HandleResetCache(client *ethclient.Client, bufferPercent int32) { + assetCacheTicker := time.NewTicker(time.Second * time.Duration(core.AssetCacheExpiry)) + defer assetCacheTicker.Stop() + + for { + <-assetCacheTicker.C // Wait for the next tick + log.Info("ASSET CACHE EXPIRED! INITIALIZING JOBS AND COLLECTIONS CACHE AGAIN...") + if err := UtilsInterface.ResetAssetCache(client, bufferPercent); err != nil { + log.Errorf("Error resetting asset cache: %v", err) + } + } +} + +func (*UtilsStruct) ResetAssetCache(client *ethclient.Client, bufferPercent int32) error { + state, err := UtilsInterface.GetBufferedState(client, bufferPercent) + if err != nil { + log.Error("Error in getting buffered state: ", err) + return err + } + // Avoiding resetting jobs/collections cache in commit state + if state == 0 { + log.Info("ResetAssetCache: Cannot reset Jobs/Collections cache in commit state!") + stateRemainingTime, err := UtilsInterface.GetRemainingTimeOfCurrentState(client, bufferPercent) + if err != nil { + log.Error("Error in getting remaining time of current state: ", err) + return err + } + log.Infof("ResetAssetCache: Waiting for commit state to complete, sleeping for %v seconds...", stateRemainingTime) + time.Sleep(time.Second * time.Duration(stateRemainingTime)) + log.Infof("ResetAssetCache: INITIALIZING JOBS AND COLLECTIONS CACHE NOW!") + } + + if err := InitJobsCache(client); err != nil { + log.Error("Error in initializing jobs cache: ", err) + return err + } + if err := InitCollectionsCache(client); err != nil { + log.Error("Error in initializing collections cache: ", err) + return err + } + return nil +} + func InitJobsCache(client *ethclient.Client) error { cache.JobsCache.Mu.Lock() defer cache.JobsCache.Mu.Unlock() diff --git a/utils/asset_test.go b/utils/asset_test.go index dac1786d5..6d214e6fd 100644 --- a/utils/asset_test.go +++ b/utils/asset_test.go @@ -1638,3 +1638,130 @@ func TestIsJSONCompatible(t *testing.T) { }) } } + +func TestUtilsStruct_ResetAssetCache(t *testing.T) { + var ( + client *ethclient.Client + bufferPercent int32 + ) + + type args struct { + state int64 + stateErr error + stateRemainingTime int64 + stateRemainingTimeErr error + numOfJobs uint16 + numOfJobsErr error + job bindings.StructsJob + jobErr error + numOfCollections uint16 + numOfCollectionsErr error + collection bindings.StructsCollection + collectionErr error + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Successful Reset", + args: args{ + state: 1, // Not in commit state + numOfJobs: 2, + job: bindings.StructsJob{Id: 1}, + numOfCollections: 2, + collection: bindings.StructsCollection{Id: 1}, + }, + wantErr: false, + }, + { + name: "Successful Reset after waiting in commit state", + args: args{ + state: 0, // Not in commit state + stateRemainingTime: 1, + numOfJobs: 1, + job: bindings.StructsJob{Id: 1}, + numOfCollections: 1, + collection: bindings.StructsCollection{Id: 1}, + }, + wantErr: false, + }, + { + name: "Error in getting buffered state", + args: args{ + stateErr: errors.New("state error"), + }, + wantErr: true, + }, + { + name: "Error in getting state remaining time when resetting in commit state", + args: args{ + state: 0, // In commit state + stateRemainingTimeErr: errors.New("stateRemainingTime error"), + }, + wantErr: true, + }, + { + name: "Error in getting num Of jobs", + args: args{ + state: 1, + numOfJobsErr: errors.New("numOfJobs error"), + }, + wantErr: true, + }, + { + name: "Error in getting job", + args: args{ + state: 1, + numOfJobs: 1, + jobErr: errors.New("job error"), + }, + wantErr: true, + }, + { + name: "Error in getting num of collections", + args: args{ + state: 1, + numOfJobs: 2, + job: bindings.StructsJob{Id: 1}, + numOfCollectionsErr: errors.New("numOfCollections error"), + }, + wantErr: true, + }, + { + name: "Error in getting collection", + args: args{ + state: 1, + numOfJobs: 2, + job: bindings.StructsJob{Id: 1}, + numOfCollections: 1, + collectionErr: errors.New("collection error"), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + utilsMock := new(mocks.Utils) + assetManagerMock := new(mocks.AssetManagerUtils) + + optionsPackageStruct := OptionsPackageStruct{ + UtilsInterface: utilsMock, + AssetManagerInterface: assetManagerMock, + } + utils := StartRazor(optionsPackageStruct) + + utilsMock.On("GetBufferedState", mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr) + utilsMock.On("GetRemainingTimeOfCurrentState", mock.Anything, mock.Anything).Return(tt.args.stateRemainingTime, tt.args.stateRemainingTimeErr) + assetManagerMock.On("GetNumJobs", mock.Anything).Return(tt.args.numOfJobs, tt.args.numOfJobsErr) + utilsMock.On("GetNumCollections", mock.Anything).Return(tt.args.numOfCollections, tt.args.numOfCollectionsErr) + utilsMock.On("GetActiveJob", mock.Anything, mock.Anything).Return(tt.args.job, tt.args.jobErr) + assetManagerMock.On("GetCollection", mock.Anything, mock.Anything).Return(tt.args.collection, tt.args.collectionErr) + + if err := utils.ResetAssetCache(client, bufferPercent); (err != nil) != tt.wantErr { + t.Errorf("ResetAssetCache() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/utils/interface.go b/utils/interface.go index 77304e2d8..56164f63a 100644 --- a/utils/interface.go +++ b/utils/interface.go @@ -158,6 +158,7 @@ type Utils interface { GetStakedTokenManagerWithOpts(client *ethclient.Client, tokenAddress common.Address) (*bindings.StakedToken, bind.CallOpts) GetStakerSRZRBalance(client *ethclient.Client, staker bindings.StructsStaker) (*big.Int, error) CheckPassword(address string, password string) error + ResetAssetCache(client *ethclient.Client, bufferPercent int32) error } type EthClientUtils interface { diff --git a/utils/mocks/utils.go b/utils/mocks/utils.go index a30978eaf..c17df5990 100644 --- a/utils/mocks/utils.go +++ b/utils/mocks/utils.go @@ -1838,6 +1838,20 @@ func (_m *Utils) ReadJSONData(fileName string) (map[string]*types.StructsJob, er return r0, r1 } +// ResetAssetCache provides a mock function with given fields: client, bufferPercent +func (_m *Utils) ResetAssetCache(client *ethclient.Client, bufferPercent int32) error { + ret := _m.Called(client, bufferPercent) + + var r0 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, int32) error); ok { + r0 = rf(client, bufferPercent) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SecondsToReadableTime provides a mock function with given fields: input func (_m *Utils) SecondsToReadableTime(input int) string { ret := _m.Called(input)