diff --git a/node/node.go b/node/node.go index e2d59cf75e..9ebbd60254 100644 --- a/node/node.go +++ b/node/node.go @@ -192,13 +192,14 @@ func (n *Node) Start(ctx context.Context) error { return fmt.Errorf("NewClient: cannot parse private key: %w", err) } operator := &Operator{ - Address: crypto.PubkeyToAddress(privateKey.PublicKey).Hex(), - Socket: socket, - Timeout: 10 * time.Second, - PrivKey: privateKey, - KeyPair: n.KeyPair, - OperatorId: n.Config.ID, - QuorumIDs: n.Config.QuorumIDList, + Address: crypto.PubkeyToAddress(privateKey.PublicKey).Hex(), + Socket: socket, + Timeout: 10 * time.Second, + PrivKey: privateKey, + KeyPair: n.KeyPair, + OperatorId: n.Config.ID, + QuorumIDs: n.Config.QuorumIDList, + RegisterNodeAtStart: n.Config.RegisterNodeAtStart, } churnerClient := NewChurnerClient(n.Config.ChurnerUrl, n.Config.UseSecureGrpc, n.Config.Timeout, n.Logger) err = RegisterOperator(ctx, operator, n.Transactor, churnerClient, n.Logger) @@ -212,7 +213,6 @@ func (n *Node) Start(ctx context.Context) error { } else { n.Logger.Infof("The node has started but the network with chainID %s is not supported yet", n.ChainID.String()) } - } n.CurrentSocket = socket diff --git a/node/operator.go b/node/operator.go index a6cd282a8a..49888317cb 100644 --- a/node/operator.go +++ b/node/operator.go @@ -3,6 +3,7 @@ package node import ( "context" "crypto/ecdsa" + "errors" "fmt" "math/big" "slices" @@ -14,13 +15,14 @@ import ( ) type Operator struct { - Address string - Socket string - Timeout time.Duration - PrivKey *ecdsa.PrivateKey - KeyPair *core.KeyPair - OperatorId core.OperatorID - QuorumIDs []core.QuorumID + Address string + Socket string + Timeout time.Duration + PrivKey *ecdsa.PrivateKey + KeyPair *core.KeyPair + OperatorId core.OperatorID + QuorumIDs []core.QuorumID + RegisterNodeAtStart bool } // RegisterOperator operator registers the operator with the given public key for the given quorum IDs. @@ -32,6 +34,12 @@ func RegisterOperator(ctx context.Context, operator *Operator, transactor core.T if err != nil { return fmt.Errorf("failed to get quorum ids to register: %w", err) } + if !operator.RegisterNodeAtStart { + // For operator-initiated registration, the supplied quorums must be not registered yet. + if len(quorumsToRegister) != len(operator.QuorumIDs) { + return errors.New("quorums to register must be not registered yet") + } + } if len(quorumsToRegister) == 0 { return nil } @@ -117,8 +125,6 @@ func (c *Operator) getQuorumIdsToRegister(ctx context.Context, transactor core.T for _, quorumID := range c.QuorumIDs { if !slices.Contains(registeredQuorumIds, quorumID) { quorumIdsToRegister = append(quorumIdsToRegister, quorumID) - } else { - return nil, fmt.Errorf("the operator already registered for quorum %d", quorumID) } } diff --git a/node/operator_test.go b/node/operator_test.go index 93c785014b..257004d6ec 100644 --- a/node/operator_test.go +++ b/node/operator_test.go @@ -23,13 +23,14 @@ func TestRegisterOperator(t *testing.T) { assert.NoError(t, err) // Create a new operator operator := &node.Operator{ - Address: "0xB7Ad27737D88B07De48CDc2f379917109E993Be4", - Socket: "localhost:50051", - Timeout: 10 * time.Second, - PrivKey: nil, - KeyPair: keyPair, - OperatorId: operatorID, - QuorumIDs: []core.QuorumID{0, 1}, + Address: "0xB7Ad27737D88B07De48CDc2f379917109E993Be4", + Socket: "localhost:50051", + Timeout: 10 * time.Second, + PrivKey: nil, + KeyPair: keyPair, + OperatorId: operatorID, + QuorumIDs: []core.QuorumID{0, 1}, + RegisterNodeAtStart: false, } createMockTx := func(quorumIDs []uint8) *coremock.MockTransactor { tx := &coremock.MockTransactor{} @@ -53,7 +54,7 @@ func TestRegisterOperator(t *testing.T) { tx2 := createMockTx([]uint8{0}) err = node.RegisterOperator(context.Background(), operator, tx2, churnerClient, logger) assert.Error(t, err) - assert.True(t, strings.Contains(err.Error(), "the operator already registered for quorum 0")) + assert.True(t, strings.Contains(err.Error(), "quorums to register must be not registered yet")) } func TestRegisterOperatorWithChurn(t *testing.T) { diff --git a/node/plugin/cmd/main.go b/node/plugin/cmd/main.go index 020fd4ca7c..8627038f9b 100644 --- a/node/plugin/cmd/main.go +++ b/node/plugin/cmd/main.go @@ -118,13 +118,14 @@ func pluginOps(ctx *cli.Context) { } operator := &node.Operator{ - Address: sk.Address.Hex(), - Socket: socket, - Timeout: 10 * time.Second, - PrivKey: sk.PrivateKey, - KeyPair: keyPair, - OperatorId: keyPair.GetPubKeyG1().GetOperatorID(), - QuorumIDs: config.QuorumIDList, + Address: sk.Address.Hex(), + Socket: socket, + Timeout: 10 * time.Second, + PrivKey: sk.PrivateKey, + KeyPair: keyPair, + OperatorId: keyPair.GetPubKeyG1().GetOperatorID(), + QuorumIDs: config.QuorumIDList, + RegisterNodeAtStart: false, } churnerClient := node.NewChurnerClient(config.ChurnerUrl, true, operator.Timeout, logger) if config.Operation == "opt-in" {