Skip to content

Commit

Permalink
Merge pull request #5572 from oasisprotocol/peternose/feature/churp-w…
Browse files Browse the repository at this point in the history
…orker

go/worker/keymanager: Add churp worker
  • Loading branch information
peternose authored Feb 27, 2024
2 parents d1cf150 + 59bb780 commit 4e2e498
Show file tree
Hide file tree
Showing 15 changed files with 736 additions and 29 deletions.
1 change: 1 addition & 0 deletions .changelog/5572.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go/worker/keymanager: Add churp worker
8 changes: 0 additions & 8 deletions go/consensus/cometbft/apps/keymanager/churp/ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ package churp
import (
"fmt"

"github.com/cometbft/cometbft/abci/types"

"github.com/oasisprotocol/oasis-core/go/common/cbor"
"github.com/oasisprotocol/oasis-core/go/consensus/api"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
tmapi "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
registryState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/registry/state"
genesis "github.com/oasisprotocol/oasis-core/go/genesis/api"
"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
)

Expand Down Expand Up @@ -88,11 +85,6 @@ func (*churpExt) EndBlock(*tmapi.Context) error {
return nil
}

// InitChain implements api.Extension.
func (ext *churpExt) InitChain(*tmapi.Context, types.RequestInitChain, *genesis.Document) error {
return nil
}

func (*churpExt) enabled(ctx *tmapi.Context) (bool, error) {
regState := registryState.NewMutableState(ctx.State())
regParams, err := regState.ConsensusParameters(ctx)
Expand Down
27 changes: 27 additions & 0 deletions go/consensus/cometbft/apps/keymanager/churp/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package churp

import (
"fmt"

"github.com/cometbft/cometbft/abci/types"

tmapi "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
churpState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/churp/state"
genesis "github.com/oasisprotocol/oasis-core/go/genesis/api"
"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
)

// InitChain implements api.Extension.
func (ext *churpExt) InitChain(ctx *tmapi.Context, _ types.RequestInitChain, _ *genesis.Document) error {
if enabled, err := ext.enabled(ctx); err != nil || !enabled {
return nil
}

state := churpState.NewMutableState(ctx.State())

if err := state.SetConsensusParameters(ctx, &churp.DefaultConsensusParameters); err != nil {
return fmt.Errorf("cometbft/keymanager/churp: failed to set consensus parameters: %w", err)
}

return nil
}
12 changes: 12 additions & 0 deletions go/keymanager/churp/rpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package churp

// RPCMethodInit is the name of the `init` method.
var RPCMethodInit = "churp/init"

// InitRequest represents an initialization request.
type InitRequest struct {
Identity

// Round is the round for which the node would like to register.
Round uint64 `json:"round,omitempty"`
}
2 changes: 2 additions & 0 deletions go/oasis-test-runner/oasis/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ type KeymanagerFixture struct {
LogWatcherHandlerFactories []log.WatcherHandlerFactory `json:"-"`

PrivatePeerPubKeys []string `json:"private_peer_pub_keys,omitempty"`
ChurpIDs []uint8 `json:"churp_ids,omitempty"`
}

// Create instantiates the key manager described by the fixture.
Expand Down Expand Up @@ -364,6 +365,7 @@ func (f *KeymanagerFixture) Create(net *Network) (*Keymanager, error) {
Policy: policy,
SentryIndices: f.Sentries,
PrivatePeerPubKeys: f.PrivatePeerPubKeys,
ChurpIDs: f.ChurpIDs,
})
}

Expand Down
15 changes: 15 additions & 0 deletions go/oasis-test-runner/oasis/keymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
registry "github.com/oasisprotocol/oasis-core/go/registry/api"
"github.com/oasisprotocol/oasis-core/go/runtime/bundle"
runtimeConfig "github.com/oasisprotocol/oasis-core/go/runtime/config"
keymanagerConfig "github.com/oasisprotocol/oasis-core/go/worker/keymanager/config"
)

