Enum holochain::core::ribosome::HostContext
source · pub enum HostContext {
EntryDefs(EntryDefsHostAccess),
GenesisSelfCheck(GenesisSelfCheckHostAccess),
Init(InitHostAccess),
MigrateAgent(MigrateAgentHostAccess),
PostCommit(PostCommitHostAccess),
Validate(ValidateHostAccess),
ValidationPackage(ValidationPackageHostAccess),
ZomeCall(ZomeCallHostAccess),
}
Variants§
EntryDefs(EntryDefsHostAccess)
GenesisSelfCheck(GenesisSelfCheckHostAccess)
Init(InitHostAccess)
MigrateAgent(MigrateAgentHostAccess)
PostCommit(PostCommitHostAccess)
Validate(ValidateHostAccess)
ValidationPackage(ValidationPackageHostAccess)
ZomeCall(ZomeCallHostAccess)
Implementations§
source§impl HostContext
impl HostContext
sourcepub fn workspace(&self) -> HostFnWorkspaceRead
pub fn workspace(&self) -> HostFnWorkspaceRead
Get the workspace, panics if none was provided
Examples found in repository?
src/core/ribosome/host_fn/emit_signal.rs (line 19)
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
pub fn emit_signal(
ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: AppSignal,
) -> Result<(), RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess{ non_determinism: Permission::Allow, .. } => {
let cell_id = CellId::new(
ribosome.dna_def().as_hash().clone(),
call_context.host_context.workspace().source_chain().as_ref().expect("Must have a source chain to emit signals").agent_pubkey().clone(),
);
let signal = Signal::App(cell_id, input);
call_context.host_context().signal_tx().send(signal).map_err(|interface_error| wasm_error!(WasmErrorInner::Host(interface_error.to_string())))?;
Ok(())
},
_ => Err(wasm_error!(WasmErrorInner::Host(RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"emit_signal".into()
).to_string())).into())
}
}
More examples
src/core/ribosome/host_fn/query.rs (line 21)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
pub fn query(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: ChainQueryFilter,
) -> Result<Vec<Record>, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace: Permission::Allow,
..
} => tokio_helper::block_forever_on(async move {
let records: Vec<Record> = call_context
.host_context
.workspace()
.source_chain()
.as_ref()
.expect("Must have source chain to query the source chain")
.query(input)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string())).into()
})?;
Ok(records)
}),
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"query".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/agent_info.rs (line 22)
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
pub fn agent_info<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
_input: (),
) -> Result<AgentInfo, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
agent_info: Permission::Allow,
..
} => {
let agent_pubkey = call_context
.host_context
.workspace()
.source_chain()
.as_ref()
.expect("Must have source chain if agent_info access is given")
.agent_pubkey()
.clone();
Ok(AgentInfo {
agent_initial_pubkey: agent_pubkey.clone(),
agent_latest_pubkey: agent_pubkey,
chain_head: call_context
.host_context
.workspace()
.source_chain()
.as_ref()
.expect("Must have source chain if agent_info access is given")
.chain_head()
.map_err(|e| wasm_error!(WasmErrorInner::Host(e.to_string())))?,
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"agent_info".into()
).to_string())).into())
}
}
src/core/ribosome/host_fn/delete.rs (line 71)
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
pub(crate) fn get_original_entry_data(
call_context: Arc<CallContext>,
address: ActionHash,
) -> Result<(EntryHash, EntryType), WasmError> {
let network = call_context.host_context.network().clone();
let workspace = call_context.host_context.workspace();
tokio_helper::block_forever_on(async move {
let mut cascade = Cascade::from_workspace_and_network(&workspace, network);
let maybe_original_record: Option<SignedActionHashed> = cascade
.get_details(address.clone().into(), GetOptions::content())
.await?
.map(|el| {
match el {
holochain_zome_types::metadata::Details::Record(e) => {
Ok(e.record.into_inner().0)
}
// Should not be trying to get original actions via EntryHash
holochain_zome_types::metadata::Details::Entry(_) => {
Err(CascadeError::InvalidResponse(address.clone().into()))
}
}
})
.transpose()?;
match maybe_original_record {
Some(SignedActionHashed {
hashed: ActionHashed {
content: action, ..
},
..
}) => match action.into_entry_data() {
Some((entry_hash, entry_type)) => Ok((entry_hash, entry_type)),
_ => Err(RibosomeError::RecordDeps(address.into())),
},
None => Err(RibosomeError::RecordDeps(address.into())),
}
})
.map_err(|ribosome_error| wasm_error!(WasmErrorInner::Host(ribosome_error.to_string())))
}
src/core/ribosome/host_fn/get_details.rs (line 30)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
pub fn get_details<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
inputs: Vec<GetInput>,
) -> Result<Vec<Option<Details>>, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace: Permission::Allow,
..
} => {
let results: Vec<Result<Option<Details>, _>> =
tokio_helper::block_forever_on(async move {
join_all(inputs.into_iter().map(|input| async {
let GetInput {
any_dht_hash,
get_options,
} = input;
Cascade::from_workspace_and_network(
&call_context.host_context.workspace(),
call_context.host_context.network().to_owned(),
)
.get_details(any_dht_hash, get_options)
.await
}))
.await
});
let results: Result<Vec<_>, _> = results
.into_iter()
.map(|result| {
result.map_err(|cascade_error| {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string()))
})
})
.collect();
Ok(results?)
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"get_details".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/get_agent_activity.rs (line 44)
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
pub fn get_agent_activity(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: GetAgentActivityInput,
) -> Result<AgentActivity, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace: Permission::Allow,
..
} => {
let GetAgentActivityInput {
agent_pubkey,
chain_query_filter,
activity_request,
} = input;
let options = match activity_request {
ActivityRequest::Status => GetActivityOptions {
include_valid_activity: false,
include_rejected_activity: false,
..Default::default()
},
ActivityRequest::Full => GetActivityOptions {
include_valid_activity: true,
include_rejected_activity: true,
..Default::default()
},
};
// Get the network from the context
let network = call_context.host_context.network().clone();
// timeouts must be handled by the network
tokio_helper::block_forever_on(async move {
let workspace = call_context.host_context.workspace();
let mut cascade = Cascade::from_workspace_and_network(&workspace, network);
let activity = cascade
.get_agent_activity(agent_pubkey, chain_query_filter, options)
.await
.map_err(|cascade_error| {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string()))
})?;
Ok(activity.into())
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"get_agent_activity".into()
)
.to_string()
))
.into()),
}
}
Additional examples can be found in:
- src/core/ribosome/host_fn/get_link_details.rs
- src/core/ribosome/host_fn/call_info.rs
- src/core/ribosome/host_fn/delete_link.rs
- src/core/ribosome/host_fn/must_get_agent_activity.rs
- src/core/ribosome/host_fn/must_get_entry.rs
- src/core/ribosome/host_fn/must_get_action.rs
- src/core/ribosome/host_fn/must_get_valid_record.rs
- src/core/ribosome/host_fn/call.rs
sourcepub fn workspace_write(&self) -> &HostFnWorkspace
pub fn workspace_write(&self) -> &HostFnWorkspace
Get the workspace, panics if none was provided
Examples found in repository?
src/core/ribosome/host_fn/schedule.rs (line 20)
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
pub fn schedule(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: String,
) -> Result<(), RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
call_context
.host_context()
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given")
.scratch()
.apply(|scratch| {
scratch.add_scheduled_fn(ScheduledFn::new(
call_context.zome.zome_name().clone(),
input.into(),
));
})
.map_err(|e| wasm_error!(WasmErrorInner::Host(e.to_string())))?;
Ok(())
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"schedule".into(),
)
.to_string(),
))
.into()),
}
}
More examples
src/core/ribosome/host_fn/delete.rs (line 37)
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
pub fn delete<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: DeleteInput,
) -> Result<ActionHash, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
let DeleteInput {
deletes_action_hash,
chain_top_ordering,
} = input;
let (deletes_entry_address, _) =
get_original_entry_data(call_context.clone(), deletes_action_hash.clone())?;
let host_access = call_context.host_context();
// handle timeouts at the source chain layer
tokio_helper::block_forever_on(async move {
let source_chain = host_access
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given");
let action_builder = builder::Delete {
deletes_address: deletes_action_hash,
deletes_entry_address,
};
let action_hash = source_chain
.put_weightless(action_builder, None, chain_top_ordering)
.await
.map_err(|source_chain_error| {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string()))
})?;
Ok(action_hash)
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"delete".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/create_link.rs (line 38)
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
pub fn create_link<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: CreateLinkInput,
) -> Result<ActionHash, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
let CreateLinkInput {
base_address,
target_address,
zome_index,
link_type,
tag,
chain_top_ordering,
} = input;
// Construct the link add
let action_builder =
builder::CreateLink::new(base_address, target_address, zome_index, link_type, tag);
let action_hash = tokio_helper::block_forever_on(tokio::task::spawn(async move {
// push the action into the source chain
let action_hash = call_context
.host_context
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given")
.put_weightless(action_builder, None, chain_top_ordering)
.await?;
Ok::<ActionHash, RibosomeError>(action_hash)
}))
.map_err(|join_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(join_error.to_string())).into()
})?
.map_err(|ribosome_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(ribosome_error.to_string())).into()
})?;
// return the hash of the committed link
// note that validation is handled by the workflow
// if the validation fails this commit will be rolled back by virtue of the DB transaction
// being atomic
Ok(action_hash)
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"create_link".into()
)
.to_string()
))
.into()),
}
}
src/core/ribosome/host_fn/update.rs (line 40)
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
pub fn update<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: UpdateInput,
) -> Result<ActionHash, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
// destructure the args out into an app type def id and entry
let UpdateInput {
original_action_address,
entry,
chain_top_ordering,
} = input;
let (original_entry_address, entry_type) =
get_original_entry_data(call_context.clone(), original_action_address.clone())?;
let weight = weigh_placeholder();
// Countersigned entries have different action handling.
match entry {
Entry::CounterSign(_, _) => tokio_helper::block_forever_on(async move {
call_context
.host_context
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given")
.put_countersigned(entry, chain_top_ordering, weight)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string())).into()
})
}),
_ => {
// build the entry hash
let entry_hash = EntryHash::with_data_sync(&entry);
// build an action for the entry being updated
let action_builder = builder::Update {
original_entry_address,
original_action_address,
entry_type,
entry_hash,
};
let workspace = call_context.host_context.workspace_write();
// return the hash of the updated entry
// note that validation is handled by the workflow
// if the validation fails this update will be rolled back by virtue of the DB transaction
// being atomic
tokio_helper::block_forever_on(async move {
let source_chain = workspace
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given");
// push the action and the entry into the source chain
let action_hash = source_chain
.put_weightless(action_builder, Some(entry), chain_top_ordering)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string()))
.into()
})?;
Ok(action_hash)
})
}
}
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"update".into()
)
.to_string()
))
.into()),
}
}
src/core/ribosome/host_fn/create.rs (line 37)
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
pub fn create<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: CreateInput,
) -> Result<ActionHash, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
let CreateInput {
entry_location,
entry_visibility,
entry,
chain_top_ordering,
} = input;
let weight = weigh_placeholder();
// Countersigned entries have different action handling.
match entry {
Entry::CounterSign(_, _) => tokio_helper::block_forever_on(async move {
call_context
.host_context
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given")
.put_countersigned(entry, chain_top_ordering, weight)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string())).into()
})
}),
_ => {
// build the entry hash
let entry_hash = EntryHash::with_data_sync(&entry);
// extract the entry defs for a zome
let entry_type = match entry_location {
EntryDefLocation::App(AppEntryDefLocation {
zome_index,
entry_def_index,
}) => {
let app_entry_def =
AppEntryDef::new(entry_def_index, zome_index, entry_visibility);
EntryType::App(app_entry_def)
}
EntryDefLocation::CapGrant => EntryType::CapGrant,
EntryDefLocation::CapClaim => EntryType::CapClaim,
};
// build an action for the entry being committed
let action_builder = builder::Create {
entry_type,
entry_hash,
};
// return the hash of the committed entry
// note that validation is handled by the workflow
// if the validation fails this commit will be rolled back by virtue of the DB transaction
// being atomic
tokio_helper::block_forever_on(async move {
// push the action and the entry into the source chain
call_context
.host_context
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given")
.put_weightless(action_builder, Some(entry), chain_top_ordering)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string()))
.into()
})
})
}
}
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"create".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/delete_link.rs (line 74)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
pub fn delete_link<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: DeleteLinkInput,
) -> Result<ActionHash, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
let DeleteLinkInput {
address,
chain_top_ordering,
} = input;
// get the base address from the add link action
// don't allow the wasm developer to get this wrong
// it is never valid to have divergent base address for add/remove links
// the subconscious will validate the base address match but we need to fetch it here to
// include it in the remove link action
let network = call_context.host_context.network().clone();
let call_context_2 = call_context.clone();
// handle timeouts at the network layer
let address_2 = address.clone();
let maybe_add_link: Option<SignedActionHashed> =
tokio_helper::block_forever_on(async move {
let workspace = call_context_2.host_context.workspace();
CascadeResult::Ok(
Cascade::from_workspace_and_network(&workspace, network)
.dht_get(address_2.into(), GetOptions::content())
.await?
.map(|el| el.into_inner().0),
)
})
.map_err(|cascade_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string())).into()
})?;
let base_address = match maybe_add_link {
Some(add_link_signed_action_hash) => {
match add_link_signed_action_hash.action() {
Action::CreateLink(link_add_action) => {
Ok(link_add_action.base_address.clone())
}
// the add link action hash provided was found but didn't point to an AddLink
// action (it is something else) so we cannot proceed
_ => Err(RibosomeError::RecordDeps(address.clone().into())),
}
}
// the add link action hash could not be found
// it's unlikely that a wasm call would have a valid add link action hash from "somewhere"
// that isn't also discoverable in either the cache or DHT, but it _is_ possible so we have
// to fail in that case (e.g. the local cache could have GC'd at the same moment the
// network connection dropped out)
None => Err(RibosomeError::RecordDeps(address.clone().into())),
}
.map_err(|ribosome_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(ribosome_error.to_string())).into()
})?;
let source_chain = call_context
.host_context
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given");
// handle timeouts at the source chain layer
// add a DeleteLink to the source chain
tokio_helper::block_forever_on(async move {
let action_builder = builder::DeleteLink {
link_add_address: address,
base_address,
};
let action_hash = source_chain
.put(action_builder, None, chain_top_ordering)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string())).into()
})?;
Ok(action_hash)
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"delete_link".into(),
)
.to_string(),
))
.into()),
}
}
Additional examples can be found in:
sourcepub fn keystore(&self) -> &MetaLairClient
pub fn keystore(&self) -> &MetaLairClient
Get the keystore, panics if none was provided
Examples found in repository?
src/core/ribosome/host_fn/create_x25519_keypair.rs (line 20)
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
pub fn create_x25519_keypair(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
_input: (),
) -> Result<X25519PubKey, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess{ keystore: Permission::Allow, .. } => tokio_helper::block_forever_on(async move {
call_context
.host_context
.keystore()
.new_x25519_keypair_random()
.await
.map(|k| (*k).into())
})
.map_err(|keystore_error| wasm_error!(WasmErrorInner::Host(keystore_error.to_string())).into()),
_ => Err(wasm_error!(WasmErrorInner::Host(RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"create_x25519_keypair".into()
).to_string())).into())
}
}
More examples
src/core/ribosome/host_fn/sign.rs (line 21)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
pub fn sign(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: Sign,
) -> Result<Signature, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
keystore: Permission::Allow,
..
} => tokio_helper::block_forever_on(async move {
call_context
.host_context
.keystore()
.sign(input.key, input.data.into_vec().into())
.await
})
.map_err(|keystore_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(keystore_error.to_string())).into()
}),
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"sign".into(),
)
.to_string(),
)).into()),
}
}
src/core/ribosome/host_fn/x_salsa20_poly1305_shared_secret_create_random.rs (line 30)
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
pub fn x_salsa20_poly1305_shared_secret_create_random(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: Option<XSalsa20Poly1305KeyRef>,
) -> Result<XSalsa20Poly1305KeyRef, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
keystore: Permission::Allow,
..
} => tokio_helper::block_forever_on(async move {
let key_ref = match input {
Some(key_ref) => key_ref,
None => rand_utf8::rand_utf8(
&mut rand::thread_rng(),
DEF_REF_SIZE,
).as_bytes().to_vec().into(),
};
let tag = key_ref.to_tag();
call_context
.host_context
.keystore()
.new_shared_secret(tag)
.await?;
holochain_keystore::LairResult::Ok(key_ref)
})
.map_err(|keystore_error| wasm_error!(WasmErrorInner::Host(keystore_error.to_string())).into()),
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"x_salsa20_poly1305_shared_secret_create_random".into(),
)
.to_string(),
)).into()),
}
}
src/core/ribosome/host_fn/x_salsa20_poly1305_encrypt.rs (line 26)
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
pub fn x_salsa20_poly1305_encrypt(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: XSalsa20Poly1305Encrypt,
) -> Result<XSalsa20Poly1305EncryptedData, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
keystore: Permission::Allow,
..
} => {
tokio_helper::block_forever_on(async move {
let key_ref = input.as_key_ref_ref().clone();
let tag = key_ref.to_tag();
let data = input.as_data_ref().as_ref().to_vec();
let (nonce, cipher) = call_context
.host_context
.keystore()
.shared_secret_encrypt(tag, data.into())
.await?;
holochain_keystore::LairResult::Ok(XSalsa20Poly1305EncryptedData::new(
nonce.into(),
cipher.to_vec(),
))
})
.map_err(|keystore_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(keystore_error.to_string())).into()
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"x_salsa20_poly1305_encrypt".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/x_salsa20_poly1305_shared_secret_export.rs (line 28)
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
pub fn x_salsa20_poly1305_shared_secret_export(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: XSalsa20Poly1305SharedSecretExport,
) -> Result<XSalsa20Poly1305EncryptedData, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
keystore: Permission::Allow,
..
} => {
tokio_helper::block_forever_on(async move {
let tag = input.as_key_ref_ref().to_tag();
let mut s_pk: [u8; 32] = [0; 32];
s_pk.copy_from_slice(input.as_sender_ref().as_ref());
let mut r_pk: [u8; 32] = [0; 32];
r_pk.copy_from_slice(input.as_recipient_ref().as_ref());
let (nonce, cipher) = call_context
.host_context
.keystore()
.shared_secret_export(tag, s_pk.into(), r_pk.into())
.await?;
holochain_keystore::LairResult::Ok(XSalsa20Poly1305EncryptedData::new(
nonce.into(),
cipher.to_vec(),
))
})
.map_err(|keystore_error| wasm_error!(WasmErrorInner::Host(keystore_error.to_string())).into())
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"x_salsa20_poly1305_shared_secret_export".into(),
)
.to_string(),
)).into()),
}
}
src/core/ribosome/host_fn/x_salsa20_poly1305_decrypt.rs (line 31)
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
pub fn x_salsa20_poly1305_decrypt(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: XSalsa20Poly1305Decrypt,
) -> Result<Option<XSalsa20Poly1305Data>, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess{
keystore_deterministic: Permission::Allow,
..
} => {
tokio_helper::block_forever_on(async move {
let key_ref = input.as_key_ref_ref().clone();
let tag = key_ref.to_tag();
let edata = input.as_encrypted_data_ref();
let mut nonce: [u8; 24] = [0; 24];
nonce.copy_from_slice(edata.as_nonce_ref().as_ref());
let data = edata.as_encrypted_data_ref().to_vec();
// for some reason, the hdk api expects us to translate
// errors into None here
let res = match call_context
.host_context
.keystore()
.shared_secret_decrypt(tag, nonce, data.into())
.await
{
Err(_) => None,
Ok(res) => Some(res.to_vec().into()),
};
holochain_keystore::LairResult::Ok(res)
})
.map_err(|keystore_error| -> RuntimeError { wasm_error!(WasmErrorInner::Host(keystore_error.to_string())).into() })
}
_ => Err(wasm_error!(WasmErrorInner::Host(RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"x_salsa20_poly1305_decrypt".into()
).to_string())).into())
}
}
Additional examples can be found in:
sourcepub fn network(&self) -> &HolochainP2pDna
pub fn network(&self) -> &HolochainP2pDna
Get the network, panics if none was provided
Examples found in repository?
src/core/ribosome/host_fn/delete.rs (line 70)
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
pub(crate) fn get_original_entry_data(
call_context: Arc<CallContext>,
address: ActionHash,
) -> Result<(EntryHash, EntryType), WasmError> {
let network = call_context.host_context.network().clone();
let workspace = call_context.host_context.workspace();
tokio_helper::block_forever_on(async move {
let mut cascade = Cascade::from_workspace_and_network(&workspace, network);
let maybe_original_record: Option<SignedActionHashed> = cascade
.get_details(address.clone().into(), GetOptions::content())
.await?
.map(|el| {
match el {
holochain_zome_types::metadata::Details::Record(e) => {
Ok(e.record.into_inner().0)
}
// Should not be trying to get original actions via EntryHash
holochain_zome_types::metadata::Details::Entry(_) => {
Err(CascadeError::InvalidResponse(address.clone().into()))
}
}
})
.transpose()?;
match maybe_original_record {
Some(SignedActionHashed {
hashed: ActionHashed {
content: action, ..
},
..
}) => match action.into_entry_data() {
Some((entry_hash, entry_type)) => Ok((entry_hash, entry_type)),
_ => Err(RibosomeError::RecordDeps(address.into())),
},
None => Err(RibosomeError::RecordDeps(address.into())),
}
})
.map_err(|ribosome_error| wasm_error!(WasmErrorInner::Host(ribosome_error.to_string())))
}
More examples
src/core/ribosome/host_fn/get_details.rs (line 31)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
pub fn get_details<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
inputs: Vec<GetInput>,
) -> Result<Vec<Option<Details>>, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace: Permission::Allow,
..
} => {
let results: Vec<Result<Option<Details>, _>> =
tokio_helper::block_forever_on(async move {
join_all(inputs.into_iter().map(|input| async {
let GetInput {
any_dht_hash,
get_options,
} = input;
Cascade::from_workspace_and_network(
&call_context.host_context.workspace(),
call_context.host_context.network().to_owned(),
)
.get_details(any_dht_hash, get_options)
.await
}))
.await
});
let results: Result<Vec<_>, _> = results
.into_iter()
.map(|result| {
result.map_err(|cascade_error| {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string()))
})
})
.collect();
Ok(results?)
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"get_details".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/get_agent_activity.rs (line 40)
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
pub fn get_agent_activity(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: GetAgentActivityInput,
) -> Result<AgentActivity, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace: Permission::Allow,
..
} => {
let GetAgentActivityInput {
agent_pubkey,
chain_query_filter,
activity_request,
} = input;
let options = match activity_request {
ActivityRequest::Status => GetActivityOptions {
include_valid_activity: false,
include_rejected_activity: false,
..Default::default()
},
ActivityRequest::Full => GetActivityOptions {
include_valid_activity: true,
include_rejected_activity: true,
..Default::default()
},
};
// Get the network from the context
let network = call_context.host_context.network().clone();
// timeouts must be handled by the network
tokio_helper::block_forever_on(async move {
let workspace = call_context.host_context.workspace();
let mut cascade = Cascade::from_workspace_and_network(&workspace, network);
let activity = cascade
.get_agent_activity(agent_pubkey, chain_query_filter, options)
.await
.map_err(|cascade_error| {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string()))
})?;
Ok(activity.into())
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"get_agent_activity".into()
)
.to_string()
))
.into()),
}
}
src/core/ribosome/host_fn/get_link_details.rs (line 39)
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
pub fn get_link_details<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
inputs: Vec<GetLinksInput>,
) -> Result<Vec<LinkDetails>, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace: Permission::Allow,
..
} => {
let results: Vec<Result<Vec<_>, RibosomeError>> =
tokio_helper::block_forever_on(async move {
join_all(inputs.into_iter().map(|input| async {
let GetLinksInput {
base_address,
link_type,
tag_prefix,
} = input;
let key = WireLinkKey {
base: base_address,
type_query: link_type,
tag: tag_prefix,
};
Ok(Cascade::from_workspace_and_network(
&call_context.host_context.workspace(),
call_context.host_context.network().to_owned(),
)
.get_link_details(key, GetLinksOptions::default())
.await?)
}))
.await
});
let results: Result<Vec<_>, RuntimeError> = results
.into_iter()
.map(|result| match result {
Ok(v) => Ok(v.into()),
Err(cascade_error) => {
Err(wasm_error!(WasmErrorInner::Host(cascade_error.to_string())).into())
}
})
.collect();
Ok(results?)
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"get_link_details".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/delete_link.rs (line 31)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
pub fn delete_link<'a>(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: DeleteLinkInput,
) -> Result<ActionHash, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
write_workspace: Permission::Allow,
..
} => {
let DeleteLinkInput {
address,
chain_top_ordering,
} = input;
// get the base address from the add link action
// don't allow the wasm developer to get this wrong
// it is never valid to have divergent base address for add/remove links
// the subconscious will validate the base address match but we need to fetch it here to
// include it in the remove link action
let network = call_context.host_context.network().clone();
let call_context_2 = call_context.clone();
// handle timeouts at the network layer
let address_2 = address.clone();
let maybe_add_link: Option<SignedActionHashed> =
tokio_helper::block_forever_on(async move {
let workspace = call_context_2.host_context.workspace();
CascadeResult::Ok(
Cascade::from_workspace_and_network(&workspace, network)
.dht_get(address_2.into(), GetOptions::content())
.await?
.map(|el| el.into_inner().0),
)
})
.map_err(|cascade_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string())).into()
})?;
let base_address = match maybe_add_link {
Some(add_link_signed_action_hash) => {
match add_link_signed_action_hash.action() {
Action::CreateLink(link_add_action) => {
Ok(link_add_action.base_address.clone())
}
// the add link action hash provided was found but didn't point to an AddLink
// action (it is something else) so we cannot proceed
_ => Err(RibosomeError::RecordDeps(address.clone().into())),
}
}
// the add link action hash could not be found
// it's unlikely that a wasm call would have a valid add link action hash from "somewhere"
// that isn't also discoverable in either the cache or DHT, but it _is_ possible so we have
// to fail in that case (e.g. the local cache could have GC'd at the same moment the
// network connection dropped out)
None => Err(RibosomeError::RecordDeps(address.clone().into())),
}
.map_err(|ribosome_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(ribosome_error.to_string())).into()
})?;
let source_chain = call_context
.host_context
.workspace_write()
.source_chain()
.as_ref()
.expect("Must have source chain if write_workspace access is given");
// handle timeouts at the source chain layer
// add a DeleteLink to the source chain
tokio_helper::block_forever_on(async move {
let action_builder = builder::DeleteLink {
link_add_address: address,
base_address,
};
let action_hash = source_chain
.put(action_builder, None, chain_top_ordering)
.await
.map_err(|source_chain_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(source_chain_error.to_string())).into()
})?;
Ok(action_hash)
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"delete_link".into(),
)
.to_string(),
))
.into()),
}
}
src/core/ribosome/host_fn/must_get_agent_activity.rs (line 35)
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
pub fn must_get_agent_activity(
_ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: MustGetAgentActivityInput,
) -> Result<Vec<RegisterAgentActivity>, RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess {
read_workspace_deterministic: Permission::Allow,
..
} => {
let MustGetAgentActivityInput {
author,
chain_filter,
} = input;
// timeouts must be handled by the network
tokio_helper::block_forever_on(async move {
let workspace = call_context.host_context.workspace();
let mut cascade = match call_context.host_context {
HostContext::Validate(_) => {
Cascade::from_workspace_stores(workspace.stores(), None)
}
_ => Cascade::from_workspace_and_network(
&workspace,
call_context.host_context.network().clone(),
),
};
let result = cascade
.must_get_agent_activity(author.clone(), chain_filter.clone())
.await
.map_err(|cascade_error| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(cascade_error.to_string())).into()
})?;
use MustGetAgentActivityResponse::*;
let result: Result<_, RuntimeError> = match (result, &call_context.host_context) {
(Activity(activity), _) => Ok(activity),
(IncompleteChain | ChainTopNotFound(_), HostContext::Init(_)) => {
Err(wasm_error!(WasmErrorInner::HostShortCircuit(
holochain_serialized_bytes::encode(
&ExternIO::encode(InitCallbackResult::UnresolvedDependencies(
UnresolvedDependencies::AgentActivity(author, chain_filter)
))
.map_err(|e| -> RuntimeError { wasm_error!(e).into() })?,
)
.map_err(|e| -> RuntimeError { wasm_error!(e).into() })?
))
.into())
}
(IncompleteChain | ChainTopNotFound(_), HostContext::Validate(_)) => {
Err(wasm_error!(WasmErrorInner::HostShortCircuit(
holochain_serialized_bytes::encode(
&ExternIO::encode(ValidateCallbackResult::UnresolvedDependencies(
UnresolvedDependencies::AgentActivity(author, chain_filter)
))
.map_err(|e| -> RuntimeError { wasm_error!(e).into() })?,
)
.map_err(|e| -> RuntimeError { wasm_error!(e).into() })?
))
.into())
}
(IncompleteChain, _) => Err(wasm_error!(WasmErrorInner::Host(format!(
"must_get_agent_activity chain is incomplete for author {} and filter {:?}",
author, chain_filter
)))
.into()),
(ChainTopNotFound(missing_action), _) => Err(wasm_error!(WasmErrorInner::Host(format!(
"must_get_agent_activity is missing action {} for author {} and filter {:?}",
missing_action, author, chain_filter
)))
.into()),
(EmptyRange, _) => Err(wasm_error!(WasmErrorInner::Host(format!(
"must_get_agent_activity chain has produced an invalid range because the range is empty for author {} and filter {:?}",
author, chain_filter
)))
.into()),
};
result
})
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"must_get_agent_activity".into(),
)
.to_string(),
))
.into()),
}
}
sourcepub fn signal_tx(&mut self) -> &mut SignalBroadcaster
pub fn signal_tx(&mut self) -> &mut SignalBroadcaster
Get the signal broadcaster, panics if none was provided
Examples found in repository?
src/core/ribosome/host_fn/emit_signal.rs (line 22)
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
pub fn emit_signal(
ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: AppSignal,
) -> Result<(), RuntimeError> {
match HostFnAccess::from(&call_context.host_context()) {
HostFnAccess{ non_determinism: Permission::Allow, .. } => {
let cell_id = CellId::new(
ribosome.dna_def().as_hash().clone(),
call_context.host_context.workspace().source_chain().as_ref().expect("Must have a source chain to emit signals").agent_pubkey().clone(),
);
let signal = Signal::App(cell_id, input);
call_context.host_context().signal_tx().send(signal).map_err(|interface_error| wasm_error!(WasmErrorInner::Host(interface_error.to_string())))?;
Ok(())
},
_ => Err(wasm_error!(WasmErrorInner::Host(RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"emit_signal".into()
).to_string())).into())
}
}
sourcepub fn call_zome_handle(&self) -> &CellConductorReadHandle
pub fn call_zome_handle(&self) -> &CellConductorReadHandle
Get the call zome handle, panics if none was provided
Examples found in repository?
src/core/ribosome/host_fn/call.rs (line 111)
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
pub fn call(
ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
inputs: Vec<Call>,
) -> Result<Vec<ZomeCallResponse>, RuntimeError> {
let results: Vec<Result<ZomeCallResponse, RuntimeError>> =
tokio_helper::block_forever_on(async move {
join_all(inputs.into_iter().map(|input| async {
// The line below was added when migrating to rust edition 2021, per
// https://doc.rust-lang.org/edition-guide/rust-2021/disjoint-capture-in-closures.html#migration
let _ = &input;
let Call {
target,
zome_name,
fn_name,
cap_secret,
payload,
} = input;
match (&target, HostFnAccess::from(&call_context.host_context())) {
(
CallTarget::ConductorCell(_),
HostFnAccess {
write_workspace: Permission::Allow,
agent_info: Permission::Allow,
..
},
)
| (
CallTarget::NetworkAgent(_),
HostFnAccess {
write_network: Permission::Allow,
agent_info: Permission::Allow,
..
},
) => {
let provenance = call_context
.host_context
.workspace()
.source_chain()
.as_ref()
.expect("Must have source chain to know provenance")
.agent_pubkey()
.clone();
let (nonce, expires_at) = fresh_nonce(Timestamp::now()).map_err(|e| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(e.to_string())).into()
})?;
let result: Result<ZomeCallResponse, RuntimeError> = match target {
CallTarget::NetworkAgent(target_agent) => {
let zome_call_unsigned = ZomeCallUnsigned {
provenance: provenance.clone(),
cell_id: CellId::new(
ribosome.dna_def().as_hash().clone(),
target_agent.clone(),
),
zome_name,
fn_name,
cap_secret,
payload,
nonce,
expires_at,
};
match call_context
.host_context()
.network()
.call_remote(
provenance.clone(),
zome_call_unsigned.provenance
.sign_raw(call_context.host_context.keystore(), zome_call_unsigned.data_to_sign().map_err(|e| -> RuntimeError { wasm_error!(e.to_string()).into() })?)
.await
.map_err(|e| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(e.to_string()))
.into()
})?,
target_agent,
zome_call_unsigned.zome_name,
zome_call_unsigned.fn_name,
zome_call_unsigned.cap_secret,
zome_call_unsigned.payload,
zome_call_unsigned.nonce,
zome_call_unsigned.expires_at,
)
.await
{
Ok(serialized_bytes) => ZomeCallResponse::try_from(
serialized_bytes,
)
.map_err(|e| -> RuntimeError { wasm_error!(e).into() }),
Err(e) => Ok(ZomeCallResponse::NetworkError(e.to_string())),
}
}
CallTarget::ConductorCell(target_cell) => {
let cell_id_result: Result<CellId, RuntimeError> = match target_cell
{
CallTargetCell::OtherRole(role_name) => {
let this_cell_id = call_context
.host_context()
.call_zome_handle()
.cell_id()
.clone();
call_context
.host_context()
.call_zome_handle()
.find_cell_with_role_alongside_cell(
&this_cell_id,
&role_name,
)
.await
.map_err(|e| -> RuntimeError {
wasm_error!(e).into()
})
.and_then(|c| {
c.ok_or_else(|| {
RuntimeError::from(wasm_error!(
WasmErrorInner::Host(
"Role not found.".to_string()
)
))
})
})
}
CallTargetCell::OtherCell(cell_id) => Ok(cell_id),
CallTargetCell::Local => Ok(call_context
.host_context()
.call_zome_handle()
.cell_id()
.clone()),
};
match cell_id_result {
Ok(cell_id) => {
let zome_call_unsigned = ZomeCallUnsigned {
cell_id,
zome_name,
fn_name,
payload,
cap_secret,
provenance,
nonce,
expires_at,
};
let call = ZomeCall::try_from_unsigned_zome_call(
call_context.host_context.keystore(),
zome_call_unsigned,
)
.await
.map_err(|e| -> RuntimeError {
wasm_error!(WasmErrorInner::Host(e.to_string())).into()
})?;
match call_context
.host_context()
.call_zome_handle()
.call_zome(
call,
call_context
.host_context()
.workspace_write()
.clone()
.try_into()
.expect(
"Must have source chain to make zome call",
),
)
.await
{
Ok(Ok(zome_call_response)) => Ok(zome_call_response),
Ok(Err(ribosome_error)) => Err(wasm_error!(
WasmErrorInner::Host(ribosome_error.to_string())
)
.into()),
Err(conductor_api_error) => {
Err(wasm_error!(WasmErrorInner::Host(
conductor_api_error.to_string()
))
.into())
}
}
}
Err(e) => Err(e),
}
}
};
result
}
_ => Err(wasm_error!(WasmErrorInner::Host(
RibosomeError::HostFnPermissions(
call_context.zome.zome_name().clone(),
call_context.function_name().clone(),
"call".into(),
)
.to_string(),
))
.into()),
}
}))
.await
});
let results: Result<Vec<_>, _> = results.into_iter().collect();
results
}
Trait Implementations§
source§impl Clone for HostContext
impl Clone for HostContext
source§fn clone(&self) -> HostContext
fn clone(&self) -> HostContext
Returns a copy of the value. Read more
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source
. Read moresource§impl Debug for HostContext
impl Debug for HostContext
source§impl From<&HostContext> for EntryDefsHostAccess
impl From<&HostContext> for EntryDefsHostAccess
source§fn from(_: &HostContext) -> Self
fn from(_: &HostContext) -> Self
Converts to this type from the input type.
source§impl From<&HostContext> for HostFnAccess
impl From<&HostContext> for HostFnAccess
source§fn from(host_access: &HostContext) -> Self
fn from(host_access: &HostContext) -> Self
Converts to this type from the input type.
source§impl From<EntryDefsHostAccess> for HostContext
impl From<EntryDefsHostAccess> for HostContext
source§fn from(entry_defs_host_access: EntryDefsHostAccess) -> Self
fn from(entry_defs_host_access: EntryDefsHostAccess) -> Self
Converts to this type from the input type.
source§impl From<GenesisSelfCheckHostAccess> for HostContext
impl From<GenesisSelfCheckHostAccess> for HostContext
source§fn from(host_access: GenesisSelfCheckHostAccess) -> Self
fn from(host_access: GenesisSelfCheckHostAccess) -> Self
Converts to this type from the input type.
source§impl From<InitHostAccess> for HostContext
impl From<InitHostAccess> for HostContext
source§fn from(init_host_access: InitHostAccess) -> Self
fn from(init_host_access: InitHostAccess) -> Self
Converts to this type from the input type.
source§impl From<MigrateAgentHostAccess> for HostContext
impl From<MigrateAgentHostAccess> for HostContext
source§fn from(migrate_agent_host_access: MigrateAgentHostAccess) -> Self
fn from(migrate_agent_host_access: MigrateAgentHostAccess) -> Self
Converts to this type from the input type.
source§impl From<PostCommitHostAccess> for HostContext
impl From<PostCommitHostAccess> for HostContext
source§fn from(post_commit_host_access: PostCommitHostAccess) -> Self
fn from(post_commit_host_access: PostCommitHostAccess) -> Self
Converts to this type from the input type.
source§impl From<ValidateHostAccess> for HostContext
impl From<ValidateHostAccess> for HostContext
source§fn from(validate_host_access: ValidateHostAccess) -> Self
fn from(validate_host_access: ValidateHostAccess) -> Self
Converts to this type from the input type.
source§impl From<ValidationPackageHostAccess> for HostContext
impl From<ValidationPackageHostAccess> for HostContext
source§fn from(validation_package_host_access: ValidationPackageHostAccess) -> Self
fn from(validation_package_host_access: ValidationPackageHostAccess) -> Self
Converts to this type from the input type.
source§impl From<ZomeCallHostAccess> for HostContext
impl From<ZomeCallHostAccess> for HostContext
source§fn from(zome_call_host_access: ZomeCallHostAccess) -> Self
fn from(zome_call_host_access: ZomeCallHostAccess) -> Self
Converts to this type from the input type.
Auto Trait Implementations§
impl !RefUnwindSafe for HostContext
impl Send for HostContext
impl Sync for HostContext
impl Unpin for HostContext
impl !UnwindSafe for HostContext
Blanket Implementations§
§impl<T> Any for Twhere
T: Any + ?Sized,
impl<T> Any for Twhere
T: Any + ?Sized,
§fn type_id_compat(&self) -> TypeId
fn type_id_compat(&self) -> TypeId
TODO: once 1.33.0 is the minimum supported compiler version, remove
Any::type_id_compat and use StdAny::type_id instead.
https://github.com/rust-lang/rust/issues/27745
§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
§type ArchivedMetadata = ()
type ArchivedMetadata = ()
The archived version of the pointer metadata for this type.
§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata
) -> <T as Pointee>::Metadata
fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata
) -> <T as Pointee>::Metadata
Converts some archived metadata to the pointer metadata for itself.
§impl<F, W, T, D> Deserialize<With<T, W>, D> for Fwhere
W: DeserializeWith<F, T, D>,
D: Fallible + ?Sized,
F: ?Sized,
impl<F, W, T, D> Deserialize<With<T, W>, D> for Fwhere
W: DeserializeWith<F, T, D>,
D: Fallible + ?Sized,
F: ?Sized,
§fn deserialize(
&self,
deserializer: &mut D
) -> Result<With<T, W>, <D as Fallible>::Error>
fn deserialize(
&self,
deserializer: &mut D
) -> Result<With<T, W>, <D as Fallible>::Error>
Deserializes using the given deserializer
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
§impl<T> Pointable for T
impl<T> Pointable for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self
from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
Checks if
self
is actually part of its subset T
(and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
Use with care! Same as
self.to_subset
but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self
to the equivalent element of its superset.§impl<T> Upcastable for Twhere
T: 'static + Any + Send + Sync,
impl<T> Upcastable for Twhere
T: 'static + Any + Send + Sync,
§fn upcast_any_ref(&self) -> &(dyn Any + 'static)
fn upcast_any_ref(&self) -> &(dyn Any + 'static)
upcast ref
§fn upcast_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn upcast_any_mut(&mut self) -> &mut (dyn Any + 'static)
upcast mut ref