@@ -50,7 +50,6 @@ import Concordium.Wasm
50
50
import Control.Monad.Trans
51
51
import qualified Data.ByteString as BS
52
52
import Data.Coerce
53
- import Data.Foldable
54
53
import Data.Map.Strict (Map )
55
54
import qualified Data.Map.Strict as Map
56
55
import Data.Serialize
@@ -152,76 +151,85 @@ instance HashableTo Hash Module where
152
151
instance (Monad m ) => MHashableTo m Hash Module
153
152
instance (MonadBlobStore m ) => Cacheable m Module
154
153
154
+ -- | Load a module from the underlying storage, without recompiling the artifact.
155
+ loadModuleDirect :: (MonadLogger m , MonadBlobStore m ) => BlobRef Module -> m Module
156
+ loadModuleDirect br = do
157
+ bs <- loadRaw br
158
+ let getModule = do
159
+ -- Offset of the start of the module
160
+ startOffset <- fromIntegral <$> bytesRead
161
+ -- Header
162
+ miModuleRef <- get
163
+ miExposedInit <- getSafeSetOf get
164
+ miExposedReceive <- getSafeMapOf get (getSafeSetOf get)
165
+ -- Artifact is serialized as @InstrumentedModule v@.
166
+ artVersion <- get
167
+ artLen <- getWord32be
168
+ -- Offset of the start of the artifact
169
+ artOffset <- fromIntegral <$> bytesRead
170
+ -- Skip the actual body of the artifact; we deserialize as a 'BlobPtr' instead.
171
+ skip (fromIntegral artLen)
172
+ -- Footer
173
+ miModuleSize <- getWord64be
174
+ let miModule :: PersistentInstrumentedModuleV v
175
+ miModule =
176
+ PIMVPtr
177
+ BlobPtr
178
+ { theBlobPtr =
179
+ -- Start of the blob ref
180
+ theBlobRef br
181
+ -- Add the size of the length field for the blob ref
182
+ + 8
183
+ -- Add the offset of the artifact
184
+ + artOffset
185
+ -- Subtract the starting offset
186
+ - startOffset,
187
+ blobPtrLen = fromIntegral artLen
188
+ }
189
+ moduleVInterface :: GSWasm. ModuleInterfaceA (PersistentInstrumentedModuleV v )
190
+ moduleVInterface = GSWasm. ModuleInterface {.. }
191
+ case artVersion of
192
+ V0 -> do
193
+ moduleVSource <- get
194
+ return $! ModuleV0 (ModuleV {.. })
195
+ V1 -> do
196
+ moduleVSource <- get
197
+ return $! ModuleV1 (ModuleV {.. })
198
+ case runGet getModule bs of
199
+ Left e -> error (e ++ " :: " ++ show bs)
200
+ Right mv -> return mv
201
+
155
202
-- | This instance is based on and should be compatible with the 'Serialize' instance
156
203
-- for 'BasicModuleInterface'.
157
204
instance (MonadLogger m , MonadBlobStore m , MonadProtocolVersion m ) => DirectBlobStorable m Module where
158
- loadDirect br = do
159
- bs <- loadRaw br
160
- let getModule = do
161
- -- Offset of the start of the module
162
- startOffset <- fromIntegral <$> bytesRead
163
- -- Header
164
- miModuleRef <- get
165
- miExposedInit <- getSafeSetOf get
166
- miExposedReceive <- getSafeMapOf get (getSafeSetOf get)
167
- -- Artifact is serialized as @InstrumentedModule v@.
168
- artVersion <- get
169
- artLen <- getWord32be
170
- -- Offset of the start of the artifact
171
- artOffset <- fromIntegral <$> bytesRead
172
- -- Skip the actual body of the artifact; we deserialize as a 'BlobPtr' instead.
173
- skip (fromIntegral artLen)
174
- -- Footer
175
- miModuleSize <- getWord64be
176
- let miModule :: PersistentInstrumentedModuleV v
177
- miModule =
178
- PIMVPtr
179
- BlobPtr
180
- { theBlobPtr =
181
- -- Start of the blob ref
182
- theBlobRef br
183
- -- Add the size of the length field for the blob ref
184
- + 8
185
- -- Add the offset of the artifact
186
- + artOffset
187
- -- Subtract the starting offset
188
- - startOffset,
189
- blobPtrLen = fromIntegral artLen
190
- }
191
- moduleVInterface :: GSWasm. ModuleInterfaceA (PersistentInstrumentedModuleV v )
192
- moduleVInterface = GSWasm. ModuleInterface {.. }
193
- case artVersion of
194
- V0 -> do
195
- moduleVSource <- get
196
- return $! ModuleV0 (ModuleV {.. })
197
- V1 -> do
198
- moduleVSource <- get
199
- return $! ModuleV1 (ModuleV {.. })
200
- case runGet getModule bs of
201
- Left e -> error (e ++ " :: " ++ show bs)
202
- Right mv@ (ModuleV0 mv0@ (ModuleV {moduleVInterface = GSWasm. ModuleInterface {miModule = PIMVPtr artPtr, .. }, .. })) | potentialLegacyArtifacts -> do
203
- artBS <- loadBlobPtr artPtr
204
- if GSWasm. isV0LegacyArtifact artBS
205
- then do
206
- logEvent GlobalState LLTrace $ " Recompiling V0 module " ++ show miModuleRef
207
- source <- loadRef moduleVSource
208
- case WasmV0. compileModule CSV0 source of
209
- Nothing -> error " Stored module that is not valid."
210
- Just (_, compiled) -> do
211
- return $! ModuleV0 mv0{moduleVInterface = (moduleVInterface mv0){GSWasm. miModule = PIMVMem compiled}}
212
- else return mv
213
- Right mv@ (ModuleV1 mv1@ (ModuleV {moduleVInterface = GSWasm. ModuleInterface {miModule = PIMVPtr artPtr, .. }, .. })) | potentialLegacyArtifacts -> do
214
- artBS <- loadBlobPtr artPtr
215
- if GSWasm. isV0LegacyArtifact artBS
216
- then do
217
- logEvent GlobalState LLTrace $ " Recompiling V1 module " ++ show miModuleRef
218
- source <- loadRef moduleVSource
219
- case WasmV1. compileModule (WasmV1. validationConfigAllowP1P6 CSV0 ) source of
220
- Nothing -> error " Stored module that is not valid."
221
- Just (_, compiled) -> do
222
- return $! ModuleV1 mv1{moduleVInterface = (moduleVInterface mv1){GSWasm. miModule = PIMVMem compiled}}
223
- else return mv
224
- Right mv -> return mv
205
+ loadDirect br
206
+ | potentialLegacyArtifacts = do
207
+ mv <- loadModuleDirect br
208
+ case mv of
209
+ (ModuleV0 mv0@ (ModuleV {moduleVInterface = GSWasm. ModuleInterface {miModule = PIMVPtr artPtr, .. }, .. })) -> do
210
+ artBS <- loadBlobPtr artPtr
211
+ if GSWasm. isV0LegacyArtifact artBS
212
+ then do
213
+ logEvent GlobalState LLTrace $ " Recompiling V0 module " ++ show miModuleRef
214
+ source <- loadRef moduleVSource
215
+ case WasmV0. compileModule CSV0 source of
216
+ Nothing -> error " Stored module that is not valid."
217
+ Just (_, compiled) -> do
218
+ return $! ModuleV0 mv0{moduleVInterface = (moduleVInterface mv0){GSWasm. miModule = PIMVMem compiled}}
219
+ else return mv
220
+ (ModuleV1 mv1@ (ModuleV {moduleVInterface = GSWasm. ModuleInterface {miModule = PIMVPtr artPtr, .. }, .. })) -> do
221
+ artBS <- loadBlobPtr artPtr
222
+ if GSWasm. isV0LegacyArtifact artBS
223
+ then do
224
+ logEvent GlobalState LLTrace $ " Recompiling V1 module " ++ show miModuleRef
225
+ source <- loadRef moduleVSource
226
+ case WasmV1. compileModule (WasmV1. validationConfigAllowP1P6 CSV0 ) source of
227
+ Nothing -> error " Stored module that is not valid."
228
+ Just (_, compiled) -> do
229
+ return $! ModuleV1 mv1{moduleVInterface = (moduleVInterface mv1){GSWasm. miModule = PIMVMem compiled}}
230
+ else return mv
231
+ _ -> return mv
232
+ | otherwise = loadModuleDirect br
225
233
where
226
234
-- When a node is running protocol 6 or lower it might have been started prior to the new notion of Wasm
227
235
-- artifacts, which needs to be recompiled on load.
@@ -271,6 +279,14 @@ instance (MonadLogger m, MonadBlobStore m, MonadProtocolVersion m) => DirectBlob
271
279
mkModule SV0 = ModuleV0
272
280
mkModule SV1 = ModuleV1
273
281
282
+ instance (MonadBlobStore m ) => DirectBlobHashable m Hash Module where
283
+ loadHash br = do
284
+ bs <- loadRaw br
285
+ -- Decode the module reference only.
286
+ case decode bs of
287
+ Left e -> error $ " Could not decode stored module hash: " ++ e
288
+ Right ModuleRef {.. } -> return moduleRef
289
+
274
290
--------------------------------------------------------------------------------
275
291
276
292
-- | A cached 'Module' accessed via a cached 'Reference' i.e., a 'Reference'
@@ -320,13 +336,14 @@ instance (MonadProtocolVersion m, SupportsPersistentModule m) => BlobStorable m
320
336
table <- load
321
337
return $ do
322
338
_modulesTable <- table
323
- _modulesMap <-
324
- foldl'
325
- ( \ m (idx, aModule) ->
326
- Map. insert (GSWasm. moduleReference aModule) idx m
339
+ (_modulesMap, _) <-
340
+ LFMB. mfoldRef
341
+ ( \ (m, idx) modHCR -> do
342
+ modRef <- ModuleRef <$> getHashM modHCR
343
+ return $!! (Map. insert modRef idx m, idx + 1 )
327
344
)
328
- Map. empty
329
- <$> LFMB. toAscPairList _modulesTable
345
+ ( Map. empty, 0 )
346
+ _modulesTable
330
347
return Modules {.. }
331
348
storeUpdate m@ Modules {.. } = do
332
349
(pModulesTable, _modulesTable') <- storeUpdate _modulesTable
@@ -390,13 +407,24 @@ getInterface ::
390
407
getInterface ref mods = fmap getModuleInterface <$> getModule ref mods
391
408
392
409
-- | Get the source of a module by module reference.
410
+ -- This does not cache the module.
393
411
getSource :: (MonadProtocolVersion m , SupportsPersistentModule m ) => ModuleRef -> Modules -> m (Maybe WasmModule )
394
412
getSource ref mods = do
395
- m <- getModule ref mods
396
- case m of
413
+ mRef <- getModuleReference ref mods
414
+ case mRef of
397
415
Nothing -> return Nothing
398
- Just (ModuleV0 ModuleV {.. }) -> Just . WasmModuleV0 <$> loadRef moduleVSource
399
- Just (ModuleV1 ModuleV {.. }) -> Just . WasmModuleV1 <$> loadRef moduleVSource
416
+ Just hcref -> do
417
+ -- Since we only care about the source of the module, we can use 'loadModuleDirect',
418
+ -- which will bypass recompiling the artifact. It will also not cache the module,
419
+ -- but that is likely fine as the source is not cached anyway, and this is only
420
+ -- ultimately used in GRPC queries.
421
+ mdl <-
422
+ openHashedCachedRef hcref >>= \ case
423
+ Left r -> loadModuleDirect r
424
+ Right v -> return v
425
+ case mdl of
426
+ (ModuleV0 ModuleV {.. }) -> Just . WasmModuleV0 <$> loadRef moduleVSource
427
+ (ModuleV1 ModuleV {.. }) -> Just . WasmModuleV1 <$> loadRef moduleVSource
400
428
401
429
-- | Get the list of all currently deployed modules.
402
430
-- The order of the list is not specified.
0 commit comments