Skip to content

Commit 86826c1

Browse files
Merge branch 'v2-dev-1' into feat/incredible-dot-product-example
2 parents 5b38051 + a4fdfbb commit 86826c1

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

examples/incredible-squaring/operator/operator_use_example.go

+8-14
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66

77
"github.com/Layr-Labs/eigensdk-go/logging"
88
sdkoperator "github.com/Layr-Labs/eigensdk-go/operator"
9-
sdktypes "github.com/Layr-Labs/eigensdk-go/types"
109

1110
cstaskmanager "github.com/Layr-Labs/eigensdk-go/examples/incredible-squaring/bindings/taskManager"
1211
)
@@ -24,18 +23,6 @@ func main() {
2423
logger.Fatalf(err.Error())
2524
}
2625

27-
// This function calculates the task response from a Task, in this case with the number to square
28-
responseCalcFunction := func(task sdktypes.GenericInputTask[*big.Int], taskIndex uint32) (sdktypes.GenericOutputTaskResponse[*big.Int], error) {
29-
numberSquared := big.NewInt(0).Exp(task.InputValue, big.NewInt(2), nil)
30-
31-
taskResponse := sdktypes.GenericOutputTaskResponse[*big.Int]{
32-
ReferenceTaskIndex: taskIndex,
33-
OutputValue: numberSquared,
34-
}
35-
36-
return taskResponse, nil
37-
}
38-
3926
// The values from this config are extracted from an incredible squaring config file:
4027
// https://github.com/Layr-Labs/incredible-squaring-avs/blob/dev/config-files/operator.anvil.yaml
4128
operatorConfig := sdkoperator.OperatorConfig{
@@ -51,7 +38,7 @@ func main() {
5138
TaskManagerAbi: taskManagerAbi,
5239
}
5340

54-
operator, err := sdkoperator.NewOperatorFromConfig(operatorConfig, responseCalcFunction, nil)
41+
operator, err := sdkoperator.NewOperatorFromConfig(operatorConfig, square, nil)
5542
if err != nil {
5643
logger.Errorf("Failed to create operator from config: %v", err)
5744
return
@@ -63,3 +50,10 @@ func main() {
6350
return
6451
}
6552
}
53+
54+
// This function computes the square of a number
55+
func square(taskIndex uint32, numberToSquare *big.Int) (*big.Int, error) {
56+
numberSquared := big.NewInt(0).Exp(numberToSquare, big.NewInt(2), nil)
57+
58+
return numberSquared, nil
59+
}

operator/config.go

+11
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,15 @@ type OperatorConfig struct {
2323

2424
Logger logging.Logger
2525
TaskManagerAbi *abi.ABI
26+
27+
// Testing options for the operator.
28+
// These shouldn't be used in production.
29+
TestingOpts struct {
30+
// Percentage chance of randomly failing a task
31+
// This is used for testing purposes and defaults to not failing any tasks
32+
FailingPercentage uint
33+
// Seed used to generate operator failures
34+
// Defaults to the current time
35+
FailingSeed uint64
36+
}
2637
}

operator/operator.go

+42-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import (
44
"context"
55
"fmt"
66
"math/big"
7+
"math/rand/v2"
78
"os"
9+
"time"
810

911
"github.com/ethereum/go-ethereum"
1012
"github.com/ethereum/go-ethereum/accounts/abi"
@@ -34,7 +36,7 @@ type Operator[Input any, Output any] struct {
3436
taskResponseHashFn TaskResponseHashFunction[Output]
3537
}
3638

37-
type ResponseCalculationFunction[Input any, Output any] func(task sdktypes.GenericInputTask[Input], taskIndex uint32) (sdktypes.GenericOutputTaskResponse[Output], error)
39+
type ResponseCalculationFunction[Input any, Output any] func(taskIndex uint32, input Input) (Output, error)
3840

3941
type TaskResponseHashFunction[Output any] func(taskResponse sdktypes.GenericOutputTaskResponse[Output]) ([32]byte, error)
4042

@@ -79,8 +81,8 @@ func getDefaultHashFunction[Output any](taskResponseType abi.Type) TaskResponseH
7981

8082
func NewOperatorFromConfig[Input any, Output any](
8183
c OperatorConfig,
82-
ResponseCalculationFn ResponseCalculationFunction[Input, Output],
83-
TaskResponseHashFn TaskResponseHashFunction[Output],
84+
responseCalculationFn ResponseCalculationFunction[Input, Output],
85+
taskResponseHashFn TaskResponseHashFunction[Output],
8486
) (*Operator[Input, Output], error) {
8587
avs_config := avsregistry.Config{
8688
RegistryCoordinatorAddress: common.HexToAddress(c.AVSRegistryCoordinatorAddress),
@@ -153,14 +155,41 @@ func NewOperatorFromConfig[Input any, Output any](
153155
c.Logger.Fatal("error subscribing to newTaskCreated events", "err", err)
154156
}
155157

156-
if TaskResponseHashFn == nil {
158+
if taskResponseHashFn == nil {
157159
taskResponseType, err := extractTypeFromAbi(c.TaskManagerAbi)
158160
if err != nil {
159161
c.Logger.Error("Failed to get task response type in default abi.", "err", err)
160162
return nil, err
161163
}
162164

163-
TaskResponseHashFn = getDefaultHashFunction[Output](taskResponseType)
165+
taskResponseHashFn = getDefaultHashFunction[Output](taskResponseType)
166+
}
167+
168+
if c.TestingOpts.FailingPercentage != 0 {
169+
failPercentage := c.TestingOpts.FailingPercentage
170+
if failPercentage > 100 {
171+
return nil, fmt.Errorf("failing percentage must be between 0 and 100")
172+
}
173+
computeOutput := responseCalculationFn
174+
175+
failSeed := c.TestingOpts.FailingSeed
176+
if failSeed == 0 {
177+
// If the seed is not set, we use the current time as the seed
178+
failSeed = uint64(time.Now().UnixNano())
179+
}
180+
rng := rand.New(rand.NewPCG(42, failSeed))
181+
182+
c.Logger.Warn("FailingPercentage option was set. This operator will randomly fail tasks.")
183+
c.Logger.Info("Using seed:", failSeed)
184+
185+
responseCalculationFn = func(taskIndex uint32, input Input) (Output, error) {
186+
randomNumber := rng.UintN(100)
187+
if randomNumber < failPercentage {
188+
var emptyOutput Output
189+
return emptyOutput, nil
190+
}
191+
return computeOutput(taskIndex, input)
192+
}
164193
}
165194

166195
operator := &Operator[Input, Output]{
@@ -170,8 +199,8 @@ func NewOperatorFromConfig[Input any, Output any](
170199
operatorId: operatorId,
171200
newTaskCreatedLogs: newTaskCreatedLogs,
172201
taskManagerAbi: c.TaskManagerAbi,
173-
responseCalculationFn: ResponseCalculationFn,
174-
taskResponseHashFn: TaskResponseHashFn,
202+
responseCalculationFn: responseCalculationFn,
203+
taskResponseHashFn: taskResponseHashFn,
175204
}
176205

177206
c.Logger.Info("Operator info",
@@ -231,12 +260,15 @@ func (o *Operator[Input, Output]) processNewTaskCreatedLog(
231260
"QuorumThresholdPercentage", newTaskCreatedLog.Task.QuorumThresholdPercentage,
232261
)
233262

234-
taskResponse, err := o.responseCalculationFn(newTaskCreatedLog.Task, newTaskIndex)
263+
output, err := o.responseCalculationFn(newTaskIndex, newTaskCreatedLog.Task.InputValue)
235264
if err != nil {
236265
return nil, fmt.Errorf("error calculating task response: %w", err)
237266
}
238-
239-
return &taskResponse, nil
267+
taskResponse := &sdktypes.GenericOutputTaskResponse[Output]{
268+
ReferenceTaskIndex: newTaskIndex,
269+
OutputValue: output,
270+
}
271+
return taskResponse, nil
240272
}
241273

242274
func (o *Operator[Input, Output]) signTaskResponse(

0 commit comments

Comments
 (0)