44 "context"
55 "encoding/base64"
66 "fmt"
7+ "maps"
78 "os"
89
910 "github.com/spf13/cobra"
@@ -14,7 +15,9 @@ import (
1415 "github.com/oasisprotocol/oasis-core/go/common/sgx"
1516 "github.com/oasisprotocol/oasis-core/go/common/version"
1617 "github.com/oasisprotocol/oasis-core/go/runtime/bundle"
18+ "github.com/oasisprotocol/oasis-sdk/client-sdk/go/client"
1719 "github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection"
20+ "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rofl"
1821
1922 buildRofl "github.com/oasisprotocol/cli/build/rofl"
2023 "github.com/oasisprotocol/cli/cmd/common"
3336 buildMode string
3437 offline bool
3538 doUpdate bool
39+ doVerify bool
3640 deploymentName string
3741
3842 Cmd = & cobra.Command {
4448 npa := common .GetNPASelection (cfg )
4549 manifest , deployment := roflCommon .LoadManifestAndSetNPA (cfg , npa , deploymentName , true )
4650
51+ if doVerify && doUpdate {
52+ cobra .CheckErr ("only one of --verify and --update-manifest may be passed" )
53+ }
54+
4755 fmt .Println ("Building a ROFL application..." )
4856 fmt .Printf ("Deployment: %s\n " , deploymentName )
4957 fmt .Printf ("Network: %s\n " , deployment .Network )
@@ -147,14 +155,83 @@ var (
147155
148156 runScript (manifest , buildRofl .ScriptBundlePost )
149157
158+ buildEnclaves := make (map [sgx.EnclaveIdentity ]struct {})
159+ for _ , eid := range eids {
160+ buildEnclaves [* eid ] = struct {}{}
161+ }
162+
163+ manifestEnclaves := make (map [sgx.EnclaveIdentity ]struct {})
164+ for _ , eid := range deployment .Policy .Enclaves {
165+ manifestEnclaves [eid ] = struct {}{}
166+ }
167+
168+ // Perform verification when requested.
169+ if doVerify {
170+ showIdentityDiff := func (build , other map [sgx.EnclaveIdentity ]struct {}, otherName string ) {
171+ fmt .Println ("Built enclave identities:" )
172+ for enclaveID := range build {
173+ data , _ := enclaveID .MarshalText ()
174+ fmt .Printf (" - %s\n " , string (data ))
175+ }
176+
177+ fmt .Printf ("%s enclave identities:\n " , otherName )
178+ for enclaveID := range other {
179+ data , _ := enclaveID .MarshalText ()
180+ fmt .Printf (" - %s\n " , string (data ))
181+ }
182+ }
183+
184+ if ! maps .Equal (buildEnclaves , manifestEnclaves ) {
185+ fmt .Println ("Built enclave identities DIFFER from manifest enclave identities!" )
186+ showIdentityDiff (buildEnclaves , manifestEnclaves , "Manifest" )
187+ cobra .CheckErr (fmt .Errorf ("enclave identity verification failed" ))
188+ }
189+
190+ fmt .Println ("Built enclave identities MATCH manifest enclave identities." )
191+
192+ // When not in offline mode, also verify on-chain enclave identities.
193+ if ! offline {
194+ var conn connection.Connection
195+ ctx := context .Background ()
196+ conn , err = connection .Connect (ctx , npa .Network )
197+ cobra .CheckErr (err )
198+
199+ var appID rofl.AppID
200+ _ = appID .UnmarshalText ([]byte (deployment .AppID )) // Already verified.
201+
202+ var appCfg * rofl.AppConfig
203+ appCfg , err = conn .Runtime (npa .ParaTime ).ROFL .App (ctx , client .RoundLatest , appID )
204+ cobra .CheckErr (err )
205+
206+ cfgEnclaves := make (map [sgx.EnclaveIdentity ]struct {})
207+ for _ , eid := range appCfg .Policy .Enclaves {
208+ cfgEnclaves [eid ] = struct {}{}
209+ }
210+
211+ if ! maps .Equal (manifestEnclaves , cfgEnclaves ) {
212+ fmt .Println ("Built enclave identities DIFFER from on-chain enclave identities!" )
213+ showIdentityDiff (buildEnclaves , cfgEnclaves , "On-chain" )
214+ cobra .CheckErr (fmt .Errorf ("enclave identity verification failed" ))
215+ }
216+
217+ fmt .Println ("Built enclave identities MATCH on-chain enclave identities." )
218+ }
219+ return
220+ }
221+
150222 // Override the update manifest flag in case the policy does not exist.
151223 if deployment .Policy == nil {
152224 doUpdate = false
153225 }
154226
155227 switch doUpdate {
156228 case false :
157- // Ask the user to update the manifest manually.
229+ // Ask the user to update the manifest manually (if the manifest has changed).
230+ if maps .Equal (buildEnclaves , manifestEnclaves ) {
231+ fmt .Println ("Built enclave identities already match manifest enclave identities." )
232+ break
233+ }
234+
158235 fmt .Println ("Update the manifest with the following identities to use the new app:" )
159236 fmt .Println ()
160237 fmt .Printf ("deployments:\n " )
@@ -177,6 +254,8 @@ var (
177254 if err = manifest .Save (); err != nil {
178255 cobra .CheckErr (fmt .Errorf ("failed to update manifest: %w" , err ))
179256 }
257+
258+ fmt .Printf ("Run `oasis rofl update` to update your ROFL app's on-chain configuration.\n " )
180259 }
181260 },
182261 }
@@ -258,6 +337,7 @@ func init() {
258337 buildFlags .BoolVar (& offline , "offline" , false , "do not perform any operations requiring network access" )
259338 buildFlags .StringVar (& outputFn , "output" , "" , "output bundle filename" )
260339 buildFlags .BoolVar (& doUpdate , "update-manifest" , false , "automatically update the manifest" )
340+ buildFlags .BoolVar (& doVerify , "verify" , false , "verify build against manifest and on-chain state" )
261341 buildFlags .StringVar (& deploymentName , "deployment" , buildRofl .DefaultDeploymentName , "deployment name" )
262342
263343 Cmd .Flags ().AddFlagSet (buildFlags )
0 commit comments