From 26994079b108efacf7104c700eeffed6bacb1adc Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Wed, 29 May 2024 16:48:04 +0200 Subject: [PATCH 1/2] Support detached ROFL components Previously each bundle that contained one or more ROFL components also needed to contain the exact version of the RONL component it was attaching to. This is somewhat awkward to use when we assume a more decentralized development and deployment of ROFL applications. This commit adds support for detached ROFL components where the bundle only contains the ROFL and oasis-node then automatically gets the appropriate RONL component from another bundle. --- .changelog/5707.feature.md | 11 +++ go/runtime/bundle/bundle.go | 29 +++++-- go/runtime/bundle/bundle_test.go | 97 ++++++++++++++++++++++-- go/runtime/bundle/component/component.go | 5 ++ go/runtime/bundle/manifest.go | 22 ++++-- go/runtime/host/composite/composite.go | 2 +- go/runtime/host/host.go | 13 ++++ go/runtime/host/multi/multi.go | 2 +- go/runtime/host/sandbox/sandbox.go | 11 ++- go/runtime/host/sgx/sgx.go | 4 +- go/runtime/registry/config.go | 70 +++++++++++++++-- go/runtime/registry/host.go | 2 +- go/runtime/registry/host_rofl.go | 20 +++-- runtime/src/attestation.rs | 6 +- runtime/src/dispatcher.rs | 10 ++- 15 files changed, 257 insertions(+), 47 deletions(-) create mode 100644 .changelog/5707.feature.md diff --git a/.changelog/5707.feature.md b/.changelog/5707.feature.md new file mode 100644 index 00000000000..2fecefc79a3 --- /dev/null +++ b/.changelog/5707.feature.md @@ -0,0 +1,11 @@ +Support detached ROFL components + +Previously each bundle that contained one or more ROFL components also +needed to contain the exact version of the RONL component it was +attaching to. + +This is somewhat awkward to use when we assume a more decentralized +development and deployment of ROFL applications. This commit adds support +for detached ROFL components where the bundle only contains the ROFL and +oasis-node then automatically gets the appropriate RONL component from +another bundle. diff --git a/go/runtime/bundle/bundle.go b/go/runtime/bundle/bundle.go index 7f23b588388..e49fd1c2fe0 100644 --- a/go/runtime/bundle/bundle.go +++ b/go/runtime/bundle/bundle.go @@ -280,19 +280,32 @@ func (bnd *Bundle) Write(fn string) error { return nil } -// ExplodedPath returns the path under the data directory that contains -// all of the exploded bundles. +// ExplodedPath returns the path under the data directory that contains all of the exploded bundles. func ExplodedPath(dataDir string) string { return filepath.Join(dataDir, "runtimes", "bundles") } -// ExplodedPath returns the path that the corresponding asset will be -// written to via WriteExploded. +// DetachedExplodedPath returns the path under the data directory that contains all of the detached +// exploded bundles. +func DetachedExplodedPath(dataDir string) string { + return filepath.Join(ExplodedPath(dataDir), "detached") +} + +// ExplodedPath returns the path that the corresponding asset will be written to via WriteExploded. func (bnd *Bundle) ExplodedPath(dataDir, fn string) string { - // DATADIR/runtimes/bundles/runtimeID-version - subDir := filepath.Join(ExplodedPath(dataDir), - fmt.Sprintf("%s-%s", bnd.Manifest.ID, bnd.Manifest.Version), - ) + var subDir string + switch bnd.Manifest.IsDetached() { + case false: + // DATADIR/runtimes/bundles/runtimeID-version + subDir = filepath.Join(ExplodedPath(dataDir), + fmt.Sprintf("%s-%s", bnd.Manifest.ID, bnd.Manifest.Version), + ) + case true: + // DATADIR/runtimes/bundles/detached/manifestHash + subDir = filepath.Join(DetachedExplodedPath(dataDir), + bnd.Manifest.Hash().String(), + ) + } if fn == "" { return subDir diff --git a/go/runtime/bundle/bundle_test.go b/go/runtime/bundle/bundle_test.go index 00006e1e661..d658f366020 100644 --- a/go/runtime/bundle/bundle_test.go +++ b/go/runtime/bundle/bundle_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/oasisprotocol/oasis-core/go/common" + "github.com/oasisprotocol/oasis-core/go/runtime/bundle/component" ) func TestBundle(t *testing.T) { @@ -32,15 +33,22 @@ func TestBundle(t *testing.T) { } return id }(), - Executable: "runtime.bin", - SGX: &SGXMetadata{ - Executable: "runtime.sgx", + Components: []*Component{ + { + Kind: component.RONL, + Executable: "runtime.bin", + SGX: &SGXMetadata{ + Executable: "runtime.sgx", + }, + }, }, } bundle := &Bundle{ Manifest: manifest, } + require.False(t, manifest.IsDetached(), "manifest with RONL component should not be detached") + t.Run("Add_Write", func(t *testing.T) { // Generate random assets. randomBuffer := func() []byte { @@ -50,9 +58,9 @@ func TestBundle(t *testing.T) { return b } - err := bundle.Add(manifest.Executable, execBuf) + err := bundle.Add(manifest.Components[0].Executable, execBuf) require.NoError(t, err, "bundle.Add(elf)") - err = bundle.Add(manifest.SGX.Executable, randomBuffer()) + err = bundle.Add(manifest.Components[0].SGX.Executable, randomBuffer()) require.NoError(t, err, "bundle.Add(sgx)") err = bundle.Write(bundleFn) @@ -94,3 +102,82 @@ func TestBundle(t *testing.T) { require.NoError(t, err, "WriteExploded(again)") }) } + +func TestDeatchedBundle(t *testing.T) { + execFile := os.Args[0] + execBuf, err := os.ReadFile(execFile) + if err != nil { + t.Fatalf("failed to read test executable %s: %v", execFile, err) + } + + // Create a synthetic bundle. + // + // Assets will be populated during the Add/Write combined test. + tmpDir := t.TempDir() + bundleFn := filepath.Join(tmpDir, "detached-bundle.orc") + manifest := &Manifest{ + Name: "test-runtime", + ID: func() common.Namespace { + var id common.Namespace + if err := id.UnmarshalHex("c000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"); err != nil { + panic("failed to unmarshal id") + } + return id + }(), + Components: []*Component{ + // No RONL component in the manifest. + { + Kind: component.ROFL, + Executable: "runtime.bin", + SGX: &SGXMetadata{ + Executable: "runtime.sgx", + }, + }, + }, + } + bundle := &Bundle{ + Manifest: manifest, + } + + require.True(t, manifest.IsDetached(), "manifest without RONL component should be detached") + + t.Run("Add_Write", func(t *testing.T) { + // Generate random assets. + randomBuffer := func() []byte { + b := make([]byte, 1024*256) + _, err := rand.Read(b) + require.NoError(t, err, "rand.Read") + return b + } + + err := bundle.Add(manifest.Components[0].Executable, execBuf) + require.NoError(t, err, "bundle.Add(elf)") + err = bundle.Add(manifest.Components[0].SGX.Executable, randomBuffer()) + require.NoError(t, err, "bundle.Add(sgx)") + + err = bundle.Write(bundleFn) + require.NoError(t, err, "bundle.Write") + }) + + t.Run("Open", func(t *testing.T) { + bundle2, err := Open(bundleFn) + require.NoError(t, err, "Open") + + // Ignore the manifest, the bundle we used to create the file + // will not have it. + delete(bundle2.Manifest.Digests, manifestName) + delete(bundle2.Data, manifestName) + + require.EqualValues(t, bundle, bundle2, "opened bundle mismatch") + }) + + t.Run("Explode", func(t *testing.T) { + err := bundle.WriteExploded(tmpDir) + require.NoError(t, err, "WriteExploded") + + // Abuse the fact that we do an integrity check if the bundle + // is already exploded. + err = bundle.WriteExploded(tmpDir) + require.NoError(t, err, "WriteExploded(again)") + }) +} diff --git a/go/runtime/bundle/component/component.go b/go/runtime/bundle/component/component.go index b93cf2f03c9..31073f8b46b 100644 --- a/go/runtime/bundle/component/component.go +++ b/go/runtime/bundle/component/component.go @@ -74,5 +74,10 @@ func (c *ID) UnmarshalText(text []byte) error { return nil } +// IsRONL returns true iff the component identifier is the special RONL component identifier. +func (c ID) IsRONL() bool { + return c == ID_RONL +} + // ID_RONL is the identifier of the RONL component. var ID_RONL = ID{Kind: RONL, Name: ""} //nolint: revive diff --git a/go/runtime/bundle/manifest.go b/go/runtime/bundle/manifest.go index dc1a343ca4e..c1b5e33164c 100644 --- a/go/runtime/bundle/manifest.go +++ b/go/runtime/bundle/manifest.go @@ -41,6 +41,11 @@ type Manifest struct { Digests map[string]hash.Hash `json:"digests"` } +// Hash returns a cryptographic hash of the CBOR-serialized manifest. +func (m *Manifest) Hash() hash.Hash { + return hash.NewFrom(m) +} + // Validate validates the manifest structure for well-formedness. func (m *Manifest) Validate() error { byID := make(map[component.ID]struct{}) @@ -69,22 +74,23 @@ func (m *Manifest) Validate() error { } } - // Ensure the RONL component is always defined. - if ronl := m.GetComponentByID(component.ID_RONL); ronl == nil { - return fmt.Errorf("runtime must define at least the RONL component") - } - return nil } +// IsDetached returns true iff the manifest does not include a RONL component. Such bundles require +// that the RONL component is provided out-of-band (e.g. in a separate bundle). +func (m *Manifest) IsDetached() bool { + return m.GetComponentByID(component.ID_RONL) == nil +} + // GetAvailableComponents collects all of the available components into a map. func (m *Manifest) GetAvailableComponents() map[component.ID]*Component { availableComps := make(map[component.ID]*Component) for _, comp := range m.Components { availableComps[comp.ID()] = comp } - if _, exists := availableComps[component.ID_RONL]; !exists { - // Needed for supporting legacy manifests -- always available, see Validate above. + if _, exists := availableComps[component.ID_RONL]; !exists && !m.IsDetached() { + // Needed for supporting legacy manifests. availableComps[component.ID_RONL] = m.GetComponentByID(component.ID_RONL) } return availableComps @@ -99,7 +105,7 @@ func (m *Manifest) GetComponentByID(id component.ID) *Component { } // We also support legacy manifests which define the RONL component at the top-level. - if id == component.ID_RONL && len(m.Executable) > 0 { + if id.IsRONL() && len(m.Executable) > 0 { return &Component{ Kind: component.RONL, Executable: m.Executable, diff --git a/go/runtime/host/composite/composite.go b/go/runtime/host/composite/composite.go index a44dbe0520d..6ca827edef3 100644 --- a/go/runtime/host/composite/composite.go +++ b/go/runtime/host/composite/composite.go @@ -72,7 +72,7 @@ func (c *composite) Call(ctx context.Context, body *protocol.Body) (*protocol.Bo } for id, comp := range c.comps { - if id == component.ID_RONL { + if id.IsRONL() { continue // Already handled above. } if !shouldPropagateToComponent(body) { diff --git a/go/runtime/host/host.go b/go/runtime/host/host.go index b597e7d9d56..1f8483b96a2 100644 --- a/go/runtime/host/host.go +++ b/go/runtime/host/host.go @@ -3,6 +3,7 @@ package host import ( "context" + "path/filepath" "github.com/oasisprotocol/oasis-core/go/common" "github.com/oasisprotocol/oasis-core/go/common/node" @@ -38,6 +39,18 @@ type RuntimeBundle struct { // ExplodedDataDir is the path to the data directory under which the bundle has been exploded. ExplodedDataDir string + + // ExplodedDetachedDirs are the paths to the data directories of detached components. + ExplodedDetachedDirs map[component.ID]string +} + +// ExplodedPath returns the path where the given asset for the given component can be found. +func (bnd *RuntimeBundle) ExplodedPath(comp component.ID, fn string) string { + if detachedDir, ok := bnd.ExplodedDetachedDirs[comp]; ok { + return filepath.Join(detachedDir, fn) + } + // Default to the exploded bundle. + return bnd.Bundle.ExplodedPath(bnd.ExplodedDataDir, fn) } // Provisioner is the runtime provisioner interface. diff --git a/go/runtime/host/multi/multi.go b/go/runtime/host/multi/multi.go index eed8b88d85f..7fca156771a 100644 --- a/go/runtime/host/multi/multi.go +++ b/go/runtime/host/multi/multi.go @@ -290,7 +290,7 @@ func (agg *Aggregate) Component(id component.ID) (host.Runtime, bool) { if cr, ok := active.host.(host.CompositeRuntime); ok { return cr.Component(id) } - if id == component.ID_RONL { + if id.IsRONL() { return active.host, true } return nil, false diff --git a/go/runtime/host/sandbox/sandbox.go b/go/runtime/host/sandbox/sandbox.go index 1f6cf380c76..b98a867d0e4 100644 --- a/go/runtime/host/sandbox/sandbox.go +++ b/go/runtime/host/sandbox/sandbox.go @@ -422,9 +422,12 @@ func (r *sandboxedRuntime) startProcess() (err error) { return fmt.Errorf("failed to initialize connection: %w", err) } - // Make sure the version matches what is configured in the bundle. - if bndVersion := r.rtCfg.Bundle.Manifest.Version; *rtVersion != bndVersion { - return fmt.Errorf("version mismatch (runtime reported: %s bundle: %s)", *rtVersion, bndVersion) + if r.rtCfg.Components[0].IsRONL() { + // Make sure the version matches what is configured in the bundle. This check is skipped for + // non-RONL components to support detached bundles. + if bndVersion := r.rtCfg.Bundle.Manifest.Version; *rtVersion != bndVersion { + return fmt.Errorf("version mismatch (runtime reported: %s bundle: %s)", *rtVersion, bndVersion) + } } hp := &HostInitializerParams{ @@ -661,7 +664,7 @@ func DefaultGetSandboxConfig(logger *logging.Logger, sandboxBinaryPath string) G "component", comp.Kind, ) return process.Config{ - Path: hostCfg.Bundle.ExplodedPath(hostCfg.Bundle.ExplodedDataDir, comp.Executable), + Path: hostCfg.Bundle.ExplodedPath(comp.ID(), comp.Executable), Env: map[string]string{ "OASIS_WORKER_HOST": socketPath, }, diff --git a/go/runtime/host/sgx/sgx.go b/go/runtime/host/sgx/sgx.go index b97c54a70b1..88089adcb44 100644 --- a/go/runtime/host/sgx/sgx.go +++ b/go/runtime/host/sgx/sgx.go @@ -182,7 +182,7 @@ func (s *sgxProvisioner) loadEnclaveBinaries(rtCfg host.Config, comp *bundle.Com if comp.SGX == nil || comp.SGX.Executable == "" { return nil, nil, fmt.Errorf("SGX executable not available in bundle") } - sgxExecutablePath := rtCfg.Bundle.ExplodedPath(rtCfg.Bundle.ExplodedDataDir, comp.SGX.Executable) + sgxExecutablePath := rtCfg.Bundle.ExplodedPath(comp.ID(), comp.SGX.Executable) var ( sig, sgxs []byte @@ -198,7 +198,7 @@ func (s *sgxProvisioner) loadEnclaveBinaries(rtCfg host.Config, comp *bundle.Com } if comp.SGX.Signature != "" { - sgxSignaturePath := rtCfg.Bundle.ExplodedPath(rtCfg.Bundle.ExplodedDataDir, comp.SGX.Signature) + sgxSignaturePath := rtCfg.Bundle.ExplodedPath(comp.ID(), comp.SGX.Signature) sig, err = os.ReadFile(sgxSignaturePath) if err != nil { return nil, nil, fmt.Errorf("failed to load SIGSTRUCT: %w", err) diff --git a/go/runtime/registry/config.go b/go/runtime/registry/config.go index b2a51142880..10b49fda979 100644 --- a/go/runtime/registry/config.go +++ b/go/runtime/registry/config.go @@ -226,10 +226,16 @@ func newConfig( //nolint: gocyclo }) } - // Configure runtimes. - rh.Runtimes = make(map[common.Namespace]map[version.Version]*runtimeHost.Config) + // Preprocess runtimes to separate detached from non-detached. + type nameKey struct { + runtime common.Namespace + comp component.ID + } + + var regularBundles []*bundle.Bundle + detachedBundles := make(map[common.Namespace][]*bundle.Bundle) + existingNames := make(map[nameKey]struct{}) for _, path := range config.GlobalConfig.Runtime.Paths { - // Open and explode the bundle. This will call Validate(). var bnd *bundle.Bundle if bnd, err = bundle.Open(path); err != nil { return nil, fmt.Errorf("failed to load runtime bundle '%s': %w", path, err) @@ -237,11 +243,38 @@ func newConfig( //nolint: gocyclo if err = bnd.WriteExploded(dataDir); err != nil { return nil, fmt.Errorf("failed to explode runtime bundle '%s': %w", path, err) } + // Release resources as the bundle has been exploded anyway. + bnd.Data = nil + + switch bnd.Manifest.IsDetached() { + case false: + // A regular non-detached bundle that has the RONL component. + regularBundles = append(regularBundles, bnd) + case true: + // A detached bundle without the RONL component that needs to be attached. + detachedBundles[bnd.Manifest.ID] = append(detachedBundles[bnd.Manifest.ID], bnd) + + // Ensure there are no name conflicts among the components. + for compID := range bnd.Manifest.GetAvailableComponents() { + nk := nameKey{bnd.Manifest.ID, compID} + if _, ok := existingNames[nk]; ok { + return nil, fmt.Errorf("duplicate component '%s' for runtime '%s'", compID, bnd.Manifest.ID) + } + existingNames[nk] = struct{}{} + } + } + } + // Configure runtimes. + rh.Runtimes = make(map[common.Namespace]map[version.Version]*runtimeHost.Config) + for _, bnd := range regularBundles { id := bnd.Manifest.ID if rh.Runtimes[id] == nil { rh.Runtimes[id] = make(map[version.Version]*runtimeHost.Config) } + if _, ok := rh.Runtimes[id][bnd.Manifest.Version]; ok { + return nil, fmt.Errorf("duplicate runtime '%s' version '%s'", id, bnd.Manifest.Version) + } // Get any local runtime configuration. var localConfig map[string]interface{} @@ -255,12 +288,30 @@ func newConfig( //nolint: gocyclo } } + rtBnd := &runtimeHost.RuntimeBundle{ + Bundle: bnd, + ExplodedDataDir: dataDir, + } + + // Merge in detached components. + for _, detachedBnd := range detachedBundles[id] { + for _, detachedComp := range detachedBnd.Manifest.Components { + // Skip components that already exist in the bundle itself. + if bnd.Manifest.GetComponentByID(detachedComp.ID()) != nil { + continue + } + + bnd.Manifest.Components = append(bnd.Manifest.Components, detachedComp) + rtBnd.ExplodedDetachedDirs[detachedComp.ID()] = detachedBnd.ExplodedPath(dataDir, "") + } + } + // Determine what kind of components we want. wantedComponents := []component.ID{ component.ID_RONL, } for _, comp := range bnd.Manifest.Components { - if comp.ID() == component.ID_RONL { + if comp.ID().IsRONL() { continue // Always enabled above. } @@ -285,10 +336,7 @@ func newConfig( //nolint: gocyclo } rh.Runtimes[id][bnd.Manifest.Version] = &runtimeHost.Config{ - Bundle: &runtimeHost.RuntimeBundle{ - Bundle: bnd, - ExplodedDataDir: dataDir, - }, + Bundle: rtBnd, Components: wantedComponents, LocalConfig: localConfig, } @@ -308,6 +356,12 @@ func newConfig( //nolint: gocyclo Bundle: &bundle.Bundle{ Manifest: &bundle.Manifest{ ID: id, + Components: []*bundle.Component{ + { + Kind: component.RONL, + Executable: "mock", + }, + }, }, }, }, diff --git a/go/runtime/registry/host.go b/go/runtime/registry/host.go index f1b1dd0423d..6f8206b02fa 100644 --- a/go/runtime/registry/host.go +++ b/go/runtime/registry/host.go @@ -492,7 +492,7 @@ func (h *runtimeHostHandler) handleHostIdentity() (*protocol.HostIdentityRespons func (h *runtimeHostHandler) NewSubHandler(cr host.CompositeRuntime, comp *bundle.Component) (host.RuntimeHandler, error) { switch comp.Kind { case component.ROFL: - return newSubHandlerROFL(h, cr) + return newSubHandlerROFL(h, cr, comp) default: return nil, fmt.Errorf("cannot create sub-handler for component '%s'", comp.Kind) } diff --git a/go/runtime/registry/host_rofl.go b/go/runtime/registry/host_rofl.go index f5fe27e2d47..743c2b5c021 100644 --- a/go/runtime/registry/host_rofl.go +++ b/go/runtime/registry/host_rofl.go @@ -28,14 +28,15 @@ const ( roflAttachRuntimeTimeout = 2 * time.Second // roflNotifyTimeout is the maximum amount of time runtime notification handling can take. roflNotifyTimeout = 2 * time.Second - // roflLocalStorageKeyPrefix is the implicit local storage prefix for all ROFL keys. - roflLocalStorageKeyPrefix = "rofl." + // roflLocalStorageKeySeparator is the local storage key separator after component ID. + roflLocalStorageKeySeparator = ":" ) // roflHostHandler is a host handler extended for use by ROFL components. type roflHostHandler struct { parent *runtimeHostHandler cr host.CompositeRuntime + comp *bundle.Component client runtimeClient.RuntimeClient eventNotifier *roflEventNotifier @@ -43,7 +44,7 @@ type roflHostHandler struct { logger *logging.Logger } -func newSubHandlerROFL(parent *runtimeHostHandler, cr host.CompositeRuntime) (host.RuntimeHandler, error) { +func newSubHandlerROFL(parent *runtimeHostHandler, cr host.CompositeRuntime, comp *bundle.Component) (host.RuntimeHandler, error) { client, err := parent.env.GetRuntimeRegistry().Client() if err != nil { return nil, err @@ -56,6 +57,7 @@ func newSubHandlerROFL(parent *runtimeHostHandler, cr host.CompositeRuntime) (ho return &roflHostHandler{ parent: parent, cr: cr, + comp: comp, client: client, eventNotifier: newROFLEventNotifier(parent.runtime, client, logger), logger: logger, @@ -72,6 +74,14 @@ func (rh *roflHostHandler) AttachRuntime(rt host.Runtime) error { return rh.eventNotifier.AttachRuntime(rt) } +// getLocalStorageKey returns a properly namespaced version of the local storage key. +func (rh *roflHostHandler) getLocalStorageKey(key []byte) []byte { + result, _ := rh.comp.ID().MarshalText() + result = append(result, roflLocalStorageKeySeparator...) + result = append(result, key...) + return result +} + // Implements protocol.Handler. func (rh *roflHostHandler) Handle(ctx context.Context, rq *protocol.Body) (*protocol.Body, error) { var ( @@ -84,11 +94,11 @@ func (rh *roflHostHandler) Handle(ctx context.Context, rq *protocol.Body) (*prot return rh.handleHostRPCCall(ctx, rq) case rq.HostLocalStorageGetRequest != nil: // Local storage get. - rq.HostLocalStorageGetRequest.Key = append([]byte(roflLocalStorageKeyPrefix), rq.HostLocalStorageGetRequest.Key...) + rq.HostLocalStorageGetRequest.Key = rh.getLocalStorageKey(rq.HostLocalStorageGetRequest.Key) return rh.parent.Handle(ctx, rq) case rq.HostLocalStorageSetRequest != nil: // Local storage set. - rq.HostLocalStorageSetRequest.Key = append([]byte(roflLocalStorageKeyPrefix), rq.HostLocalStorageSetRequest.Key...) + rq.HostLocalStorageSetRequest.Key = rh.getLocalStorageKey(rq.HostLocalStorageSetRequest.Key) return rh.parent.Handle(ctx, rq) case rq.HostSubmitTxRequest != nil: // Transaction submission. diff --git a/runtime/src/attestation.rs b/runtime/src/attestation.rs index 89c2ec2ff2e..52bdb3ed3c2 100644 --- a/runtime/src/attestation.rs +++ b/runtime/src/attestation.rs @@ -26,7 +26,7 @@ pub struct Handler { host: Arc, consensus_verifier: Arc, runtime_id: Namespace, - version: Version, + version: Option, logger: Logger, } @@ -37,7 +37,7 @@ impl Handler { host: Arc, consensus_verifier: Arc, runtime_id: Namespace, - version: Version, + version: Option, ) -> Self { Self { identity, @@ -98,7 +98,7 @@ impl Handler { // TODO: Make async. let consensus_verifier = self.consensus_verifier.clone(); - let version = Some(self.version); + let version = self.version; let runtime_id = self.runtime_id; let policy = tokio::task::block_in_place(move || { // Obtain current quote policy from (verified) consensus state. diff --git a/runtime/src/dispatcher.rs b/runtime/src/dispatcher.rs index bb6b6d29d74..c8f5637b999 100644 --- a/runtime/src/dispatcher.rs +++ b/runtime/src/dispatcher.rs @@ -265,6 +265,14 @@ impl Dispatcher { error!(self.logger, "ROFL application initialization failed"; "err" => ?err); } + // Determine what runtime version to support during remote attestation. For runtimes that + // define a ROFL application, we use `None` to signal that the active version is used. + let version = if app.is_supported() { + None + } else { + Some(protocol.get_config().version) + }; + let state = State { protocol: protocol.clone(), consensus_verifier: consensus_verifier.clone(), @@ -278,7 +286,7 @@ impl Dispatcher { protocol.clone(), consensus_verifier.clone(), protocol.get_runtime_id(), - protocol.get_config().version, + version, ), policy_verifier: Arc::new(PolicyVerifier::new(consensus_verifier)), cache_set: cache::CacheSet::new(protocol.clone()), From ef6ccb597ebcc7a006f2d4cb0880206b648f1574 Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Thu, 30 May 2024 09:18:35 +0200 Subject: [PATCH 2/2] go/runtime/bundle: Use manifest hash for bundle cache path --- go/runtime/bundle/bundle.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/runtime/bundle/bundle.go b/go/runtime/bundle/bundle.go index e49fd1c2fe0..0dae752c48d 100644 --- a/go/runtime/bundle/bundle.go +++ b/go/runtime/bundle/bundle.go @@ -296,9 +296,9 @@ func (bnd *Bundle) ExplodedPath(dataDir, fn string) string { var subDir string switch bnd.Manifest.IsDetached() { case false: - // DATADIR/runtimes/bundles/runtimeID-version + // DATADIR/runtimes/bundles/manifestHash subDir = filepath.Join(ExplodedPath(dataDir), - fmt.Sprintf("%s-%s", bnd.Manifest.ID, bnd.Manifest.Version), + bnd.Manifest.Hash().String(), ) case true: // DATADIR/runtimes/bundles/detached/manifestHash