diff --git a/core/state.go b/core/state.go index de57f0a1c..6df4e0c6f 100644 --- a/core/state.go +++ b/core/state.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "math/big" + "strings" ) // Operators @@ -18,6 +19,25 @@ func MakeOperatorSocket(nodeIP, dispersalPort, retrievalPort string) OperatorSoc return OperatorSocket(fmt.Sprintf("%s:%s;%s", nodeIP, dispersalPort, retrievalPort)) } +func ParseOperatorSocket(socket string) (host string, dispersalPort string, retrievalPort string, err error) { + s := strings.Split(socket, ";") + if len(s) != 2 { + err = fmt.Errorf("invalid socket address format, missing retrieval port: %s", socket) + return + } + retrievalPort = s[1] + + s = strings.Split(s[0], ":") + if len(s) != 2 { + err = fmt.Errorf("invalid socket address format: %s", socket) + return + } + host = s[0] + dispersalPort = s[1] + + return +} + type StakeAmount *big.Int // OperatorInfo contains information about an operator which is stored on the blockchain state, diff --git a/core/test/core_test.go b/core/test/core_test.go index be741470e..89214c239 100644 --- a/core/test/core_test.go +++ b/core/test/core_test.go @@ -256,3 +256,20 @@ func TestCoreLibrary(t *testing.T) { } } + +func TestParseOperatorSocket(t *testing.T) { + operatorSocket := "localhost:1234;5678" + host, dispersalPort, retrievalPort, err := core.ParseOperatorSocket(operatorSocket) + assert.NoError(t, err) + assert.Equal(t, "localhost", host) + assert.Equal(t, "1234", dispersalPort) + assert.Equal(t, "5678", retrievalPort) + + _, _, _, err = core.ParseOperatorSocket("localhost:12345678") + assert.NotNil(t, err) + assert.Equal(t, "invalid socket address format, missing retrieval port: localhost:12345678", err.Error()) + + _, _, _, err = core.ParseOperatorSocket("localhost1234;5678") + assert.NotNil(t, err) + assert.Equal(t, "invalid socket address format: localhost1234;5678", err.Error()) +} diff --git a/node/node.go b/node/node.go index 290fb232a..93a8e110e 100644 --- a/node/node.go +++ b/node/node.go @@ -375,7 +375,7 @@ func (n *Node) checkCurrentNodeIp(ctx context.Context) { case <-ctx.Done(): return case <-t.C: - newSocketAddr, err := n.socketAddress(ctx) + newSocketAddr, err := SocketAddress(ctx, n.PubIPProvider, n.Config.DispersalPort, n.Config.RetrievalPort) if err != nil { n.Logger.Error("failed to get socket address", "err", err) continue @@ -385,15 +385,6 @@ func (n *Node) checkCurrentNodeIp(ctx context.Context) { } } -func (n *Node) socketAddress(ctx context.Context) (string, error) { - ip, err := n.PubIPProvider.PublicIPAddress(ctx) - if err != nil { - return "", fmt.Errorf("failed to get public ip address from IP provider: %w", err) - } - socket := core.MakeOperatorSocket(ip, n.Config.DispersalPort, n.Config.RetrievalPort) - return socket.String(), nil -} - // we only need to build the sdk clients for eigenmetrics right now, // but we might eventually want to move as much as possible to the sdk func buildSdkClients(config *Config, logger common.Logger) (*constructor.Clients, error) { diff --git a/node/plugin/cmd/main.go b/node/plugin/cmd/main.go index f880c0ae2..387522d5b 100644 --- a/node/plugin/cmd/main.go +++ b/node/plugin/cmd/main.go @@ -4,10 +4,12 @@ import ( "context" "log" "os" + "strings" "time" "github.com/Layr-Labs/eigenda/common/geth" "github.com/Layr-Labs/eigenda/common/logging" + "github.com/Layr-Labs/eigenda/common/pubip" "github.com/Layr-Labs/eigenda/core" "github.com/Layr-Labs/eigenda/core/eth" "github.com/Layr-Labs/eigenda/node" @@ -97,8 +99,24 @@ func pluginOps(ctx *cli.Context) { return } + _, dispersalPort, retrievalPort, err := core.ParseOperatorSocket(config.Socket) + if err != nil { + log.Printf("Error: failed to parse operator socket: %v", err) + return + } + + socket := config.Socket + if isLocalhost(socket) { + pubIPProvider := pubip.ProviderOrDefault(config.PubIPProvider) + socket, err = node.SocketAddress(context.Background(), pubIPProvider, dispersalPort, retrievalPort) + if err != nil { + log.Printf("Error: failed to get socket address from ip provider: %v", err) + return + } + } + operator := &node.Operator{ - Socket: config.Socket, + Socket: socket, Timeout: 10 * time.Second, KeyPair: keyPair, OperatorId: keyPair.GetPubKeyG1().GetOperatorID(), @@ -132,3 +150,7 @@ func pluginOps(ctx *cli.Context) { log.Fatalf("Fatal: unsupported operation: %s", config.Operation) } } + +func isLocalhost(socket string) bool { + return strings.Contains(socket, "localhost") || strings.Contains(socket, "127.0.0.1") || strings.Contains(socket, "0.0.0.0") +} diff --git a/node/plugin/config.go b/node/plugin/config.go index 4fb272813..8da55f71a 100644 --- a/node/plugin/config.go +++ b/node/plugin/config.go @@ -14,6 +14,13 @@ import ( var ( /* Required Flags */ + PubIPProviderFlag = cli.StringFlag{ + Name: "public-ip-provider", + Usage: "The ip provider service used to obtain a operator's public IP [seeip (default), ipify)", + Required: true, + EnvVar: common.PrefixEnvVar(flags.EnvVarPrefix, "PUBLIC_IP_PROVIDER"), + } + // The operation to run. OperationFlag = cli.StringFlag{ Name: "operation", @@ -99,6 +106,7 @@ var ( ) type Config struct { + PubIPProvider string Operation string EcdsaKeyFile string BlsKeyFile string @@ -130,6 +138,7 @@ func NewConfig(ctx *cli.Context) (*Config, error) { } return &Config{ + PubIPProvider: ctx.GlobalString(PubIPProviderFlag.Name), Operation: op, EcdsaKeyPassword: ctx.GlobalString(EcdsaKeyPasswordFlag.Name), BlsKeyPassword: ctx.GlobalString(BlsKeyPasswordFlag.Name), diff --git a/node/utils.go b/node/utils.go index 1166136b4..e493887d6 100644 --- a/node/utils.go +++ b/node/utils.go @@ -2,9 +2,12 @@ package node import ( "bytes" + "context" "encoding/binary" "errors" + "fmt" + "github.com/Layr-Labs/eigenda/common/pubip" "github.com/Layr-Labs/eigenda/core" ) @@ -80,3 +83,12 @@ func DecodeBatchExpirationKey(key []byte) (int64, error) { ts := int64(binary.BigEndian.Uint64(key[len(key)-8:])) return ts, nil } + +func SocketAddress(ctx context.Context, provider pubip.Provider, dispersalPort string, retrievalPort string) (string, error) { + ip, err := provider.PublicIPAddress(ctx) + if err != nil { + return "", fmt.Errorf("failed to get public ip address from IP provider: %w", err) + } + socket := core.MakeOperatorSocket(ip, dispersalPort, retrievalPort) + return socket.String(), nil +}