Skip to content

Commit

Permalink
working call
Browse files Browse the repository at this point in the history
  • Loading branch information
freesig committed Oct 30, 2020
1 parent b0074f6 commit d0c2ef4
Show file tree
Hide file tree
Showing 15 changed files with 331 additions and 18 deletions.
27 changes: 26 additions & 1 deletion crates/hdk/src/host_fn/call.rs
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
//! @todo
use crate::prelude::*;
use holo_hash::AgentPubKey;
use holochain_wasmer_guest::SerializedBytesError;
use holochain_zome_types::{
call::Call,
zome::{FunctionName, ZomeName},
};

use crate::host_fn;

pub fn call(
to_agent: AgentPubKey,
zome_name: ZomeName,
fn_name: FunctionName,
cap_secret: Option<CapSecret>,
request: SerializedBytes,
) -> Result<ZomeCallResponse, SerializedBytesError> {
let provenance = agent_info!()?.agent_latest_pubkey;
host_fn!(
__call,
CallInput::new(Call::new(
to_agent, zome_name, fn_name, cap_secret, request, provenance
)),
CallOutput
)
}
1 change: 1 addition & 0 deletions crates/hdk/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub use crate::hash_path::anchor::list_anchor_tags;
pub use crate::hash_path::anchor::list_anchor_type_addresses;
pub use crate::hash_path::anchor::Anchor;
pub use crate::hash_path::path::Path;
pub use crate::host_fn::call::call;
pub use crate::map_extern;
pub use crate::map_extern::ExternResult;
pub use crate::query;
Expand Down
34 changes: 34 additions & 0 deletions crates/holochain/src/conductor/api/api_cell.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! The CellConductorApi allows Cells to talk to their Conductor

use std::sync::Arc;

