Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bincode = "1"
byteorder = "1"
blake3 = { version = "1", features = ["std", "traits-preview"] }
bs58 = "0.5"
chrono = { version = "0.4", default-features = false }
chrono = { version = "0.4", default-features = false, features = ["serde"] }
flatbuffers = "24.3"
futures = { version = "0.3", default-features = false }
semver = { version = "1", default-features = false }
Expand Down
17 changes: 17 additions & 0 deletions rust/src/client_api/client_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1452,6 +1452,23 @@ impl HostResponse {
"GetContractRequest reached client serialization - this is a bug"
);
}
OutboundDelegateMsg::PutContractRequest(_) => {
// PutContractRequest should be handled by the executor and never
// reach client serialization. If we get here, it's a bug.
tracing::error!(
"PutContractRequest reached client serialization - this is a bug"
);
}
OutboundDelegateMsg::UpdateContractRequest(_) => {
tracing::error!(
"UpdateContractRequest reached client serialization - this is a bug"
);
}
OutboundDelegateMsg::SubscribeContractRequest(_) => {
tracing::error!(
"SubscribeContractRequest reached client serialization - this is a bug"
);
}
});
let messages_offset = builder.create_vector(&messages);
let delegate_response_offset = FbsDelegateResponse::create(
Expand Down
201 changes: 201 additions & 0 deletions rust/src/delegate_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use crate::generated::client_request::{
use crate::common_generated::common::SecretsId as FbsSecretsId;

use crate::client_api::{TryFromFbs, WsApiError};
use crate::contract_interface::{RelatedContracts, UpdateData};
use crate::prelude::{ContractInstanceId, WrappedState, CONTRACT_KEY_SIZE};
use crate::versioning::ContractContainer;
use crate::{code_hash::CodeHash, prelude::Parameters};

const DELEGATE_HASH_LENGTH: usize = 32;
Expand Down Expand Up @@ -458,6 +460,9 @@ pub enum InboundDelegateMsg<'a> {
ApplicationMessage(ApplicationMessage),
UserResponse(#[serde(borrow)] UserInputResponse<'a>),
GetContractResponse(GetContractResponse),
PutContractResponse(PutContractResponse),
UpdateContractResponse(UpdateContractResponse),
SubscribeContractResponse(SubscribeContractResponse),
}

impl InboundDelegateMsg<'_> {
Expand All @@ -468,6 +473,15 @@ impl InboundDelegateMsg<'_> {
InboundDelegateMsg::GetContractResponse(r) => {
InboundDelegateMsg::GetContractResponse(r)
}
InboundDelegateMsg::PutContractResponse(r) => {
InboundDelegateMsg::PutContractResponse(r)
}
InboundDelegateMsg::UpdateContractResponse(r) => {
InboundDelegateMsg::UpdateContractResponse(r)
}
InboundDelegateMsg::SubscribeContractResponse(r) => {
InboundDelegateMsg::SubscribeContractResponse(r)
}
}
}

Expand All @@ -479,6 +493,16 @@ impl InboundDelegateMsg<'_> {
InboundDelegateMsg::GetContractResponse(GetContractResponse { context, .. }) => {
Some(context)
}
InboundDelegateMsg::PutContractResponse(PutContractResponse { context, .. }) => {
Some(context)
}
InboundDelegateMsg::UpdateContractResponse(UpdateContractResponse {
context, ..
}) => Some(context),
InboundDelegateMsg::SubscribeContractResponse(SubscribeContractResponse {
context,
..
}) => Some(context),
_ => None,
}
}
Expand All @@ -491,6 +515,16 @@ impl InboundDelegateMsg<'_> {
InboundDelegateMsg::GetContractResponse(GetContractResponse { context, .. }) => {
Some(context)
}
InboundDelegateMsg::PutContractResponse(PutContractResponse { context, .. }) => {
Some(context)
}
InboundDelegateMsg::UpdateContractResponse(UpdateContractResponse {
context, ..
}) => Some(context),
InboundDelegateMsg::SubscribeContractResponse(SubscribeContractResponse {
context,
..
}) => Some(context),
_ => None,
}
}
Expand Down Expand Up @@ -593,6 +627,9 @@ pub enum OutboundDelegateMsg {
// todo: remove when context can be accessed from the delegate environment and we pass it as reference
ContextUpdated(DelegateContext),
GetContractRequest(GetContractRequest),
PutContractRequest(PutContractRequest),
UpdateContractRequest(UpdateContractRequest),
SubscribeContractRequest(SubscribeContractRequest),
}

impl From<ApplicationMessage> for OutboundDelegateMsg {
Expand All @@ -607,6 +644,24 @@ impl From<GetContractRequest> for OutboundDelegateMsg {
}
}

impl From<PutContractRequest> for OutboundDelegateMsg {
fn from(req: PutContractRequest) -> Self {
Self::PutContractRequest(req)
}
}

impl From<UpdateContractRequest> for OutboundDelegateMsg {
fn from(req: UpdateContractRequest) -> Self {
Self::UpdateContractRequest(req)
}
}

impl From<SubscribeContractRequest> for OutboundDelegateMsg {
fn from(req: SubscribeContractRequest) -> Self {
Self::SubscribeContractRequest(req)
}
}

