-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVS-215, AVS-259: Add Subgraphs #233
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
b66c56d
added querier
Sidu28 fb2886e
added grahql query
Sidu28 ecfedbb
cleanup
Sidu28 9ff18c2
added optimistic test
Sidu28 079f1e0
AVS-259: Subgraph test (#244)
Sidu28 9a80d5c
Subgraph testing (#245)
Sidu28 9b8b4be
resolved merge
Sidu28 48f51eb
added remappings
Sidu28 7dc8a2f
integration test
Sidu28 5183a39
added integration test halpers
Sidu28 f6569c3
fixed
Sidu28 5667b64
cleaned gir modules
Sidu28 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package operatorsinfo | ||
|
||
import ( | ||
"context" | ||
"encoding/hex" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/Layr-Labs/eigensdk-go/crypto/bls" | ||
"github.com/Layr-Labs/eigensdk-go/logging" | ||
"github.com/Layr-Labs/eigensdk-go/types" | ||
"github.com/consensys/gnark-crypto/ecc/bn254" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/shurcooL/graphql" | ||
) | ||
|
||
type ( | ||
QueryOperatorByAddressGql struct { | ||
Operator IndexedOperatorInfoGql `graphql:"operator(address: $address)"` | ||
} | ||
OperatorsInfoServiceSubgraph struct { | ||
logger logging.Logger | ||
client GraphQLQuerier | ||
name string | ||
} | ||
SocketUpdates struct { | ||
Socket graphql.String | ||
} | ||
IndexedOperatorInfoGql struct { | ||
Address graphql.String | ||
PubkeyG1_X graphql.String `graphql:"pubkeyG1_X"` | ||
PubkeyG1_Y graphql.String `graphql:"pubkeyG1_Y"` | ||
PubkeyG2_X []graphql.String `graphql:"pubkeyG2_X"` | ||
PubkeyG2_Y []graphql.String `graphql:"pubkeyG2_Y"` | ||
// Socket is the socket address of the operator, in the form "host:port" | ||
SocketUpdates []SocketUpdates `graphql:"socketUpdates(first: 1, orderBy: blockNumber, orderDirection: desc)"` | ||
} | ||
IndexedOperatorInfo struct { | ||
// PubKeyG1 and PubKeyG2 are the public keys of the operator, which are retrieved from the EigenDAPubKeyCompendium smart contract | ||
PubkeyG1 *G1Point | ||
PubkeyG2 *G2Point | ||
// Socket is the socket address of the operator, in the form "host:port" | ||
Socket string | ||
} | ||
G2Point struct { | ||
*bn254.G2Affine | ||
} | ||
G1Point struct { | ||
*bn254.G1Affine | ||
} | ||
GraphQLQuerier interface { | ||
Query(ctx context.Context, q any, variables map[string]any) error | ||
} | ||
) | ||
|
||
var _ OperatorsInfoService = (*OperatorsInfoServiceSubgraph)(nil) | ||
|
||
// NewOperatorsInfoServiceSubgraph constructs a OperatorsInfoServiceSubgraph and starts it in a goroutine. | ||
// It takes a context as argument because the "backfilling" of the database is done inside this constructor, | ||
// so we wait for all past NewPubkeyRegistration/OperatorSocketUpdate events to be queried and the db to be filled before returning the service. | ||
// The constructor is thus following a RAII-like pattern, of initializing the serving during construction. | ||
// Using a separate initialize() function might lead to some users forgetting to call it and the service not behaving properly. | ||
func NewOperatorsInfoServiceSubgraph( | ||
ctx context.Context, | ||
client GraphQLQuerier, | ||
logger logging.Logger, | ||
) *OperatorsInfoServiceSubgraph { | ||
return &OperatorsInfoServiceSubgraph{ | ||
logger: logger, | ||
client: client, | ||
name: "OperatorsInfoServiceSubgraph", | ||
} | ||
} | ||
|
||
// TODO(samlaf): we might want to also add an async version of this method that returns a channel of operator pubkeys? | ||
func (ops *OperatorsInfoServiceSubgraph) GetOperatorInfo(ctx context.Context, operator common.Address) (operatorPubkeys types.OperatorInfo, operatorFound bool) { | ||
operatorInfo, err := ops.getIndexedOperatorInfoByOperatorId(ctx, operator) | ||
if err != nil { | ||
return types.OperatorInfo{}, false | ||
} | ||
return *operatorInfo, true | ||
} | ||
|
||
func (ops *OperatorsInfoServiceSubgraph) getIndexedOperatorInfoByOperatorId(ctx context.Context, operator common.Address) (*types.OperatorInfo, error) { | ||
var ( | ||
query QueryOperatorByAddressGql | ||
variables = map[string]any{ | ||
"id": graphql.String(fmt.Sprintf("0x%s", hex.EncodeToString(operator[:]))), | ||
} | ||
) | ||
err := ops.client.Query(ctx, &query, variables) | ||
if err != nil { | ||
ops.logger.Error("Error requesting info for operator", "err", err, "operator", hex.EncodeToString(operator[:])) | ||
return nil, err | ||
} | ||
|
||
return convertIndexedOperatorInfoGqlToOperatorInfo(&query.Operator) | ||
} | ||
|
||
func convertIndexedOperatorInfoGqlToOperatorInfo(operator *IndexedOperatorInfoGql) (*types.OperatorInfo, error) { | ||
|
||
if len(operator.SocketUpdates) == 0 { | ||
return nil, errors.New("no socket found for operator") | ||
} | ||
|
||
pubkeyG1 := new(bn254.G1Affine) | ||
_, err := pubkeyG1.X.SetString(string(operator.PubkeyG1_X)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
_, err = pubkeyG1.Y.SetString(string(operator.PubkeyG1_Y)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pubkeyG2 := new(bn254.G2Affine) | ||
_, err = pubkeyG2.X.A1.SetString(string(operator.PubkeyG2_X[0])) | ||
if err != nil { | ||
return nil, err | ||
} | ||
_, err = pubkeyG2.X.A0.SetString(string(operator.PubkeyG2_X[1])) | ||
if err != nil { | ||
return nil, err | ||
} | ||
_, err = pubkeyG2.Y.A1.SetString(string(operator.PubkeyG2_Y[0])) | ||
if err != nil { | ||
return nil, err | ||
} | ||
_, err = pubkeyG2.Y.A0.SetString(string(operator.PubkeyG2_Y[1])) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &types.OperatorInfo{ | ||
Socket: types.Socket(string(operator.SocketUpdates[0].Socket)), | ||
Pubkeys: types.OperatorPubkeys{ | ||
G1Pubkey: &bls.G1Point{G1Affine: pubkeyG1}, | ||
G2Pubkey: &bls.G2Point{G2Affine: pubkeyG2}, | ||
}, | ||
}, nil | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package operatorsinfo | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/Layr-Labs/eigensdk-go/logging" | ||
"github.com/Layr-Labs/eigensdk-go/types" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/shurcooL/graphql" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
type mockGraphQLQuerier struct { | ||
QueryFn func(ctx context.Context, q any, variables map[string]any) error | ||
} | ||
samlaf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func (m mockGraphQLQuerier) Query(ctx context.Context, q any, variables map[string]any) error { | ||
return m.QueryFn(ctx, q, variables) | ||
} | ||
|
||
func TestIndexedChainState_GetIndexedOperatorState(t *testing.T) { | ||
logger, err := logging.NewZapLogger(logging.Development) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
operatorAddress := common.Address{0x1} | ||
|
||
operatorsQueryCalled := false | ||
querier := &mockGraphQLQuerier{} | ||
querier.QueryFn = func(ctx context.Context, q any, variables map[string]any) error { | ||
switch res := q.(type) { | ||
case *QueryOperatorByAddressGql: | ||
if operatorsQueryCalled { | ||
return nil | ||
} | ||
res.Operator = IndexedOperatorInfoGql{ | ||
Address: graphql.String(operatorAddress.String()), | ||
PubkeyG1_X: "3336192159512049190945679273141887248666932624338963482128432381981287252980", | ||
PubkeyG1_Y: "15195175002875833468883745675063986308012687914999552116603423331534089122704", | ||
PubkeyG2_X: []graphql.String{ | ||
"21597023645215426396093421944506635812143308313031252511177204078669540440732", | ||
"11405255666568400552575831267661419473985517916677491029848981743882451844775", | ||
}, | ||
PubkeyG2_Y: []graphql.String{ | ||
"9416989242565286095121881312760798075882411191579108217086927390793923664442", | ||
"13612061731370453436662267863740141021994163834412349567410746669651828926551", | ||
}, | ||
SocketUpdates: []SocketUpdates{{Socket: "localhost:32006;32007"}}, | ||
} | ||
operatorsQueryCalled = true | ||
return nil | ||
default: | ||
return nil | ||
} | ||
} | ||
|
||
cs := NewOperatorsInfoServiceSubgraph(context.Background(), querier, logger) | ||
operatorPubkeys, success := cs.GetOperatorInfo(context.Background(), operatorAddress) | ||
assert.True(t, success) | ||
assert.Equal(t, operatorPubkeys.Socket, types.Socket("localhost:32006;32007")) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are the
any
s necessary? If so, can you add comments as to how they are being used and what they are supposed to be. Hard to understand what this is used if we throwaway all type information.