Skip to content
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

Validate machine account config at startup #1236

Merged
merged 17 commits into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
103 changes: 53 additions & 50 deletions cmd/collection/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/onflow/flow-go/cmd/util/cmd/common"
"github.com/onflow/flow-go/model/bootstrap"

"github.com/spf13/pflag"

Expand Down Expand Up @@ -86,8 +87,9 @@ func main() {
// epoch qc contract client
accessAddress string
secureAccessNodeID string

insecureAccessAPI bool
insecureAccessAPI bool
machineAccountInfo *bootstrap.NodeMachineAccountInfo
flowClient *client.Client
)

cmd.FlowNode(flow.RoleCollection.String()).
Expand Down Expand Up @@ -181,6 +183,50 @@ func main() {
mainChainSyncCore, err = synchronization.New(node.Logger, synchronization.DefaultConfig())
return err
}).
Module("machine account config", func(builder cmd.NodeBuilder, node *cmd.NodeConfig) error {
machineAccountInfo, err = cmd.LoadNodeMachineAccountInfoFile(node.BootstrapDir, node.NodeID)
return err
}).
Module("sdk client", func(builder cmd.NodeBuilder, node *cmd.NodeConfig) error {
if accessAddress == "" {
return fmt.Errorf("missing required flag --access-address")
}
// create flow client with correct GRPC configuration for QC contract client
if insecureAccessAPI {
flowClient, err = common.InsecureFlowClient(accessAddress)
return err
} else {
if secureAccessNodeID == "" {
return fmt.Errorf("invalid flag --secure-access-node-id required")
}

nodeID, err := flow.HexStringToIdentifier(secureAccessNodeID)
if err != nil {
return fmt.Errorf("could not get flow identifer from secured access node id: %s", secureAccessNodeID)
}

identities, err := node.State.Sealed().Identities(filter.HasNodeID(nodeID))
if err != nil {
return fmt.Errorf("could not get identity of secure access node: %s", secureAccessNodeID)
}

if len(identities) < 1 {
return fmt.Errorf("could not find identity of secure access node: %s", secureAccessNodeID)
}

flowClient, err = common.SecureFlowClient(accessAddress, identities[0].NetworkPubKey.String()[2:])
return err
}
}).
Component("machine account config validator", func(builder cmd.NodeBuilder, node *cmd.NodeConfig) (module.ReadyDoneAware, error) {
validator, err := epochs.NewMachineAccountConfigValidator(
node.Logger,
flowClient,
flow.RoleCollection,
*machineAccountInfo,
)
return validator, err
}).
Component("follower engine", func(builder cmd.NodeBuilder, node *cmd.NodeConfig) (module.ReadyDoneAware, error) {

// initialize cleaner for DB
Expand Down Expand Up @@ -401,40 +447,8 @@ func main() {

signer := verification.NewSingleSigner(staking, node.Me.NodeID())

// create flow client with correct GRPC configuration for QC contract client
var flowClient *client.Client
if insecureAccessAPI {
flowClient, err = common.InsecureFlowClient(accessAddress)
if err != nil {
return nil, err
}
} else {
if secureAccessNodeID == "" {
return nil, fmt.Errorf("invalid flag --secure-access-node-id required")
}

nodeID, err := flow.HexStringToIdentifier(secureAccessNodeID)
if err != nil {
return nil, fmt.Errorf("could not get flow identifer from secured access node id: %s", secureAccessNodeID)
}

identities, err := node.State.Sealed().Identities(filter.HasNodeID(nodeID))
if err != nil {
return nil, fmt.Errorf("could not get identity of secure access node: %s", secureAccessNodeID)
}

if len(identities) < 1 {
return nil, fmt.Errorf("could not find identity of secure access node: %s", secureAccessNodeID)
}

flowClient, err = common.SecureFlowClient(accessAddress, identities[0].NetworkPubKey.String()[2:])
if err != nil {
return nil, err
}
}

// construct QC contract client
qcContractClient, err := createQCContractClient(node, accessAddress, flowClient)
qcContractClient, err := createQCContractClient(node, machineAccountInfo, flowClient)
if err != nil {
return nil, fmt.Errorf("could not create qc contract client %w", err)
}
Expand Down Expand Up @@ -482,7 +496,7 @@ func main() {
}

// createQCContractClient creates QC contract client
func createQCContractClient(node *cmd.NodeConfig, accessAddress string, flowClient *client.Client) (module.QCContractClient, error) {
func createQCContractClient(node *cmd.NodeConfig, machineAccountInfo *bootstrap.NodeMachineAccountInfo, flowClient *client.Client) (module.QCContractClient, error) {

var qcContractClient module.QCContractClient

Expand All @@ -492,26 +506,15 @@ func createQCContractClient(node *cmd.NodeConfig, accessAddress string, flowClie
}
qcContractAddress := contracts.ClusterQC.Address.Hex()

// if not valid return a mock qc contract client
if valid := cmd.IsValidNodeMachineAccountConfig(node, accessAddress); !valid {
return nil, fmt.Errorf("could not validate node machine account config")
}

// attempt to read NodeMachineAccountInfo
info, err := cmd.LoadNodeMachineAccountInfoFile(node.BaseConfig.BootstrapDir, node.Me.NodeID())
if err != nil {
return nil, fmt.Errorf("could not load node machine account info file: %w", err)
}
Comment on lines -500 to -504
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's indeed in LoadNodeMachineAccountInfoFile already, 👍


// construct signer from private key
sk, err := sdkcrypto.DecodePrivateKey(info.SigningAlgorithm, info.EncodedPrivateKey)
sk, err := sdkcrypto.DecodePrivateKey(machineAccountInfo.SigningAlgorithm, machineAccountInfo.EncodedPrivateKey)
if err != nil {
return nil, fmt.Errorf("could not decode private key from hex: %w", err)
}
txSigner := sdkcrypto.NewInMemorySigner(sk, info.HashAlgorithm)
txSigner := sdkcrypto.NewInMemorySigner(sk, machineAccountInfo.HashAlgorithm)

// create actual qc contract client, all flags and machine account info file found
qcContractClient = epochs.NewQCContractClient(node.Logger, flowClient, node.Me.NodeID(), info.Address, info.KeyIndex, qcContractAddress, txSigner)
qcContractClient = epochs.NewQCContractClient(node.Logger, flowClient, node.Me.NodeID(), machineAccountInfo.Address, machineAccountInfo.KeyIndex, qcContractAddress, txSigner)

return qcContractClient, nil
}
103 changes: 0 additions & 103 deletions cmd/collection/main_test.go

This file was deleted.