Skip to content

Commit

Permalink
Merge pull request #3999 from oasisprotocol/yawning/feature/3897
Browse files Browse the repository at this point in the history
 Make current beacon status available via the CLI
  • Loading branch information
Yawning authored Jun 7, 2021
2 parents 2e939b2 + 26cad5b commit 01b0f8c
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 7 deletions.
4 changes: 4 additions & 0 deletions .changelog/3897.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go/oasis-node/cmd/debug/beacon: Initial import

Add a `debug beacon status` command which queries the current beacon and
PVSS backend state.
47 changes: 47 additions & 0 deletions go/beacon/api/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ var (
methodStateToGenesis = serviceName.NewMethod("StateToGenesis", int64(0))
// methodConsensusParameters is the ConsensusParameters method.
methodConsensusParameters = serviceName.NewMethod("ConsensusParameters", int64(0))
// methodGetPVSSState is the GetPVSSState method.
methodGetPVSSState = serviceName.NewMethod("GetPVSSState", nil)

// methodWatchEpochs is the WatchEpochs method.
methodWatchEpochs = serviceName.NewMethod("WatchEpochs", nil)
Expand Down Expand Up @@ -71,6 +73,10 @@ var (
MethodName: methodConsensusParameters.ShortName(),
Handler: handlerConsensusParameters,
},
{
MethodName: methodGetPVSSState.ShortName(),
Handler: handlerGetPVSSState,
},
},
Streams: []grpc.StreamDesc{
{
Expand Down Expand Up @@ -262,6 +268,33 @@ func handlerConsensusParameters( //nolint:golint
return interceptor(ctx, height, info, handler)
}

func handlerGetPVSSState( //nolint:golint
srv interface{},
ctx context.Context,
dec func(interface{}) error,
interceptor grpc.UnaryServerInterceptor,
) (interface{}, error) {
pvssBackend, ok := srv.(PVSSBackend)
if !ok {
return nil, fmt.Errorf("beacon: not using PVSS backend")
}
var height int64
if err := dec(&height); err != nil {
return nil, err
}
if interceptor == nil {
return pvssBackend.GetPVSSState(ctx, height)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: methodGetPVSSState.FullName(),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return pvssBackend.GetPVSSState(ctx, req.(int64))
}
return interceptor(ctx, height, info, handler)
}

func handlerWatchEpochs(srv interface{}, stream grpc.ServerStream) error {
if err := stream.RecvMsg(nil); err != nil {
return err
Expand Down Expand Up @@ -400,6 +433,20 @@ func (c *beaconClient) ConsensusParameters(ctx context.Context, height int64) (*
return &rsp, nil
}

func (c *beaconClient) GetPVSSState(ctx context.Context, height int64) (*PVSSState, error) {
var rsp PVSSState
if err := c.conn.Invoke(ctx, methodGetPVSSState.FullName(), height, &rsp); err != nil {
return nil, err
}
return &rsp, nil
}

func (c *beaconClient) WatchLatestPVSSEvent(ctx context.Context) (<-chan *PVSSEvent, *pubsub.Subscription, error) {
// The only thing that uses this is the beacon worker, and it is not
// over gRPC.
return nil, nil, fmt.Errorf("beacon: gRPC method not implemented")
}

func (c *beaconClient) Cleanup() {
}

Expand Down
2 changes: 1 addition & 1 deletion go/beacon/api/pvss.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,5 @@ type PVSSBackend interface {
// from the channel, old events are overwritten.
//
// Upon subscription the current round event is sent immediately.
WatchLatestPVSSEvent() (<-chan *PVSSEvent, *pubsub.Subscription)
WatchLatestPVSSEvent(ctx context.Context) (<-chan *PVSSEvent, *pubsub.Subscription, error)
}
4 changes: 2 additions & 2 deletions go/consensus/tendermint/beacon/beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,12 @@ func (sc *serviceClient) GetPVSSState(ctx context.Context, height int64) (*beaco
return q.PVSSState(ctx)
}

func (sc *serviceClient) WatchLatestPVSSEvent() (<-chan *beaconAPI.PVSSEvent, *pubsub.Subscription) {
func (sc *serviceClient) WatchLatestPVSSEvent(ctx context.Context) (<-chan *beaconAPI.PVSSEvent, *pubsub.Subscription, error) {
typedCh := make(chan *beaconAPI.PVSSEvent)
sub := sc.pvssNotifier.Subscribe()
sub.Unwrap(typedCh)

return typedCh, sub
return typedCh, sub, nil
}

func (sc *serviceClient) SetEpoch(ctx context.Context, epoch beaconAPI.EpochTime) error {
Expand Down
5 changes: 5 additions & 0 deletions go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ replace (
// Can be removed once there is a spf13/viper release with updated etcd.
// https://github.com/spf13/viper/issues/956
github.com/coreos/etcd => github.com/coreos/etcd v3.3.25+incompatible
// Updates the version used by badgerdb, because some of the Go
// module caches apparently have a messed up copy that causes
// build failures.
// https://github.com/google/flatbuffers/issues/6466
github.com/google/flatbuffers => github.com/google/flatbuffers v1.12.1
// Updates the version used in spf13/cobra (dependency via tendermint) as
// there is no release yet with the fix. Remove once an updated release of
// spf13/cobra exists and tendermint is updated to include it.
Expand Down
4 changes: 2 additions & 2 deletions go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/flatbuffers v1.12.0 h1:/PtAHvnBY4Kqnx/xCQ3OIV9uYcSFGScBsWI3Oogeh6w=
github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw=
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
Expand Down
102 changes: 102 additions & 0 deletions go/oasis-node/cmd/debug/beacon/beacon.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Package beacon implements the beacon introspection debug sub-commands.
package beacon

import (
"context"
"encoding/json"
"fmt"
"os"

"github.com/spf13/cobra"
"google.golang.org/grpc"

beacon "github.com/oasisprotocol/oasis-core/go/beacon/api"
"github.com/oasisprotocol/oasis-core/go/common/logging"
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
cmdCommon "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common"
cmdGrpc "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/grpc"
)

var (
beaconCmd = &cobra.Command{
Use: "beacon",
Short: "debug the random beacon",
}

beaconStatusCmd = &cobra.Command{
Use: "status",
Short: "query beacon status",
Run: doBeaconStatus,
}

logger = logging.GetLogger("cmd/debug/beacon")
)

func doConnect(cmd *cobra.Command) (*grpc.ClientConn, beacon.Backend) {
if err := cmdCommon.Init(); err != nil {
cmdCommon.EarlyLogAndExit(err)
}

conn, err := cmdGrpc.NewClient(cmd)
if err != nil {
logger.Error("failed to establish connection with node",
"err", err,
)
os.Exit(1)
}

client := beacon.NewBeaconClient(conn)

return conn, client
}

func doBeaconStatus(cmd *cobra.Command, args []string) {
conn, client := doConnect(cmd)
defer conn.Close()

logger.Info("querying latest beacon")

b, err := client.GetBeacon(context.Background(), consensus.HeightLatest)
if err != nil {
logger.Error("failed to query beacon",
"err", err,
)
os.Exit(1)
}

// I'm going to be sad if people use this as a way to programatically
// scrape the beacon. Oh well.
prettyOut := struct {
Beacon []byte
State *beacon.PVSSState
}{
Beacon: b,
}

pvssClient, ok := client.(beacon.PVSSBackend)
if ok {
prettyOut.State, err = pvssClient.GetPVSSState(context.Background(), consensus.HeightLatest)
if err != nil {
logger.Error("failed to query PVSS backend state",
"err", err,
)
os.Exit(1)
}
}

formatted, err := json.MarshalIndent(prettyOut, "", " ")
if err != nil {
logger.Error("failed to format state",
"err", err,
)
os.Exit(1)
}
fmt.Println(string(formatted))
}

// Register registers the beacon sub-command and all of it's children.
func Register(parentCmd *cobra.Command) {
beaconCmd.PersistentFlags().AddFlagSet(cmdGrpc.ClientFlags)

beaconCmd.AddCommand(beaconStatusCmd)
}
5 changes: 4 additions & 1 deletion go/oasis-node/cmd/debug/byzantine/beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ func doBeaconScenario(cmd *cobra.Command, args []string) {
}

// Start watching for PVSS events
ch, sub := backend.WatchLatestPVSSEvent()
ch, sub, err := backend.WatchLatestPVSSEvent(ctx)
if err != nil {
panic(fmt.Sprintf("failed to subscribe to PVSS events: %+v", err))
}
defer sub.Close()

var iter int
Expand Down
2 changes: 2 additions & 0 deletions go/oasis-node/cmd/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package debug
import (
"github.com/spf13/cobra"

"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/debug/beacon"
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/debug/byzantine"
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/debug/consim"
"github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/debug/control"
Expand All @@ -27,6 +28,7 @@ func Register(parentCmd *cobra.Command) {
control.Register(debugCmd)
consim.Register(debugCmd)
dumpdb.Register(debugCmd)
beacon.Register(debugCmd)

parentCmd.AddCommand(debugCmd)
}
8 changes: 7 additions & 1 deletion go/worker/beacon/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,13 @@ func (w *Worker) worker() {
w.recoverPersistedState()

// Subscribe to PVSS events.
eventCh, eventSub := w.backend.WatchLatestPVSSEvent()
eventCh, eventSub, err := w.backend.WatchLatestPVSSEvent(w.ctx)
if err != nil {
w.logger.Error("failed to subscribe to PVSS events",
"err", err,
)
return
}
defer eventSub.Close()

for {
Expand Down

0 comments on commit 01b0f8c

Please sign in to comment.