impl OutboundDelegateMsg {
fn deser_user_input_req<'de, D>(deser: D) -> Result<UserInputRequest<'static>, D::Error>
where
Expand All @@ -620,6 +675,9 @@ impl OutboundDelegateMsg {
match self {
OutboundDelegateMsg::ApplicationMessage(msg) => msg.processed,
OutboundDelegateMsg::GetContractRequest(msg) => msg.processed,
OutboundDelegateMsg::PutContractRequest(msg) => msg.processed,
OutboundDelegateMsg::UpdateContractRequest(msg) => msg.processed,
OutboundDelegateMsg::SubscribeContractRequest(msg) => msg.processed,
OutboundDelegateMsg::RequestUserInput(_) => true,
OutboundDelegateMsg::ContextUpdated(_) => true,
}
Expand All @@ -633,6 +691,16 @@ impl OutboundDelegateMsg {
OutboundDelegateMsg::GetContractRequest(GetContractRequest { context, .. }) => {
Some(context)
}
OutboundDelegateMsg::PutContractRequest(PutContractRequest { context, .. }) => {
Some(context)
}
OutboundDelegateMsg::UpdateContractRequest(UpdateContractRequest {
context, ..
}) => Some(context),
OutboundDelegateMsg::SubscribeContractRequest(SubscribeContractRequest {
context,
..
}) => Some(context),
_ => None,
}
}
Expand All @@ -645,6 +713,16 @@ impl OutboundDelegateMsg {
OutboundDelegateMsg::GetContractRequest(GetContractRequest { context, .. }) => {
Some(context)
}
OutboundDelegateMsg::PutContractRequest(PutContractRequest { context, .. }) => {
Some(context)
}
OutboundDelegateMsg::UpdateContractRequest(UpdateContractRequest {
context, ..
}) => Some(context),
OutboundDelegateMsg::SubscribeContractRequest(SubscribeContractRequest {
context,
..
}) => Some(context),
_ => None,
}
}
Expand Down Expand Up @@ -677,6 +755,129 @@ pub struct GetContractResponse {
pub context: DelegateContext,
}

/// Request to store a new contract from within a delegate.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PutContractRequest {
/// The contract code and parameters.
pub contract: ContractContainer,
/// The initial state for the contract.
pub state: WrappedState,
/// Related contracts that this contract depends on.
#[serde(deserialize_with = "RelatedContracts::deser_related_contracts")]
pub related_contracts: RelatedContracts<'static>,
/// Context for the delegate.
pub context: DelegateContext,
/// Whether this request has been processed.
pub processed: bool,
}

impl PutContractRequest {
pub fn new(
contract: ContractContainer,
state: WrappedState,
related_contracts: RelatedContracts<'static>,
) -> Self {
Self {
contract,
state,
related_contracts,
context: Default::default(),
processed: false,
}
}
}

/// Response after attempting to store a contract from a delegate.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PutContractResponse {
/// The ID of the contract that was (attempted to be) stored.
pub contract_id: ContractInstanceId,
/// Success (Ok) or error message (Err).
pub result: Result<(), String>,
/// Context for the delegate.
pub context: DelegateContext,
}

/// Request to update an existing contract's state from within a delegate.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UpdateContractRequest {
/// The contract to update.
pub contract_id: ContractInstanceId,
/// The update to apply (full state or delta).
#[serde(deserialize_with = "UpdateContractRequest::deser_update_data")]
pub update: UpdateData<'static>,
/// Context for the delegate.
pub context: DelegateContext,
/// Whether this request has been processed.
pub processed: bool,
}

impl UpdateContractRequest {
pub fn new(contract_id: ContractInstanceId, update: UpdateData<'static>) -> Self {
Self {
contract_id,
update,
context: Default::default(),
processed: false,
}
}

fn deser_update_data<'de, D>(deser: D) -> Result<UpdateData<'static>, D::Error>
where
D: Deserializer<'de>,
{
let value = <UpdateData<'de> as Deserialize>::deserialize(deser)?;
Ok(value.into_owned())
}
}

/// Response after attempting to update a contract from a delegate.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UpdateContractResponse {
/// The contract that was updated.
pub contract_id: ContractInstanceId,
/// Success (Ok) or error message (Err).
pub result: Result<(), String>,
/// Context for the delegate.
pub context: DelegateContext,
}

/// Request to subscribe to a contract's state changes from within a delegate.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SubscribeContractRequest {
/// The contract to subscribe to.
pub contract_id: ContractInstanceId,
/// Context for the delegate.
pub context: DelegateContext,
/// Whether this request has been processed.
pub processed: bool,
}

impl SubscribeContractRequest {
pub fn new(contract_id: ContractInstanceId) -> Self {
Self {
contract_id,
context: Default::default(),
processed: false,
}
}
}

/// Response after attempting to subscribe to a contract from a delegate.
///
/// Note: This confirms subscription registration only. Actual notification
/// delivery to the delegate when the contract updates is not yet implemented
/// and will require the async delegate v2 API.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct SubscribeContractResponse {
/// The contract subscribed to.
pub contract_id: ContractInstanceId,
/// Success (Ok) or error message (Err).
pub result: Result<(), String>,
/// Context for the delegate.
pub context: DelegateContext,
}

#[serde_as]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct NotificationMessage<'a>(
Expand Down
Loading
Loading