Skip to content

Commit

Permalink
go/oasis-test-runner: Add sentry node support
Browse files Browse the repository at this point in the history
  • Loading branch information
tjanez committed Nov 8, 2019
1 parent de0178a commit dfcc4b0
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 7 deletions.
31 changes: 31 additions & 0 deletions go/oasis-test-runner/oasis/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package oasis

import (
"encoding/hex"
"fmt"
"path/filepath"
"strconv"
"strings"

"github.com/oasislabs/oasis-core/go/client"
"github.com/oasislabs/oasis-core/go/common/crypto/signature"
Expand Down Expand Up @@ -273,6 +275,35 @@ func (args *argBuilder) sentryControlPort(port uint16) *argBuilder {
return args
}

func (args *argBuilder) addSentries(sentries []*Sentry) *argBuilder {
var addrs, certFiles []string
for _, sentry := range sentries {
addrs = append(addrs, fmt.Sprintf("127.0.0.1:%d", sentry.controlPort))
certFiles = append(certFiles, sentry.TLSCertPath())
}
args = args.workerSentryAddresses(strings.Join(addrs, ","))
args = args.workerSentryCertFiles(strings.Join(certFiles, ","))
return args
}

func (args *argBuilder) addSentriesAsPersistentPeers(sentries []*Sentry) *argBuilder {
var peers []string
for _, sentry := range sentries {
peers = append(peers, fmt.Sprintf("%[email protected]:%d", sentry.tmAddress, sentry.consensusPort))
}
args = args.tendermintPersistentPeers(strings.Join(peers, ","))
return args
}

func (args *argBuilder) addValidatorsAsPrivatePeers(validators []*Validator) *argBuilder {
var peers []string
for _, val := range validators {
peers = append(peers, fmt.Sprintf("%[email protected]:%d", val.tmAddress, val.consensusPort))
}
args = args.tendermintPrivatePeers(strings.Join(peers, ","))
return args
}

func (args *argBuilder) appendSeedNodes(net *Network) *argBuilder {
if seed := net.seedNode; seed != nil {
args.vec = append(args.vec, []string{
Expand Down
53 changes: 52 additions & 1 deletion go/oasis-test-runner/oasis/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type NetworkFixture struct {
Keymanagers []KeymanagerFixture `json:"keymanagers,omitempty"`
StorageWorkers []StorageWorkerFixture `json:"storage_workers,omitempty"`
ComputeWorkers []ComputeWorkerFixture `json:"compute_workers,omitempty"`
Sentries []SentryFixture `json:"sentries,omitempty"`
Clients []ClientFixture `json:"clients,omitempty"`
ByzantineNodes []ByzantineFixture `json:"byzantine_nodes,omitempty"`
}
Expand Down Expand Up @@ -54,6 +55,13 @@ func (f *NetworkFixture) Create(env *env.Env) (*Network, error) {
}
}

// Provision the sentry nodes.
for _, fx := range f.Sentries {
if _, err = fx.Create(net); err != nil {
return nil, err
}
}

// Provision validators.
for _, fx := range f.Validators {
if _, err = fx.Create(net); err != nil {
Expand Down Expand Up @@ -108,6 +116,8 @@ type TEEFixture struct {
// ValidatorFixture is a validator fixture.
type ValidatorFixture struct {
Entity int `json:"entity"`

Sentries []int `json:"sentries,omitempty"`
}

// Create instantiates the validator described by the fixture.
Expand All @@ -116,9 +126,14 @@ func (f *ValidatorFixture) Create(net *Network) (*Validator, error) {
if err != nil {
return nil, err
}
sentries, err := resolveSentries(net, f.Sentries)
if err != nil {
return nil, err
}

return net.NewValidator(&ValidatorCfg{
Entity: entity,
Entity: entity,
Sentries: sentries,
})
}

Expand Down Expand Up @@ -239,6 +254,18 @@ func (f *ComputeWorkerFixture) Create(net *Network) (*Compute, error) {
})
}

// SentryFixture is a sentry node fixture.
type SentryFixture struct {
Validators []int `json:"validators"`
}

// Create instantiates the client node described by the fixture.
func (f *SentryFixture) Create(net *Network) (*Sentry, error) {
return net.NewSentry(&SentryCfg{
ValidatorIndices: f.Validators,
})
}

// ClientFixture is a client node fixture.
type ClientFixture struct {
}
Expand Down Expand Up @@ -277,6 +304,18 @@ func resolveEntity(net *Network, index int) (*Entity, error) {
return entities[index], nil
}

func resolveValidators(net *Network, indices []int) ([]*Validator, error) {
allValidators := net.Validators()
var validators []*Validator
for _, index := range indices {
if index < 0 || index >= len(allValidators) {
return nil, fmt.Errorf("invalid validator index: %d", index)
}
validators = append(validators, allValidators[index])
}
return validators, nil
}

func resolveRuntime(net *Network, index int) (*Runtime, error) {
runtimes := net.Runtimes()
if index < 0 || index >= len(runtimes) {
Expand All @@ -299,3 +338,15 @@ func resolveRuntimeOfKind(net *Network, index int, kind registry.RuntimeKind) (*
}
return runtime, nil
}

func resolveSentries(net *Network, indices []int) ([]*Sentry, error) {
allSentries := net.Sentries()
var sentries []*Sentry
for _, index := range indices {
if index < 0 || index >= len(allSentries) {
return nil, fmt.Errorf("invalid sentry index: %d", index)
}
sentries = append(sentries, allSentries[index])
}
return sentries, nil
}
18 changes: 17 additions & 1 deletion go/oasis-test-runner/oasis/oasis.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type Network struct {
keymanager *Keymanager
storageWorkers []*Storage
computeWorkers []*Compute
sentries []*Sentry
clients []*Client
byzantine []*Byzantine

Expand Down Expand Up @@ -152,6 +153,11 @@ func (net *Network) ComputeWorkers() []*Compute {
return net.computeWorkers
}

// Sentries returns the sentry nodes associated with the network.
func (net *Network) Sentries() []*Sentry {
return net.sentries
}

// Clients returns the client nodes associated with the network.
func (net *Network) Clients() []*Client {
return net.clients
Expand Down Expand Up @@ -305,10 +311,20 @@ func (net *Network) Start() error {
}
}

net.logger.Debug("starting sentry node(s)")
for _, v := range net.sentries {
if err := v.startNode(); err != nil {
net.logger.Error("failed to start sentry node",
"err", err,
)
return err
}
}

net.logger.Debug("starting client node(s)")
for _, v := range net.clients {
if err := v.startNode(); err != nil {
net.logger.Error("failed to start client worker",
net.logger.Error("failed to start client node",
"err", err,
)
return err
Expand Down
103 changes: 103 additions & 0 deletions go/oasis-test-runner/oasis/sentry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package oasis

import (
"fmt"

"github.com/oasislabs/oasis-core/go/common/crypto/signature"
fileSigner "github.com/oasislabs/oasis-core/go/common/crypto/signature/signers/file"
"github.com/oasislabs/oasis-core/go/common/identity"
"github.com/oasislabs/oasis-core/go/oasis-test-runner/env"
"github.com/oasislabs/oasis-core/go/tendermint/crypto"
)

// Sentry is an Oasis sentry node.
type Sentry struct {
net *Network
dir *env.Dir

validatorIndices []int

publicKey signature.PublicKey
tmAddress string
consensusPort uint16
controlPort uint16
}

// SentryCfg is the Oasis sentry node configuration.
type SentryCfg struct {
ValidatorIndices []int
}

// LogPath returns the path to the node's log.
func (sentry *Sentry) LogPath() string {
return nodeLogPath(sentry.dir)
}

// TLSCertPath returns the path to the node's TLS certificate.
func (sentry *Sentry) TLSCertPath() string {
return nodeTLSCertPath(sentry.dir)
}

func (sentry *Sentry) startNode() error {
validators, err := resolveValidators(sentry.net, sentry.validatorIndices)
if err != nil {
return err
}

args := newArgBuilder().
debugAllowTestKeys().
sentry().
tendermintCoreListenAddress(sentry.consensusPort).
sentryControlPort(sentry.controlPort).
appendNetwork(sentry.net).
addValidatorsAsPrivatePeers(validators)

if _, err := sentry.net.startOasisNode(sentry.dir, nil, args, "sentry", false, false); err != nil {
return fmt.Errorf("oasis/sentry: failed to launch node: %w", err)
}

return nil
}

// NewSentry provisions a new sentry node and adds it to the network.
func (net *Network) NewSentry(cfg *SentryCfg) (*Sentry, error) {
sentryName := fmt.Sprintf("sentry-%d", len(net.sentries))

sentryDir, err := net.baseDir.NewSubDir(sentryName)
if err != nil {
net.logger.Error("failed to create sentry subdir",
"err", err,
"sentry_name", sentryName,
)
return nil, fmt.Errorf("oasis/sentry: failed to create sentry subdir: %w", err)
}

// Pre-provision node's identity to pass the sentry node's consensus
// address to the validator so it can configure the sentry node's consensus
// address as its consensus address.
signerFactory := fileSigner.NewFactory(sentryDir.String(), signature.SignerNode, signature.SignerP2P, signature.SignerConsensus)
sentryIdentity, err := identity.LoadOrGenerate(sentryDir.String(), signerFactory)
if err != nil {
net.logger.Error("failed to provision sentry identity",
"err", err,
"sentry_name", sentryName,
)
return nil, fmt.Errorf("oasis/sentry: failed to provision sentry identity: %w", err)
}
sentryPublicKey := sentryIdentity.NodeSigner.Public()

sentry := &Sentry{
net: net,
dir: sentryDir,
validatorIndices: cfg.ValidatorIndices,
publicKey: sentryPublicKey,
tmAddress: crypto.PublicKeyToTendermint(&sentryPublicKey).Address().String(),
consensusPort: net.nextNodePort,
controlPort: net.nextNodePort + 1,
}

net.sentries = append(net.sentries, sentry)
net.nextNodePort += 2

return sentry, nil
}
Loading

0 comments on commit dfcc4b0

Please sign in to comment.