Skip to content

Commit

Permalink
go/keymanager/churp: Implement backend
Browse files Browse the repository at this point in the history
  • Loading branch information
peternose committed Feb 24, 2024
1 parent 642bc7a commit 2a1baa1
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 11 deletions.
36 changes: 36 additions & 0 deletions go/consensus/cometbft/apps/keymanager/churp/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package churp

import (
"context"

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

// Query is the key manager query interface.
type Query interface {
Status(context.Context, common.Namespace, uint8) (*churp.Status, error)
Statuses(context.Context, common.Namespace) ([]*churp.Status, error)
AllStatuses(context.Context) ([]*churp.Status, error)
}

type querier struct {
state *churpState.ImmutableState
}

func (kq *querier) Status(ctx context.Context, runtimeID common.Namespace, churpID uint8) (*churp.Status, error) {
return kq.state.Status(ctx, runtimeID, churpID)
}

func (kq *querier) Statuses(ctx context.Context, runtimeID common.Namespace) ([]*churp.Status, error) {
return kq.state.Statuses(ctx, runtimeID)
}

func (kq *querier) AllStatuses(ctx context.Context) ([]*churp.Status, error) {
return kq.state.AllStatuses(ctx)
}

func NewQuery(state *churpState.ImmutableState) Query {
return &querier{state}
}
25 changes: 21 additions & 4 deletions go/consensus/cometbft/apps/keymanager/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import (
"context"

abciAPI "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/churp"
churpState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/churp/state"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/secrets"
secretsState "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager/secrets/state"
)

// Query is the key manager query interface.
type Query interface {
Secrets() secrets.Query
Churp() churp.Query
}

// QueryFactory is the key manager query factory.
Expand All @@ -20,19 +23,33 @@ type QueryFactory struct {

// QueryAt returns the key manager query interface for a specific height.
func (sf *QueryFactory) QueryAt(ctx context.Context, height int64) (Query, error) {
state, err := secretsState.NewImmutableState(ctx, sf.state, height) // TODO: not ok
secretsState, err := secretsState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}
return &keymanagerQuerier{state}, nil

churpState, err := churpState.NewImmutableState(ctx, sf.state, height)
if err != nil {
return nil, err
}

return &keymanagerQuerier{
secretsState: secretsState,
churpState: churpState,
}, nil
}

type keymanagerQuerier struct {
state *secretsState.ImmutableState
secretsState *secretsState.ImmutableState
churpState *churpState.ImmutableState
}

func (kq *keymanagerQuerier) Secrets() secrets.Query {
return secrets.NewQuery(kq.state)
return secrets.NewQuery(kq.secretsState)
}

func (kq *keymanagerQuerier) Churp() churp.Query {
return churp.NewQuery(kq.churpState)
}

func (app *keymanagerApplication) QueryFactory() interface{} {
Expand Down
12 changes: 6 additions & 6 deletions go/consensus/cometbft/apps/keymanager/secrets/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ type querier struct {
state *secretsState.ImmutableState
}

func (kq *querier) Status(ctx context.Context, id common.Namespace) (*secrets.Status, error) {
return kq.state.Status(ctx, id)
func (kq *querier) Status(ctx context.Context, runtimeID common.Namespace) (*secrets.Status, error) {
return kq.state.Status(ctx, runtimeID)
}

func (kq *querier) Statuses(ctx context.Context) ([]*secrets.Status, error) {
return kq.state.Statuses(ctx)
}

func (kq *querier) MasterSecret(ctx context.Context, id common.Namespace) (*secrets.SignedEncryptedMasterSecret, error) {
return kq.state.MasterSecret(ctx, id)
func (kq *querier) MasterSecret(ctx context.Context, runtimeID common.Namespace) (*secrets.SignedEncryptedMasterSecret, error) {
return kq.state.MasterSecret(ctx, runtimeID)
}

func (kq *querier) EphemeralSecret(ctx context.Context, id common.Namespace) (*secrets.SignedEncryptedEphemeralSecret, error) {
return kq.state.EphemeralSecret(ctx, id)
func (kq *querier) EphemeralSecret(ctx context.Context, runtimeID common.Namespace) (*secrets.SignedEncryptedEphemeralSecret, error) {
return kq.state.EphemeralSecret(ctx, runtimeID)
}

func (kq *querier) Genesis(ctx context.Context) (*secrets.Genesis, error) {
Expand Down
118 changes: 118 additions & 0 deletions go/consensus/cometbft/keymanager/churp/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package churp

import (
"context"

cmtabcitypes "github.com/cometbft/cometbft/abci/types"
"github.com/eapache/channels"

"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/pubsub"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
"github.com/oasisprotocol/oasis-core/go/consensus/api/events"
app "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager"
"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
"github.com/oasisprotocol/oasis-core/go/registry/api"
)

type ServiceClient struct {
logger *logging.Logger

querier *app.QueryFactory
statusNotifier *pubsub.Broker
}

// Status implements churp.Backend.
func (sc *ServiceClient) Status(ctx context.Context, query *churp.StatusQuery) (*churp.Status, error) {
q, err := sc.querier.QueryAt(ctx, query.Height)
if err != nil {
return nil, err
}

return q.Churp().Status(ctx, query.RuntimeID, query.ChurpID)
}

// Statuses implements churp.Backend.
func (sc *ServiceClient) Statuses(ctx context.Context, query *api.NamespaceQuery) ([]*churp.Status, error) {
q, err := sc.querier.QueryAt(ctx, query.Height)
if err != nil {
return nil, err
}

return q.Churp().Statuses(ctx, query.ID)
}

// AllStatuses implements churp.Backend.
func (sc *ServiceClient) AllStatuses(ctx context.Context, height int64) ([]*churp.Status, error) {
q, err := sc.querier.QueryAt(ctx, height)
if err != nil {
return nil, err
}

return q.Churp().AllStatuses(ctx)
}

// WatchStatuses implements churp.Backend.
func (sc *ServiceClient) WatchStatuses() (<-chan *churp.Status, *pubsub.Subscription) {
sub := sc.statusNotifier.Subscribe()
ch := make(chan *churp.Status)
sub.Unwrap(ch)

return ch, sub
}

func (sc *ServiceClient) DeliverEvent(ev *cmtabcitypes.Event) error {
for _, pair := range ev.GetAttributes() {
key := pair.GetKey()
val := pair.GetValue()

if events.IsAttributeKind(key, &churp.CreateEvent{}) {
var event churp.CreateEvent
if err := events.DecodeValue(val, &event); err != nil {
sc.logger.Error("worker: failed to get status from tag",
"err", err,
)
continue
}

sc.statusNotifier.Broadcast(event.Status)
}
if events.IsAttributeKind(key, &churp.UpdateEvent{}) {
var event churp.UpdateEvent
if err := events.DecodeValue(val, &event); err != nil {
sc.logger.Error("worker: failed to get status from tag",
"err", err,
)
continue
}

sc.statusNotifier.Broadcast(event.Status)
}
}
return nil
}

// New constructs a new CometBFT backed key manager secrets management Backend
// instance.
func New(ctx context.Context, querier *app.QueryFactory) (*ServiceClient, error) {
sc := ServiceClient{
logger: logging.GetLogger("cometbft/keymanager/churp"),
querier: querier,
}
sc.statusNotifier = pubsub.NewBrokerEx(func(ch channels.Channel) {
statuses, err := sc.AllStatuses(ctx, consensus.HeightLatest)
if err != nil {
sc.logger.Error("status notifier: unable to get a list of statuses",
"err", err,
)
return
}

wr := ch.In()
for _, v := range statuses {
wr <- v
}
})

return &sc, nil
}
20 changes: 19 additions & 1 deletion go/consensus/cometbft/keymanager/keymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import (

tmapi "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/api"
app "github.com/oasisprotocol/oasis-core/go/consensus/cometbft/apps/keymanager"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/keymanager/churp"
"github.com/oasisprotocol/oasis-core/go/consensus/cometbft/keymanager/secrets"
"github.com/oasisprotocol/oasis-core/go/keymanager/api"
churpAPI "github.com/oasisprotocol/oasis-core/go/keymanager/churp"
secretsAPI "github.com/oasisprotocol/oasis-core/go/keymanager/secrets"
)

Expand All @@ -27,6 +29,7 @@ type serviceClient struct {
tmapi.BaseServiceClient

secretsClient *secrets.ServiceClient
churpClient *churp.ServiceClient
}

// Implements api.Backend.
Expand All @@ -44,14 +47,22 @@ func (sc *serviceClient) Secrets() secretsAPI.Backend {
return sc.secretsClient
}

// Implements api.Backend.
func (sc *serviceClient) Churp() churpAPI.Backend {
return sc.churpClient
}

// Implements api.ServiceClient.
func (sc *serviceClient) ServiceDescriptor() tmapi.ServiceDescriptor {
return tmapi.NewStaticServiceDescriptor(api.ModuleName, app.EventType, []cmtpubsub.Query{app.QueryApp})
}

// Implements api.ServiceClient.
func (sc *serviceClient) DeliverEvent(_ context.Context, _ int64, _ cmttypes.Tx, ev *cmtabcitypes.Event) error {
return sc.secretsClient.DeliverEvent(ev)
if err := sc.secretsClient.DeliverEvent(ev); err != nil {
return err
}
return sc.churpClient.DeliverEvent(ev)
}

// New constructs a new CometBFT backed key manager management Backend
Expand All @@ -63,13 +74,20 @@ func New(ctx context.Context, backend tmapi.Backend) (ServiceClient, error) {
}

querier := a.QueryFactory().(*app.QueryFactory)

secretsClient, err := secrets.New(ctx, querier)
if err != nil {
return nil, fmt.Errorf("cometbft/keymanager: failed to create secrets client: %w", err)
}

churpClient, err := churp.New(ctx, querier)
if err != nil {
return nil, fmt.Errorf("cometbft/keymanager: failed to create churp client: %w", err)
}

sc := serviceClient{
secretsClient: secretsClient,
churpClient: churpClient,
}

return &sc, nil
Expand Down
4 changes: 4 additions & 0 deletions go/keymanager/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
memorySigner "github.com/oasisprotocol/oasis-core/go/common/crypto/signature/signers/memory"
"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
"github.com/oasisprotocol/oasis-core/go/keymanager/secrets"
)

Expand Down Expand Up @@ -41,6 +42,9 @@ type Backend interface {

// Secrets returns the key manager secrets management implementation.
Secrets() secrets.Backend

// Churp returns the key manager CHURP management implementation.
Churp() churp.Backend
}

// Genesis is the key manager management genesis state.
Expand Down
8 changes: 8 additions & 0 deletions go/keymanager/api/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,34 @@ package api
import (
"google.golang.org/grpc"

"github.com/oasisprotocol/oasis-core/go/keymanager/churp"
"github.com/oasisprotocol/oasis-core/go/keymanager/secrets"
)

// RegisterService registers a new keymanager backend service with the given gRPC server.
func RegisterService(server *grpc.Server, service Backend) {
secrets.RegisterService(server, service.Secrets())
churp.RegisterService(server, service.Churp())
}

// KeymanagerClient is a gRPC keymanager client.
type KeymanagerClient struct {
secretsClient *secrets.Client
churpClient *churp.Client
}

func (c *KeymanagerClient) Secrets() *secrets.Client {
return c.secretsClient
}

func (c *KeymanagerClient) Churp() *churp.Client {
return c.churpClient
}

// NewKeymanagerClient creates a new gRPC keymanager client service.
func NewKeymanagerClient(c *grpc.ClientConn) *KeymanagerClient {
return &KeymanagerClient{
secretsClient: secrets.NewClient(c),
churpClient: churp.NewClient(c),
}
}
8 changes: 8 additions & 0 deletions go/keymanager/churp/api.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package churp

import (
"github.com/oasisprotocol/oasis-core/go/common"
"github.com/oasisprotocol/oasis-core/go/common/errors"
"github.com/oasisprotocol/oasis-core/go/consensus/api/transaction"
)
Expand Down Expand Up @@ -67,3 +68,10 @@ func NewUpdateTx(nonce uint64, fee *transaction.Fee, req *UpdateRequest) *transa
func NewApplyTx(nonce uint64, fee *transaction.Fee, req *SignedApplicationRequest) *transaction.Transaction {
return transaction.NewTransaction(nonce, fee, MethodApply, req)
}

// StatusQuery is a status query by CHURP and runtime ID.
type StatusQuery struct {
Height int64 `json:"height"`
RuntimeID common.Namespace `json:"runtime_id"`
ChurpID uint8 `json:"churp_id"`
}
Loading

0 comments on commit 2a1baa1

Please sign in to comment.