const (
Expand Down Expand Up @@ -164,6 +165,7 @@ type Keymanager struct { // nolint: maligned
p2pPort uint16

privatePeerPubKeys []string
churpIDs []uint8
}

// KeymanagerCfg is the Oasis key manager provisioning configuration.
Expand All @@ -178,6 +180,9 @@ type KeymanagerCfg struct {

// PrivatePeerPubKeys is a list of base64-encoded libp2p public keys of peers who may call non-public methods.
PrivatePeerPubKeys []string

// ChurpIDs is a list of supported CHURP schemes.
ChurpIDs []uint8
}

// IdentityKeyPath returns the paths to the node's identity key.
Expand Down Expand Up @@ -296,6 +301,15 @@ func (km *Keymanager) ModifyConfig() error {
km.Config.Keymanager.RuntimeID = km.runtime.ID().String()
km.Config.Keymanager.PrivatePeerPubKeys = km.privatePeerPubKeys

// Configuration for the CHURP key manager extension.
schemes := make([]keymanagerConfig.ChurpSchemeConfig, len(km.churpIDs))
for i, id := range km.churpIDs {
schemes[i] = keymanagerConfig.ChurpSchemeConfig{
ID: id,
}
}
km.Config.Keymanager.Churp.Schemes = schemes

// Sentry configuration.
sentries, err := resolveSentries(km.net, km.sentryIndices)
if err != nil {
Expand Down Expand Up @@ -349,6 +363,7 @@ func (net *Network) NewKeymanager(cfg *KeymanagerCfg) (*Keymanager, error) {
consensusPort: host.getProvisionedPort(nodePortConsensus),
p2pPort: host.getProvisionedPort(nodePortP2P),
privatePeerPubKeys: cfg.PrivatePeerPubKeys,
churpIDs: cfg.ChurpIDs,
}

// Remove any exploded bundles on cleanup.
Expand Down
120 changes: 120 additions & 0 deletions go/oasis-test-runner/scenario/e2e/runtime/keymanager_churp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package runtime

import (
"context"
"fmt"

"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/env"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/oasis"
"github.com/oasisprotocol/oasis-core/go/oasis-test-runner/scenario"
)

// KeymanagerChurp is the key manager CHURP scenario.
var KeymanagerChurp scenario.Scenario = newKmChurpImpl()

type kmChurpImpl struct {
Scenario
}

func newKmChurpImpl() scenario.Scenario {
return &kmChurpImpl{
Scenario: *NewScenario(
"keymanager-churp",
NewTestClient(),
),
}
}

func (sc *kmChurpImpl) Clone() scenario.Scenario {
return &kmChurpImpl{
Scenario: *sc.Scenario.Clone().(*Scenario),
}
}

func (sc *kmChurpImpl) Fixture() (*oasis.NetworkFixture, error) {
f, err := sc.Scenario.Fixture()
if err != nil {
return nil, err
}

// We don't need compute workers.
f.ComputeWorkers = []oasis.ComputeWorkerFixture{}

// Ensure that the key manager workers participate in the CHURP scheme.
f.Keymanagers[0].ChurpIDs = []uint8{0}

// Enable CHURP extension.
f.Network.EnableKeyManagerCHURP = true

return f, nil
}

func (sc *kmChurpImpl) Run(ctx context.Context, _ *env.Env) error {
var nonce uint64

if err := sc.Net.Start(); err != nil {
return err
}

if err := sc.Net.ClientController().WaitReady(ctx); err != nil {
return err
}

stCh, stSub, err := sc.Net.ClientController().Keymanager.Churp().WatchStatuses(ctx)
if err != nil {
return err
}
defer stSub.Close()

// Create a new CHURP instance.
identity := churp.Identity{
ID: 0,
RuntimeID: KeyManagerRuntimeID,
}
req := churp.CreateRequest{
Identity: identity,
GroupID: churp.EccNistP384,
Threshold: 2,
HandoffInterval: 1,
Policy: churp.SignedPolicySGX{
Policy: churp.PolicySGX{
Identity: identity,
},
},
}

tx := churp.NewCreateTx(nonce, &transaction.Fee{Gas: 10000}, &req)
entSigner := sc.Net.Entities()[0].Signer()
sigTx, err := transaction.Sign(entSigner, tx)
if err != nil {
return fmt.Errorf("failed signing create churp transaction: %w", err)
}
err = sc.Net.Controller().Consensus.SubmitTx(ctx, sigTx)
if err != nil {
return fmt.Errorf("failed submitting create churp transaction: %w", err)
}

// Test wether the key manager node submits an application every round.
var st *churp.Status
for i := range 4 {
select {
case st = <-stCh:
case <-ctx.Done():
return ctx.Err()
}

round := uint64(i / 2)
if st.Round != round {
return fmt.Errorf("expected round %d, not round %d", round, st.Round)
}

// New round started or node just submitted an application.
if appSize := i % 2; len(st.Applications) != appSize {
return fmt.Errorf("status should have %d applications", appSize)
}
}

return nil
}
1 change: 1 addition & 0 deletions go/oasis-test-runner/scenario/e2e/runtime/scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ func RegisterScenarios() error {
KeymanagerReplicateMany,
KeymanagerRotationFailure,
KeymanagerUpgrade,
KeymanagerChurp,
// Dump/restore test.
DumpRestore,
DumpRestoreRuntimeRoundAdvance,
Expand Down
16 changes: 16 additions & 0 deletions go/worker/keymanager/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/common/version"
"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
"github.com/oasisprotocol/oasis-core/go/keymanager/secrets"
enclaverpc "github.com/oasisprotocol/oasis-core/go/runtime/enclaverpc/api"
)
Expand Down Expand Up @@ -104,6 +105,9 @@ type Status struct {

// Secrets is the master and ephemeral secrets status.
Secrets *SecretsStatus `json:"secrets"`

// Churp is the CHURP status.
Churp ChurpStatus `json:"churp"`
}

// SecretsStatus is the key manager master and ephemeral secrets status.
Expand Down Expand Up @@ -170,6 +174,18 @@ type EphemeralSecretStats struct {
LastGenerated beacon.EpochTime `json:"last_generated_epoch"`
}

// ChurpStatus represents the status of the key manager CHURP extension.
type ChurpStatus struct {
// Schemes is a list of CHURP scheme configurations.
Schemes map[uint8]ChurpSchemeStatus `json:"schemes,omitempty"`
}

// ChurpSchemeStatus represents the status of a CHURP scheme.
type ChurpSchemeStatus struct {
// Status is the consensus status of the CHURP scheme.
Status *churp.Status `json:"status,omitempty"`
}

// RPCAccessController handles the authorization of enclave RPC calls.
type RPCAccessController interface {
// Methods returns a list of allowed methods.
Expand Down
Loading

0 comments on commit 4e2e498

Please sign in to comment.