Skip to content

Commit 1ac1221

Browse files
anzomanclaude
andcommitted
cmd/rofl: Add set-trust-root subcommand
Add a `set-trust-root` subcommand that writes the consensus trust root (block height and hash) into the deployment section of the rofl.yaml manifest. The block height and hash may be passed as positional arguments; when omitted, the latest finalized block is used, and when only the height is given, the corresponding hash is fetched from the network. The naming and positional-argument style mirror `oasis network set-chain-context`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent faeefa4 commit 1ac1221

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

cmd/rofl/rofl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func init() {
2525
Cmd.AddCommand(listCmd)
2626
Cmd.AddCommand(setDefaultCmd)
2727
Cmd.AddCommand(trustRootCmd)
28+
Cmd.AddCommand(setTrustRootCmd)
2829
Cmd.AddCommand(build.Cmd)
2930
Cmd.AddCommand(identityCmd)
3031
Cmd.AddCommand(secretCmd)

cmd/rofl/set_trust_root.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package rofl
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strconv"
7+
8+
"github.com/spf13/cobra"
9+
10+
consensus "github.com/oasisprotocol/oasis-core/go/consensus/api"
11+
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
12+
13+
buildRofl "github.com/oasisprotocol/cli/build/rofl"
14+
"github.com/oasisprotocol/cli/cmd/common"
15+
roflCommon "github.com/oasisprotocol/cli/cmd/rofl/common"
16+
)
17+
18+
var setTrustRootCmd = &cobra.Command{
19+
Use: "set-trust-root [height] [hash]",
20+
Short: "Set the trust root in the rofl.yaml manifest",
21+
Long: "Set the consensus block height and hash of the trust root in the rofl.yaml manifest.\n\n" +
22+
"If no arguments are passed, the latest finalized block is used. If only the height is\n" +
23+
"passed, the corresponding block hash is fetched from the network.",
24+
Args: cobra.RangeArgs(0, 2),
25+
Run: func(_ *cobra.Command, args []string) {
26+
// Load manifest and deployment, and configure network/paratime/account selection.
27+
manifest, deployment, npa := roflCommon.LoadManifestAndSetNPA(nil)
28+
29+
var (
30+
height uint64
31+
hash string
32+
)
33+
switch len(args) {
34+
case 2:
35+
// Both height and hash passed; set them directly without querying the network.
36+
h, err := strconv.ParseUint(args[0], 10, 64)
37+
if err != nil {
38+
cobra.CheckErr(fmt.Errorf("malformed height: %w", err))
39+
}
40+
height = h
41+
hash = args[1]
42+
default:
43+
// Determine the block height to query (latest by default).
44+
queryHeight := consensus.HeightLatest
45+
if len(args) == 1 {
46+
h, err := strconv.ParseInt(args[0], 10, 64)
47+
if err != nil {
48+
cobra.CheckErr(fmt.Errorf("malformed height: %w", err))
49+
}
50+
queryHeight = h
51+
}
52+
53+
// Establish connection with the target network and fetch the block.
54+
ctx := context.Background()
55+
conn, err := connection.Connect(ctx, npa.Network)
56+
cobra.CheckErr(err)
57+
58+
blk, err := conn.Consensus().Core().GetBlock(ctx, queryHeight)
59+
cobra.CheckErr(err)
60+
61+
height = uint64(blk.Height)
62+
hash = blk.Hash.Hex()
63+
}
64+
65+
if deployment.TrustRoot == nil {
66+
deployment.TrustRoot = &buildRofl.TrustRootConfig{}
67+
}
68+
deployment.TrustRoot.Height = height
69+
deployment.TrustRoot.Hash = hash
70+
71+
if err := manifest.Save(); err != nil {
72+
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
73+
}
74+
75+
fmt.Printf("Updated '%s' with trust root: height=%d, hash=%s\n", manifest.SourceFileName(), height, hash)
76+
},
77+
}
78+
79+
func init() {
80+
setTrustRootCmd.Flags().AddFlagSet(common.SelectorNPFlags)
81+
setTrustRootCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
82+
}

cmd/rofl/set_trust_root_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package rofl
2+
3+
import "testing"
4+
5+
func TestSetTrustRootUse(t *testing.T) {
6+
if got, want := setTrustRootCmd.Name(), "set-trust-root"; got != want {
7+
t.Fatalf("unexpected command name: got %q, want %q", got, want)
8+
}
9+
}
10+
11+
func TestSetTrustRootCommandRegistered(t *testing.T) {
12+
found := false
13+
for _, c := range Cmd.Commands() {
14+
if c == setTrustRootCmd || c.Name() == "set-trust-root" {
15+
found = true
16+
break
17+
}
18+
}
19+
if !found {
20+
t.Fatalf("set-trust-root command not registered under rofl.Cmd")
21+
}
22+
}
23+
24+
func TestSetTrustRootCommandFlags(t *testing.T) {
25+
// The command should expose selector flags (network/paratime) and deployment flags.
26+
names := []string{"network", "paratime", "no-paratime", "deployment"}
27+
for _, n := range names {
28+
if setTrustRootCmd.Flags().Lookup(n) == nil {
29+
t.Errorf("expected flag %q to be present", n)
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)