use super::error::{ConductorApiError, ConductorApiResult};
use crate::conductor::{
entry_def_store::EntryDefBufferKey, interface::SignalBroadcaster, ConductorHandle,
Expand All @@ -21,6 +23,10 @@ pub struct CellConductorApi {
cell_id: CellId,
}

/// A handle that cn only call zome functions to avoid
/// making write lock calls
pub type CallZomeHandle = Arc<dyn CallZomeHandleT>;

impl CellConductorApi {
/// Instantiate from a Conductor reference and a CellId to identify which Cell
/// this API instance is associated with
Expand Down Expand Up @@ -86,6 +92,10 @@ impl CellConductorApiT for CellConductorApi {
async fn get_entry_def(&self, key: &EntryDefBufferKey) -> Option<EntryDef> {
self.conductor_handle.get_entry_def(key).await
}

fn into_call_zome_handle(self) -> CallZomeHandle {
Arc::new(self)
}
}

/// The "internal" Conductor API interface, for a Cell to talk to its calling Conductor.
Expand Down Expand Up @@ -125,4 +135,28 @@ pub trait CellConductorApiT: Clone + Send + Sync + Sized {

/// Get a [EntryDef] from the [EntryDefBuf]
async fn get_entry_def(&self, key: &EntryDefBufferKey) -> Option<EntryDef>;

/// Turn this into a call zome handle
fn into_call_zome_handle(self) -> CallZomeHandle;
}

#[async_trait]
/// A handle that cn only call zome functions to avoid
/// making write lock calls
pub trait CallZomeHandleT: Send + Sync {
/// Invoke a zome function on a Cell
async fn call_zome(
&self,
invocation: ZomeCallInvocation,
) -> ConductorApiResult<ZomeCallInvocationResult>;
}

#[async_trait]
impl CallZomeHandleT for CellConductorApi {
async fn call_zome(
&self,
invocation: ZomeCallInvocation,
) -> ConductorApiResult<ZomeCallInvocationResult> {
self.conductor_handle.call_zome(invocation).await
}
}
4 changes: 4 additions & 0 deletions crates/holochain/src/conductor/api/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ mock! {
fn sync_get_dna(&self, dna_hash: &DnaHash) -> Option<DnaFile>;
fn sync_get_this_dna(&self) -> Option<DnaFile>;
fn sync_get_entry_def(&self, key: &EntryDefBufferKey) -> Option<EntryDef>;
fn into_call_zome_handle(self) -> super::CallZomeHandle;
}

trait Clone {
Expand Down Expand Up @@ -86,4 +87,7 @@ impl CellConductorApiT for MockCellConductorApi {
async fn get_entry_def(&self, key: &EntryDefBufferKey) -> Option<EntryDef> {
self.sync_get_entry_def(key)
}
fn into_call_zome_handle(self) -> super::CallZomeHandle {
self.into_call_zome_handle()
}
}
15 changes: 14 additions & 1 deletion crates/holochain/src/core/ribosome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ pub mod guest_callback;
pub mod host_fn;
pub mod wasm_ribosome;

use crate::core::ribosome::guest_callback::entry_defs::EntryDefsInvocation;
use crate::core::ribosome::guest_callback::entry_defs::EntryDefsResult;
use crate::core::ribosome::guest_callback::init::InitInvocation;
use crate::core::ribosome::guest_callback::init::InitResult;
Expand All @@ -32,6 +31,9 @@ use crate::core::workflow::CallZomeWorkspaceLock;
use crate::fixt::ExternInputFixturator;
use crate::fixt::FunctionNameFixturator;
use crate::fixt::ZomeNameFixturator;
use crate::{
conductor::api::CallZomeHandle, core::ribosome::guest_callback::entry_defs::EntryDefsInvocation,
};
use crate::{conductor::interface::SignalBroadcaster, core::ribosome::error::RibosomeError};
use ::fixt::prelude::*;
use derive_more::Constructor;
Expand Down Expand Up @@ -175,6 +177,16 @@ impl HostAccess {
_ => panic!("Gave access to a host function that references a CellId"),
}
}

/// Get the call zome handle, panics if none was provided
pub fn call_zome_handle(&self) -> &CallZomeHandle {
match self {
Self::ZomeCall(ZomeCallHostAccess{call_zome_handle, .. }) => {
call_zome_handle
}
_ => panic!("Gave access to a host function that uses the call zome handle without providing a call zome handle"),
}
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -390,6 +402,7 @@ pub struct ZomeCallHostAccess {
pub keystore: KeystoreSender,
pub network: HolochainP2pCell,
pub signal_tx: SignalBroadcaster,
pub call_zome_handle: CallZomeHandle,
// NB: this is kind of an odd place for this, since CellId is not really a special
// "resource" to give access to, but rather it's a bit of data that makes sense in
// the context of zome calls, but not every CallContext
Expand Down
6 changes: 5 additions & 1 deletion crates/holochain/src/core/ribosome/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! Errors occurring during a [Ribosome] call

use crate::{
conductor::interface::error::InterfaceError,
conductor::{api::error::ConductorApiError, interface::error::InterfaceError},
core::state::{cascade::error::CascadeError, source_chain::SourceChainError},
};
use holo_hash::AnyDhtHash;
Expand Down Expand Up @@ -65,6 +65,10 @@ pub enum RibosomeError {
#[error(transparent)]
CascadeError(#[from] CascadeError),

/// ident
#[error(transparent)]
ConductorApiError(#[from] Box<ConductorApiError>),

/// ident
#[error(transparent)]
SourceChainError(#[from] SourceChainError),
Expand Down
114 changes: 107 additions & 7 deletions crates/holochain/src/core/ribosome/host_fn/call.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,114 @@
use crate::core::ribosome::error::RibosomeResult;
use crate::core::ribosome::CallContext;
use crate::core::ribosome::RibosomeT;
use holochain_zome_types::CallInput;
use holochain_zome_types::CallOutput;
use crate::core::ribosome::{error::RibosomeResult, ZomeCallInvocation};
use holochain_types::cell::CellId;
use holochain_zome_types::{CallInput, ZomeCallResponse};
use holochain_zome_types::{CallOutput, ExternInput};
use std::sync::Arc;

pub fn call(
_ribosome: Arc<impl RibosomeT>,
_call_context: Arc<CallContext>,
_input: CallInput,
ribosome: Arc<impl RibosomeT>,
call_context: Arc<CallContext>,
input: CallInput,
) -> RibosomeResult<CallOutput> {
unimplemented!();
let call = input.into_inner();
let dna_hash = ribosome.dna_file().dna_hash().clone();
let to_agent = call.to_agent();
let cell_id = CellId::new(dna_hash, to_agent);
let invocation = ZomeCallInvocation {
cell_id,
zome_name: call.zome_name(),
cap: call.cap(),
fn_name: call.fn_name(),
payload: ExternInput::new(call.request()),
provenance: call.provenance(),
};
let host_access = call_context.host_access();
let call_zome_handle = host_access.call_zome_handle();
let result: ZomeCallResponse = tokio_safe_block_on::tokio_safe_block_forever_on(async move {
call_zome_handle
.call_zome(invocation)
.await
.map_err(Box::new)
})??;

Ok(CallOutput::new(result))
}

#[cfg(test)]
pub mod wasm_test {
use std::convert::TryInto;

use hdk3::prelude::AgentInfo;
use holochain_serialized_bytes::SerializedBytes;
use holochain_wasm_test_utils::TestWasm;
use holochain_zome_types::{ExternInput, ZomeCallResponse};

use crate::{
core::ribosome::ZomeCallInvocation, test_utils::conductor_setup::ConductorTestData,
};

#[tokio::test(threaded_scheduler)]
async fn call_test() {
observability::test_run().ok();

let zomes = vec![TestWasm::WhoAmI];
let conductor_test = ConductorTestData::new(zomes, true).await;
let ConductorTestData {
__tmpdir,
handle,
alice_call_data,
bob_call_data,
..
} = conductor_test;
let bob_call_data = bob_call_data.unwrap();
let alice_cell_id = &alice_call_data.cell_id;
let bob_cell_id = &bob_call_data.cell_id;
let alice_agent_id = alice_cell_id.agent_pubkey();
let bob_agent_id = bob_cell_id.agent_pubkey();

// BOB INIT (to do cap grant)

let _ = handle
.call_zome(ZomeCallInvocation {
cell_id: bob_cell_id.clone(),
zome_name: TestWasm::WhoAmI.into(),
cap: None,
fn_name: "set_access".into(),
payload: ExternInput::new(().try_into().unwrap()),
provenance: bob_agent_id.clone(),
})
.await
.unwrap();

// ALICE DOING A CALL

let output = handle
.call_zome(ZomeCallInvocation {
cell_id: alice_cell_id.clone(),
zome_name: TestWasm::WhoAmI.into(),
cap: None,
fn_name: "who_are_they_local".into(),
payload: ExternInput::new(bob_agent_id.clone().try_into().unwrap()),
provenance: alice_agent_id.clone(),
})
.await
.unwrap()
.unwrap();

match output {
ZomeCallResponse::Ok(guest_output) => {
let response: SerializedBytes = guest_output.into_inner();
let agent_info: AgentInfo = response.try_into().unwrap();
assert_eq!(
agent_info,
AgentInfo {
agent_initial_pubkey: bob_agent_id.clone(),
agent_latest_pubkey: bob_agent_id.clone(),
},
);
}
_ => unreachable!(),
}
}
}
3 changes: 3 additions & 0 deletions crates/holochain/src/core/workflow/call_zome_workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ async fn call_zome_workflow_inner<'env, Ribosome: RibosomeT, C: CellConductorApi
conductor_api,
} = args;

let call_zome_handle = conductor_api.clone().into_call_zome_handle();

let zome_name = invocation.zome_name.clone();

// Get the current head
Expand All @@ -100,6 +102,7 @@ async fn call_zome_workflow_inner<'env, Ribosome: RibosomeT, C: CellConductorApi
keystore,
network.clone(),
signal_tx,
call_zome_handle,
invocation.cell_id.clone(),
);
ribosome.call_zome_function(host_access, invocation)
Expand Down
21 changes: 18 additions & 3 deletions crates/holochain/src/fixt.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
pub mod curve;

use crate::conductor::interface::SignalBroadcaster;
use crate::conductor::handle::MockConductorHandleT;
use crate::conductor::{
api::{CallZomeHandle, CellConductorApi},
interface::SignalBroadcaster,
};
use crate::core::ribosome::guest_callback::entry_defs::EntryDefsInvocation;
use crate::core::ribosome::guest_callback::init::InitHostAccess;
use crate::core::ribosome::guest_callback::init::InitInvocation;
Expand Down Expand Up @@ -35,13 +39,13 @@ use holo_hash::WasmHash;
use holochain_keystore::keystore_actor::KeystoreSender;
use holochain_p2p::HolochainP2pCellFixturator;
use holochain_state::test_utils::test_keystore;
use holochain_types::dna::wasm::DnaWasm;
use holochain_types::dna::zome::Zome;
use holochain_types::dna::DnaFile;
use holochain_types::dna::Wasms;
use holochain_types::dna::Zomes;
pub use holochain_types::fixt::*;
use holochain_types::test_utils::fake_dna_zomes;
use holochain_types::{cell::CellId, dna::wasm::DnaWasm};
use holochain_wasm_test_utils::strum::IntoEnumIterator;
use holochain_wasm_test_utils::TestWasm;
use holochain_zome_types::element::Element;
Expand Down Expand Up @@ -298,9 +302,20 @@ fixturator!(
};
);

fn make_call_zome_handle(cell_id: CellId) -> CallZomeHandle {
let handle = Arc::new(MockConductorHandleT::new());
let cell_conductor_api = CellConductorApi::new(handle, cell_id);
Arc::new(cell_conductor_api)
}

fixturator!(
CallZomeHandle;
vanilla fn make_call_zome_handle(CellId);
);

fixturator!(
ZomeCallHostAccess;
constructor fn new(CallZomeWorkspaceLock, KeystoreSender, HolochainP2pCell, SignalBroadcaster, CellId);
constructor fn new(CallZomeWorkspaceLock, KeystoreSender, HolochainP2pCell, SignalBroadcaster, CallZomeHandle, CellId);
);

fixturator!(
Expand Down

1 comment on commit d0c2ef4

@thedavidmeister
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarking wasm_call_n/1

Please sign in to comment.