Skip to content

Commit e074d1b

Browse files
authored
fix avs hooks panic (#373)
* fix avs hooks panic * skip when avsInfo is empty * handle error * reject create task when no valid operator exists * check env is set correctly * fix lint
1 parent a015283 commit e074d1b

File tree

6 files changed

+64
-38
lines changed

6 files changed

+64
-38
lines changed

local_node.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ command -v bc >/dev/null 2>&1 || {
5555
exit 1
5656
}
5757

58+
# check that ALCHEMY_API_KEY is set
59+
if [ -z "$ALCHEMY_API_KEY" ]; then
60+
echo "ALCHEMY_API_KEY is not set"
61+
exit 1
62+
fi
63+
5864
# used to exit on first error (any non-zero exit code)
5965
set -e
6066

x/avs/keeper/impl_epoch_hook.go

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,68 +35,66 @@ func (wrapper EpochsHooksWrapper) AfterEpochEnd(
3535
// TODO:There should be a retry mechanism or compensation mechanism to handle cases of failure
3636
if len(taskResList) != 0 {
3737
groupedTasks := wrapper.keeper.GroupTasksByIDAndAddress(taskResList)
38-
for _, value := range groupedTasks {
38+
for key, value := range groupedTasks {
39+
taskAddr, taskID, err := parseGroupKey(key)
40+
if err != nil {
41+
ctx.Logger().Error("Failed to parse group key", "key", key, "error", err)
42+
continue
43+
}
44+
avsInfo := wrapper.keeper.GetAVSInfoByTaskAddress(ctx, taskAddr)
45+
if avsInfo.AvsAddress == "" {
46+
ctx.Logger().Error("Failed to update task result statistics, no AVS address found for task address!", "task address", taskAddr, "task id", taskID)
47+
continue
48+
}
49+
avsAddr := avsInfo.AvsAddress
50+
taskInfo, err := wrapper.keeper.GetTaskInfo(ctx, strconv.FormatUint(taskID, 10), taskAddr)
51+
if err != nil {
52+
// Log the error and continue to the next task, and this should be an 'impossible' case, since we retrieved the taskID and taskAddr from the taskResList
53+
ctx.Logger().Error("Failed to update task result statistics, GetTaskInfo call failed!", "task address", taskAddr, "task id", taskID, "error", err)
54+
continue
55+
}
56+
taskPowerTotal, err := wrapper.keeper.operatorKeeper.GetAVSUSDValue(ctx, avsAddr)
57+
if err != nil || taskPowerTotal.IsZero() {
58+
// Log the error and continue to the next task, and this is also an 'impossible' case, since a valid task must have a non-zero total power
59+
ctx.Logger().Error("Failed to update task result statistics, GetAVSUSDValue call failed!", "avs address", avsAddr, "error", err)
60+
continue
61+
}
62+
3963
var signedOperatorList []string
40-
var taskID uint64
41-
var taskAddr string
42-
var avsAddr string
4364
var operatorPowers []*types.OperatorActivePowerInfo
4465
operatorPowerTotal := sdkmath.LegacyZeroDec()
4566
for _, res := range value {
4667
// Find signed operators
4768
if res.BlsSignature != nil && res.TaskResponseHash != "" || res.TaskResponse != nil {
4869
signedOperatorList = append(signedOperatorList, res.OperatorAddress)
49-
if avsAddr == "" {
50-
avsInfo := wrapper.keeper.GetAVSInfoByTaskAddress(ctx, res.TaskContractAddress)
51-
avsAddr = avsInfo.AvsAddress
52-
}
53-
if taskID == 0 {
54-
taskID = res.TaskId
55-
}
56-
if taskAddr == "" {
57-
taskAddr = res.TaskContractAddress
58-
}
5970
power, err := wrapper.keeper.operatorKeeper.GetOperatorOptedUSDValue(ctx, avsAddr, res.OperatorAddress)
71+
activePower := sdkmath.LegacyZeroDec()
6072
if err != nil || power.ActiveUSDValue.IsNegative() {
61-
ctx.Logger().Error("Failed to update task result statistics,GetOperatorOptedUSDValue call failed!", "task result", taskAddr, "error", err)
62-
// Handle the error gracefully, continue to the next
63-
// continue
73+
// Log the error and and use 0 as the active power for this operator
74+
ctx.Logger().Error("Failed to get optedUSDValue for operator, skip this one", "operator", res.OperatorAddress, "avsAddr", avsAddr, "error", err)
75+
} else {
76+
activePower = power.ActiveUSDValue
6477
}
65-
6678
operatorSelfPower := &types.OperatorActivePowerInfo{
6779
OperatorAddress: res.OperatorAddress,
68-
SelfActivePower: power.ActiveUSDValue,
80+
SelfActivePower: activePower,
6981
}
7082
operatorPowers = append(operatorPowers, operatorSelfPower)
71-
operatorPowerTotal = operatorPowerTotal.Add(power.ActiveUSDValue)
83+
operatorPowerTotal = operatorPowerTotal.Add(activePower)
7284
}
7385
}
74-
taskInfo, err := wrapper.keeper.GetTaskInfo(ctx, strconv.FormatUint(taskID, 10), taskAddr)
75-
if err != nil {
76-
ctx.Logger().Error("Failed to update task result statistics,GetTaskInfo call failed!", "task result", taskAddr, "error", err)
77-
// Handle the error gracefully, continue to the next
78-
// continue
79-
}
86+
8087
diff := types.Difference(taskInfo.OptInOperators, signedOperatorList)
8188
taskInfo.SignedOperators = signedOperatorList
8289
// If a signature is submitted only once, it is counted as NoSignedOperators
8390
taskInfo.NoSignedOperators = diff
8491
taskInfo.OperatorActivePower = &types.OperatorActivePowerList{OperatorPowerList: operatorPowers}
85-
// Calculate actual threshold
86-
taskPowerTotal, err := wrapper.keeper.operatorKeeper.GetAVSUSDValue(ctx, avsAddr)
8792

88-
if err != nil || taskPowerTotal.IsZero() || operatorPowerTotal.IsZero() {
89-
ctx.Logger().Error("Failed to update task result statistics,GetAVSUSDValue call failed!", "task result", taskAddr, "error", err)
90-
// Handle the error gracefully, continue to the next
91-
// continue
92-
}
9393
taskInfo.TaskTotalPower = taskPowerTotal
9494
// Update the taskInfo in the state
9595
err = wrapper.keeper.SetTaskInfo(ctx, taskInfo)
9696
if err != nil {
9797
ctx.Logger().Error("Failed to update task result statistics,SetTaskInfo call failed!", "task result", taskAddr, "error", err)
98-
// Handle the error gracefully, continue to the next
99-
// continue
10098
}
10199
}
102100
}

x/avs/keeper/keeper.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ func (k Keeper) CreateAVSTask(ctx sdk.Context, params *types.TaskInfoParams) (ui
286286
if err != nil {
287287
return types.InvalidTaskID, errorsmod.Wrap(err, "CreateAVSTask: failed to get opt-in operators")
288288
}
289+
290+
if len(operatorList) == 0 {
291+
return types.InvalidTaskID, errorsmod.Wrap(types.ErrNoOptedInOperators, fmt.Sprintf("CreateAVSTask: no valid opted-in operators for AVS: %s", avsInfo.AvsAddress))
292+
}
289293
params.TaskID = k.GetTaskID(ctx, common.HexToAddress(params.TaskContractAddress.String()))
290294
task := &types.TaskInfo{
291295
Name: params.TaskName,

x/avs/keeper/task.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func (k Keeper) IterateResultInfo(ctx sdk.Context, fn func(index int64, info typ
269269
func (k Keeper) GroupTasksByIDAndAddress(tasks []types.TaskResultInfo) map[string][]types.TaskResultInfo {
270270
taskMap := make(map[string][]types.TaskResultInfo)
271271
for _, task := range tasks {
272-
key := task.TaskContractAddress + "_" + strconv.FormatUint(task.TaskId, 10)
272+
key := task.TaskContractAddress + types.DelimiterForGroupKey + strconv.FormatUint(task.TaskId, 10)
273273
taskMap[key] = append(taskMap[key], task)
274274
}
275275

@@ -386,3 +386,16 @@ func (k *Keeper) GetAllChallengeInfos(ctx sdk.Context) ([]types.ChallengeInfo, e
386386
}
387387
return ret, nil
388388
}
389+
390+
func parseGroupKey(key string) (string, uint64, error) {
391+
parts := strings.Split(key, types.DelimiterForGroupKey)
392+
if len(parts) != 2 {
393+
return "", 0, fmt.Errorf("invalid group key format: %s", key)
394+
}
395+
taskAddr := parts[0]
396+
taskID, err := strconv.ParseUint(parts[1], 10, 64)
397+
if err != nil {
398+
return "", 0, fmt.Errorf("invalid task ID in group key: %s", key)
399+
}
400+
return taskAddr, taskID, nil
401+
}

x/avs/types/errors.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,8 @@ var (
119119
ModuleName, 28,
120120
"Resource not found",
121121
)
122+
ErrNoOptedInOperators = errorsmod.Register(
123+
ModuleName, 29,
124+
"No operators have opted in to the AVS yet",
125+
)
122126
)

x/avs/types/types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ var (
4949
)
5050

5151
const (
52-
InvalidTaskID = 0
53-
BLSMessageToSign = "BLS12-381 Signed Message\nChainIDWithoutRevision: %s\nAccAddressBech32: %s"
52+
InvalidTaskID = 0
53+
BLSMessageToSign = "BLS12-381 Signed Message\nChainIDWithoutRevision: %s\nAccAddressBech32: %s"
54+
DelimiterForGroupKey = "_"
5455
)
5556

5657
type AVSRegisterOrDeregisterParams struct {

0 commit comments

Comments
 (0)