From b61eaefb0d8a27f6bae1802f418818a51cddcbde Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Thu, 12 Mar 2020 15:32:01 +0000 Subject: [PATCH] Add chain status --- cmd/chaininfo.go | 9 ++---- cmd/chainstatus.go | 72 +++++++++++++++++++++++++++++++++++++++++++++ cmd/version.go | 2 +- grpc/beaconchain.go | 9 ++++++ 4 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 cmd/chainstatus.go diff --git a/cmd/chaininfo.go b/cmd/chaininfo.go index f6a4b66..b0e9bf0 100644 --- a/cmd/chaininfo.go +++ b/cmd/chaininfo.go @@ -43,13 +43,10 @@ In quiet mode this will return 0 if the chain information can be obtained, other os.Exit(_exit_success) } - for k, v := range config { - fmt.Printf("%v => %v\n", k, v) - } fmt.Printf("Genesis time:\t\t%s\n", genesisTime.Format(time.UnixDate)) slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(uint64)) fmt.Printf("Current slot:\t\t%d\n", slot) - fmt.Printf("Current epoch:\t\t%d\n", slot/int64(config["SlotsPerEpoch"].(uint64))) + fmt.Printf("Current epoch:\t\t%d\n", slot/config["SlotsPerEpoch"].(uint64)) outputIf(verbose, fmt.Sprintf("Genesis fork version:\t%0x", config["GenesisForkVersion"].([]byte))) outputIf(verbose, fmt.Sprintf("Genesis timestamp:\t%v", genesisTime.Unix())) outputIf(verbose, fmt.Sprintf("Seconds per slot:\t%v", config["SecondsPerSlot"].(uint64))) @@ -64,9 +61,9 @@ func init() { chainFlags(chainInfoCmd) } -func timestampToSlot(genesis int64, timestamp int64, secondsPerSlot uint64) int64 { +func timestampToSlot(genesis int64, timestamp int64, secondsPerSlot uint64) uint64 { if timestamp < genesis { return 0 } - return (timestamp - genesis) / int64(secondsPerSlot) + return uint64(timestamp-genesis) / secondsPerSlot } diff --git a/cmd/chainstatus.go b/cmd/chainstatus.go new file mode 100644 index 0000000..ae0f166 --- /dev/null +++ b/cmd/chainstatus.go @@ -0,0 +1,72 @@ +// Copyright © 2020 Weald Technology Trading +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + "time" + + "github.com/spf13/cobra" + "github.com/wealdtech/ethdo/grpc" +) + +var chainStatusCmd = &cobra.Command{ + Use: "status", + Short: "Obtain status about a chain", + Long: `Obtain status about a chain. For example: + + ethdo chain status + +In quiet mode this will return 0 if the chain status can be obtained, otherwise 1.`, + Run: func(cmd *cobra.Command, args []string) { + err := connect() + errCheck(err, "Failed to obtain connection to Ethereum 2 beacon chain node") + config, err := grpc.FetchChainConfig(eth2GRPCConn) + errCheck(err, "Failed to obtain beacon chain configuration") + + genesisTime, err := grpc.FetchGenesis(eth2GRPCConn) + errCheck(err, "Failed to obtain genesis time") + + info, err := grpc.FetchChainInfo(eth2GRPCConn) + errCheck(err, "Failed to obtain chain info") + + if quiet { + os.Exit(_exit_success) + } + + slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(uint64)) + fmt.Printf("Current slot:\t\t%d\n", slot) + fmt.Printf("Finalized slot:\t\t%d", info.GetFinalizedSlot()) + if verbose { + distance := slot - info.GetFinalizedSlot() + fmt.Printf(" (%d)", distance) + } + fmt.Printf("\n") + fmt.Printf("Justified slot:\t\t%d", info.GetJustifiedSlot()) + if verbose { + distance := slot - info.GetJustifiedSlot() + fmt.Printf(" (%d)", distance) + } + fmt.Printf("\n") + outputIf(verbose, fmt.Sprintf("Prior justified slot:\t%v (%d)", info.GetPreviousJustifiedSlot(), slot-info.GetPreviousJustifiedSlot())) + + os.Exit(_exit_success) + }, +} + +func init() { + chainCmd.AddCommand(chainStatusCmd) + chainFlags(chainStatusCmd) +} diff --git a/cmd/version.go b/cmd/version.go index 04df02d..f1fedb5 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -30,7 +30,7 @@ var versionCmd = &cobra.Command{ ethdo version.`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("1.2.3") + fmt.Println("1.2.4") if viper.GetBool("verbose") { buildInfo, ok := dbg.ReadBuildInfo() if ok { diff --git a/grpc/beaconchain.go b/grpc/beaconchain.go index 54375c1..8a011c1 100644 --- a/grpc/beaconchain.go +++ b/grpc/beaconchain.go @@ -107,3 +107,12 @@ func FetchValidatorInfo(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.V } return stream.Recv() } + +// FetchChainInfo fetches current chain info from the beacon node. +func FetchChainInfo(conn *grpc.ClientConn) (*ethpb.ChainHead, error) { + beaconClient := ethpb.NewBeaconChainClient(conn) + ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout")) + defer cancel() + + return beaconClient.GetChainHead(ctx, &empty.Empty{}) +}