Skip to content

Commit 477610e

Browse files
feat: precompiled wasm blobs (#1291)
Co-authored-by: David Anyatonwu <[email protected]>
1 parent 6bcb3cf commit 477610e

File tree

18 files changed

+316
-139
lines changed

18 files changed

+316
-139
lines changed

crates/context/primitives/src/client/external/config.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::future::Future;
33
use calimero_context_config::client::env::config::ContextConfig;
44
use calimero_context_config::repr::{Repr, ReprBytes, ReprTransmute};
55
use calimero_context_config::types::{self as types, Capability};
6-
use calimero_primitives::application::Application;
6+
use calimero_primitives::application::{Application, ApplicationBlob};
7+
use calimero_primitives::blobs::BlobId;
78
use calimero_primitives::identity::{PrivateKey, PublicKey};
89
use eyre::{bail, OptionExt};
910

@@ -98,7 +99,11 @@ impl ExternalConfigClient<'_> {
9899
identity.rt().expect("infallible conversion"),
99100
types::Application::new(
100101
application.id.rt().expect("infallible conversion"),
101-
application.blob.rt().expect("infallible conversion"),
102+
application
103+
.blob
104+
.bytecode
105+
.rt()
106+
.expect("infallible conversion"),
102107
application.size,
103108
types::ApplicationSource(application.source.to_string().into()),
104109
types::ApplicationMetadata(Repr::new(application.metadata.as_slice().into())),
@@ -135,7 +140,11 @@ impl ExternalConfigClient<'_> {
135140
self.client.context_id.rt().expect("infallible conversion"),
136141
types::Application::new(
137142
application.id.rt().expect("infallible conversion"),
138-
application.blob.rt().expect("infallible conversion"),
143+
application
144+
.blob
145+
.bytecode
146+
.rt()
147+
.expect("infallible conversion"),
139148
application.size,
140149
types::ApplicationSource(application.source.to_string().into()),
141150
types::ApplicationMetadata(Repr::new(
@@ -346,7 +355,10 @@ impl ExternalConfigClient<'_> {
346355

347356
let application = Application::new(
348357
application.id.as_bytes().into(),
349-
application.blob.as_bytes().into(),
358+
ApplicationBlob {
359+
bytecode: application.blob.as_bytes().into(),
360+
compiled: BlobId::from([0; 32]),
361+
},
350362
application.size,
351363
application.source.0.parse()?,
352364
application.metadata.0.into_inner().into_owned(),

crates/context/primitives/src/client/sync.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl ContextClient {
9999
if !self.node_client.has_application(&application.id)? {
100100
let source: Url = application.source.into();
101101

102-
let metadata = application.metadata.to_vec();
102+
let metadata = application.metadata;
103103

104104
let derived_application_id = match source.scheme() {
105105
"http" | "https" => {
@@ -108,6 +108,7 @@ impl ContextClient {
108108
.await?
109109
}
110110
_ => {
111+
// fixme! we shouldn't assume both nodes run on the same machine
111112
self.node_client
112113
.install_application_from_path(source.path().into(), metadata)
113114
.await?

crates/context/src/handlers/create_context.rs

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl Handler<CreateContextRequest> for ContextManager {
4343
&self.context_client,
4444
&self.external_config,
4545
&mut self.contexts,
46+
&mut self.applications,
4647
protocol,
4748
seed,
4849
&application_id,
@@ -52,33 +53,48 @@ impl Handler<CreateContextRequest> for ContextManager {
5253
Err(err) => return ActorResponse::reply(Err(err)),
5354
};
5455

55-
let guard = prepared
56-
.context
56+
let Prepared {
57+
external_config,
58+
application,
59+
context,
60+
context_secret,
61+
identity,
62+
identity_secret,
63+
sender_key,
64+
} = prepared;
65+
66+
let guard = context
5767
.lock
5868
.clone()
5969
.try_lock_owned()
6070
.expect("logically exclusive");
6171

62-
let task = create_context(
63-
self.datastore.clone(),
64-
self.node_client.clone(),
65-
self.context_client.clone(),
66-
self.runtime_engine.clone(),
67-
prepared.external_config,
68-
prepared.context.meta,
69-
prepared.context_secret,
70-
prepared.application,
71-
prepared.identity,
72-
prepared.identity_secret,
73-
prepared.sender_key,
74-
init_params,
75-
guard,
76-
);
72+
let context = context.meta;
73+
74+
let module_task = self.get_module(application_id);
7775

7876
ActorResponse::r#async(
79-
task.into_actor(self)
77+
module_task
78+
.and_then(move |module, act, _ctx| {
79+
create_context(
80+
act.datastore.clone(),
81+
act.node_client.clone(),
82+
act.context_client.clone(),
83+
module,
84+
external_config,
85+
context,
86+
context_secret,
87+
application,
88+
identity,
89+
identity_secret,
90+
sender_key,
91+
init_params,
92+
guard,
93+
)
94+
.into_actor(act)
95+
})
8096
.map_ok(move |root_hash, act, _ctx| {
81-
if let Some(meta) = act.contexts.get_mut(&prepared.context.meta.id) {
97+
if let Some(meta) = act.contexts.get_mut(&context.id) {
8298
// this should almost always exist, but with an LruCache, it
8399
// may not. And if it's been evicted, the next execution will
84100
// re-create it with data from the store, so it's not a problem
@@ -87,12 +103,12 @@ impl Handler<CreateContextRequest> for ContextManager {
87103
}
88104

89105
CreateContextResponse {
90-
context_id: prepared.context.meta.id,
91-
identity: prepared.identity,
106+
context_id: context.id,
107+
identity,
92108
}
93109
})
94110
.map_err(move |err, act, _ctx| {
95-
let _ignored = act.contexts.remove(&prepared.context.meta.id);
111+
let _ignored = act.contexts.remove(&context.id);
96112

97113
err
98114
}),
@@ -116,6 +132,7 @@ impl Prepared<'_> {
116132
context_client: &ContextClient,
117133
external_config: &ExternalClientConfig,
118134
contexts: &mut BTreeMap<ContextId, ContextMeta>,
135+
applications: &mut BTreeMap<ApplicationId, Application>,
119136
protocol: String,
120137
seed: Option<[u8; 32]>,
121138
application_id: &ApplicationId,
@@ -185,24 +202,28 @@ impl Prepared<'_> {
185202
.flatten()
186203
.ok_or_eyre("failed to derive a context id after 5 tries")?;
187204

188-
let Some(application) = node_client.get_application(application_id)? else {
189-
bail!("application not found");
190-
};
205+
let application = match applications.entry(*application_id) {
206+
btree_map::Entry::Vacant(vacant) => {
207+
let application = node_client
208+
.get_application(application_id)?
209+
.ok_or_eyre("application not found")?;
191210

192-
if !node_client.has_blob(&application.blob)? {
193-
bail!("application points to dangling blob");
194-
}
211+
vacant.insert(application)
212+
}
213+
btree_map::Entry::Occupied(occupied) => occupied.into_mut(),
214+
};
195215

196216
let identity = identity_secret.public_key();
197217

198-
let meta = Context::new(context_id, application.id, Hash::default());
218+
let meta = Context::new(context_id, *application_id, Hash::default());
199219

200220
let context = entry.insert(ContextMeta {
201221
meta,
202-
blob: application.blob,
203222
lock: Arc::new(Mutex::new(context_id)),
204223
});
205224

225+
let application = application.clone();
226+
206227
Ok(Self {
207228
external_config,
208229
application,
@@ -219,7 +240,7 @@ async fn create_context(
219240
datastore: Store,
220241
node_client: NodeClient,
221242
context_client: ContextClient,
222-
engine: calimero_runtime::Engine,
243+
module: calimero_runtime::Module,
223244
external_config: ContextConfigParams<'_>,
224245
mut context: Context,
225246
context_secret: PrivateKey,
@@ -230,22 +251,12 @@ async fn create_context(
230251
init_params: Vec<u8>,
231252
guard: OwnedMutexGuard<ContextId>,
232253
) -> eyre::Result<Hash> {
233-
let Some(blob) = node_client.get_blob_bytes(&application.blob).await? else {
234-
bail!(
235-
"missing blob `{}` for application `{}`",
236-
application.blob,
237-
application.id
238-
);
239-
};
240-
241254
let storage = ContextStorage::from(datastore, context.id);
242255

243-
let module = engine.compile(&blob)?;
244-
245256
let (outcome, storage) = execute(
246257
&guard,
247-
identity,
248258
module,
259+
identity,
249260
"init".into(),
250261
init_params.into(),
251262
storage,

0 commit comments

Comments
 (0)