Skip to content

Commit 9b1e3d7

Browse files
authored
Merge pull request #699 from oasisprotocol/anzoman/feature/rofl-refresh-trust-root
cmd/rofl: Add set-trust-root subcommand
2 parents faeefa4 + b01588b commit 9b1e3d7

8 files changed

Lines changed: 164 additions & 13 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: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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 app manifest",
21+
Long: "Set the consensus block height and hash of the trust root in the ROFL app 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+
out, err := common.PrettyJSONMarshal(deployment.TrustRoot)
76+
cobra.CheckErr(err)
77+
fmt.Printf("Updated '%s' with trust root:\n%s\n", manifest.SourceFileName(), string(out))
78+
},
79+
}
80+
81+
func init() {
82+
setTrustRootCmd.Flags().AddFlagSet(common.SelectorNPFlags)
83+
setTrustRootCmd.Flags().AddFlagSet(roflCommon.DeploymentFlags)
84+
}

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+
}

cmd/rofl/trust_root.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ import (
1212
cliConfig "github.com/oasisprotocol/cli/config"
1313
)
1414

15+
// trustRoot is the consensus trust root for a ROFL application.
16+
type trustRoot struct {
17+
Height uint64 `json:"height"`
18+
Hash string `json:"hash"`
19+
RuntimeID string `json:"runtime_id"`
20+
ChainContext string `json:"chain_context"`
21+
}
22+
1523
var trustRootCmd = &cobra.Command{
1624
Use: "trust-root",
1725
Short: "Show a recent trust root for a ROFL application",
@@ -36,13 +44,16 @@ var trustRootCmd = &cobra.Command{
3644
blk, err := conn.Consensus().Core().GetBlock(ctx, height)
3745
cobra.CheckErr(err)
3846

39-
// TODO: Support different output formats.
40-
fmt.Printf("TrustRoot {\n")
41-
fmt.Printf(" height: %d,\n", height)
42-
fmt.Printf(" hash: \"%s\".into(),\n", blk.Hash)
43-
fmt.Printf(" runtime_id: \"%s\".into(),\n", npa.ParaTime.ID)
44-
fmt.Printf(" chain_context: \"%s\".to_string(),\n", npa.Network.ChainContext)
45-
fmt.Printf("}\n")
47+
tr := trustRoot{
48+
Height: uint64(height),
49+
Hash: blk.Hash.Hex(),
50+
RuntimeID: npa.ParaTime.ID,
51+
ChainContext: npa.Network.ChainContext,
52+
}
53+
54+
out, err := common.PrettyJSONMarshal(tr)
55+
cobra.CheckErr(err)
56+
fmt.Println(string(out))
4657
},
4758
}
4859

docs/rofl.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ needs to have a hardcoded *trust root*. Typically, it consists of:
541541
- the [chain domain separation context],
542542
- the specific consensus block hash and its height.
543543

544-
To obtain the latest trust root in rust programming language, run
544+
To obtain the latest trust root in JSON format, run
545545
`oasis rofl trust-root`:
546546

547547
![code shell](../examples/rofl/trust-root.in.static)
@@ -554,3 +554,20 @@ You can also define specific [Network and ParaTime][npa] parameters:
554554

555555
[ParaTime ID]: https://github.com/oasisprotocol/oasis-core/blob/master/docs/runtime/identifiers.md
556556
[chain domain separation context]: https://github.com/oasisprotocol/oasis-core/blob/master/docs/crypto.md#chain-domain-separation
557+
558+
### Set the trust root in the app manifest {#set-trust-root}
559+
560+
The consensus block height and hash of the [trust root](#trust-root) are stored
561+
in the deployment section of the `rofl.yaml` app manifest and are embedded into
562+
the app at build time. Instead of editing the manifest by hand, you can fetch
563+
the latest trust root and update the manifest automatically by running
564+
`oasis rofl set-trust-root`:
565+
566+
![code shell](../examples/rofl/set-trust-root.in.static)
567+
568+
![code](../examples/rofl/set-trust-root.out.static)
569+
570+
By default the latest finalized consensus block is used. You can also pass the
571+
block `height` (and optionally the block `hash`) as positional arguments to pin
572+
a specific block, or `--deployment` to update a non-default deployment. After
573+
setting the trust root, run [`oasis rofl build`](#build) for it to take effect.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
oasis rofl set-trust-root
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Updated 'rofl.yaml' with trust root:
2+
{
3+
"height": 1022,
4+
"hash": "bb3e63d729dd568ce07b37eea33eddf8082ed4cacbd64097aad32168a4a4fc9a"
5+
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
TrustRoot {
2-
height: 1022,
3-
hash: "bb3e63d729dd568ce07b37eea33eddf8082ed4cacbd64097aad32168a4a4fc9a".into(),
4-
runtime_id: "8000000000000000000000000000000000000000000000000000000000000000".into(),
5-
chain_context: "074f5ba071c4385a7ad24aea0a3a7b137901395e8f3b35479c1cce87d3170f4e".to_string(),
1+
{
2+
"height": 1022,
3+
"hash": "bb3e63d729dd568ce07b37eea33eddf8082ed4cacbd64097aad32168a4a4fc9a",
4+
"runtime_id": "8000000000000000000000000000000000000000000000000000000000000000",
5+
"chain_context": "074f5ba071c4385a7ad24aea0a3a7b137901395e8f3b35479c1cce87d3170f4e"
66
}

0 commit comments

Comments
 (0)