From bc12def208a5e8016e3393fc380d9c04edefaa4d Mon Sep 17 00:00:00 2001 From: amela Date: Fri, 18 Apr 2025 11:33:26 +0200 Subject: [PATCH] feat(cmd/network): Add nodes info to network show { | entities } --- cmd/network/show.go | 89 +++++++++++++++++++++- docs/network.md | 4 +- examples/network-show/id-entity.in.static | 1 + examples/network-show/id-entity.out | 7 -- examples/network-show/id-entity.out.static | 15 ++++ 5 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 examples/network-show/id-entity.in.static delete mode 100644 examples/network-show/id-entity.out create mode 100644 examples/network-show/id-entity.out.static diff --git a/cmd/network/show.go b/cmd/network/show.go index e1c3f83d..38a5a3f1 100644 --- a/cmd/network/show.go +++ b/cmd/network/show.go @@ -10,7 +10,9 @@ import ( "github.com/spf13/cobra" + "github.com/oasisprotocol/oasis-core/go/beacon/api" "github.com/oasisprotocol/oasis-core/go/common/crypto/signature" + "github.com/oasisprotocol/oasis-core/go/common/entity" consensusPretty "github.com/oasisprotocol/oasis-core/go/common/prettyprint" consensus "github.com/oasisprotocol/oasis-core/go/consensus/api" "github.com/oasisprotocol/oasis-core/go/consensus/api/transaction" @@ -19,6 +21,7 @@ import ( staking "github.com/oasisprotocol/oasis-core/go/staking/api" "github.com/oasisprotocol/oasis-core/go/staking/api/token" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/helpers" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/types" "github.com/oasisprotocol/cli/cmd/common" @@ -40,6 +43,87 @@ const ( selParameters ) +func printEntityNodes(ctx context.Context, npa *common.NPASelection, stakingConn staking.Backend, registryConn registry.Backend, beaconConn api.Backend, entity *entity.Entity, height int64) error { + epoch, err := beaconConn.GetEpoch(ctx, height) + if err != nil { + return err + } + + fmt.Printf("=== ENTITY ===\n") + + entityAddr := staking.NewAddress(entity.ID) + fmt.Printf("Entity Address: %s\n", entityAddr.String()) + + fmt.Printf("Entity ID: %s\n", entity.ID.String()) + + account, err := stakingConn.Account( + ctx, + &staking.OwnerQuery{Height: height, Owner: entityAddr}, + ) + if err != nil { + return err + } + + balance := &account.Escrow.Active.Balance + var fmtBalance string + if balance != nil { + fmtBalance = helpers.FormatConsensusDenomination(npa.Network, *balance) + } else { + fmtBalance = "unknown" + } + fmt.Printf("Stake: %s\n", fmtBalance) + + commission := account.Escrow.CommissionSchedule.CurrentRate(epoch) + var commissionString string + if commission != nil { + commissionString = staking.PrettyPrintCommissionRatePercentage(*commission) + } else { + commissionString = "not set" + } + fmt.Printf("Commission: %s\n", commissionString) + + fmt.Println() + fmt.Printf("=== NODES ===\n") + for i, node := range entity.Nodes { + nodeAddr := staking.NewAddress(node) + fmt.Printf("Node Address: %s\n", nodeAddr.String()) + fmt.Printf("Node ID: %s\n", node.String()) + idQuery2 := ®istry.IDQuery{ + Height: height, + ID: node, + } + + nodeStatus, err := registryConn.GetNodeStatus(ctx, idQuery2) + if err != nil { + fmt.Println(" Node is not active") + continue + } + + if node, err2 := registryConn.GetNode(ctx, idQuery2); err2 == nil { + fmt.Printf(" Node Roles: %s\n", node.Roles.String()) + fmt.Printf(" Software Version: %s\n", node.SoftwareVersion) + if len(node.Runtimes) > 0 { + fmt.Printf(" Runtimes:\n") + } + for _, runtime := range node.Runtimes { + fmt.Printf(" Runtime ID: %s\n", runtime.ID) + fmt.Printf(" Runtime Version: %s\n", runtime.Version) + } + fmt.Printf(" Node Status:\n") + fmt.Printf(" Expiration Processed: %t\n", nodeStatus.ExpirationProcessed) + fmt.Printf(" Freeze End Time: %d\n", nodeStatus.FreezeEndTime) + fmt.Printf(" Election Eligible After: %d\n", nodeStatus.ElectionEligibleAfter) + } else { + return fmt.Errorf("could not get a node: %s", err2) + } + + if i < len(entity.Nodes)-1 { + fmt.Println() + } + } + return nil +} + var showCmd = &cobra.Command{ Use: "show { | committees | entities | gas-costs | native-token | nodes | parameters | paratimes | validators }", Short: "Show network properties", @@ -63,6 +147,7 @@ var showCmd = &cobra.Command{ roothashConn := conn.Consensus().RootHash() schedulerConn := conn.Consensus().Scheduler() stakingConn := conn.Consensus().Staking() + beaconConn := conn.Consensus().Beacon() // Figure out the height to use if "latest". height, err := common.GetActualHeight( @@ -92,7 +177,7 @@ var showCmd = &cobra.Command{ } if entity, err := registryConn.GetEntity(ctx, idQuery); err == nil { - err = prettyPrint(entity) + err = printEntityNodes(ctx, npa, stakingConn, registryConn, beaconConn, entity, height) cobra.CheckErr(err) return } @@ -125,7 +210,7 @@ var showCmd = &cobra.Command{ cobra.CheckErr(err) // If this doesn't work the other large queries won't either. for _, entity := range entities { if staking.NewAddress(entity.ID).Equal(addr) { - err = prettyPrint(entity) + err = printEntityNodes(ctx, npa, stakingConn, registryConn, beaconConn, entity, height) cobra.CheckErr(err) return } diff --git a/docs/network.md b/docs/network.md index 21bcb217..b9ba80ec 100644 --- a/docs/network.md +++ b/docs/network.md @@ -410,9 +410,9 @@ The provided ID can be one of the following: - If the entity ID is provided, Oasis CLI shows information on the entity and its corresponding nodes in the network registry. For example: - ![code shell](../examples/network-show/id-entity.in) + ![code shell](../examples/network-show/id-entity.in.static) - ![code json](../examples/network-show/id-entity.out) + ![code json](../examples/network-show/id-entity.out.static) - If the node ID is provided, Oasis CLI shows detailed information of the node such as the Oasis Core software version, the node's role, supported diff --git a/examples/network-show/id-entity.in.static b/examples/network-show/id-entity.in.static new file mode 100644 index 00000000..6461d83f --- /dev/null +++ b/examples/network-show/id-entity.in.static @@ -0,0 +1 @@ +oasis network show xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ= diff --git a/examples/network-show/id-entity.out b/examples/network-show/id-entity.out deleted file mode 100644 index a98d567c..00000000 --- a/examples/network-show/id-entity.out +++ /dev/null @@ -1,7 +0,0 @@ -{ - "v": 2, - "id": "xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ=", - "nodes": [ - "Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM=" - ] -} diff --git a/examples/network-show/id-entity.out.static b/examples/network-show/id-entity.out.static new file mode 100644 index 00000000..2bae85d4 --- /dev/null +++ b/examples/network-show/id-entity.out.static @@ -0,0 +1,15 @@ +=== ENTITY === +Entity Address: oasis1qzp84num6xgspdst65yv7yqegln6ndcxmuuq8s9w +Entity ID: xQN6ffLSdc51EfEQ2BzltK1iWYAw6Y1CkBAbFzlhhEQ= +Stake: 11504987.432765658 ROSE +Commission: 20.0% + +=== NODES === +Node Address: oasis1qqzjrsadvr2q5qq5ev6xyspjses8cjxxdcrth0g7 +Node ID: Kb6opWKGbJHL0LK2Lto+m5ROIAXLhIr1lxQz0/kAOUM= + Node Roles: validator + Software Version: 24.1 + Node Status: + Expiration Processed: false + Freeze End Time: 0 + Election Eligible After: 38659