Skip to main content

freenet_stdlib/
delegate_interface.rs

1use std::{
2    borrow::{Borrow, Cow},
3    fmt::Display,
4    fs::File,
5    io::Read,
6    ops::Deref,
7    path::Path,
8};
9
10use blake3::{traits::digest::Digest, Hasher as Blake3};
11use serde::{Deserialize, Deserializer, Serialize};
12use serde_with::serde_as;
13
14use crate::generated::client_request::{
15    DelegateKey as FbsDelegateKey, InboundDelegateMsg as FbsInboundDelegateMsg,
16    InboundDelegateMsgType,
17};
18
19use crate::common_generated::common::SecretsId as FbsSecretsId;
20
21use crate::client_api::{TryFromFbs, WsApiError};
22use crate::prelude::{ContractInstanceId, WrappedState, CONTRACT_KEY_SIZE};
23use crate::{code_hash::CodeHash, prelude::Parameters};
24
25const DELEGATE_HASH_LENGTH: usize = 32;
26
27type Secret = Vec<u8>;
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
30pub struct Delegate<'a> {
31    #[serde(borrow)]
32    parameters: Parameters<'a>,
33    #[serde(borrow)]
34    pub data: DelegateCode<'a>,
35    key: DelegateKey,
36}
37
38impl Delegate<'_> {
39    pub fn key(&self) -> &DelegateKey {
40        &self.key
41    }
42
43    pub fn code(&self) -> &DelegateCode<'_> {
44        &self.data
45    }
46
47    pub fn code_hash(&self) -> &CodeHash {
48        &self.data.code_hash
49    }
50
51    pub fn params(&self) -> &Parameters<'_> {
52        &self.parameters
53    }
54
55    pub fn into_owned(self) -> Delegate<'static> {
56        Delegate {
57            parameters: self.parameters.into_owned(),
58            data: self.data.into_owned(),
59            key: self.key,
60        }
61    }
62
63    pub fn size(&self) -> usize {
64        self.parameters.size() + self.data.size()
65    }
66
67    pub(crate) fn deserialize_delegate<'de, D>(deser: D) -> Result<Delegate<'static>, D::Error>
68    where
69        D: Deserializer<'de>,
70    {
71        let data: Delegate<'de> = Deserialize::deserialize(deser)?;
72        Ok(data.into_owned())
73    }
74}
75
76impl PartialEq for Delegate<'_> {
77    fn eq(&self, other: &Self) -> bool {
78        self.key == other.key
79    }
80}
81
82impl Eq for Delegate<'_> {}
83
84impl<'a> From<(&DelegateCode<'a>, &Parameters<'a>)> for Delegate<'a> {
85    fn from((data, parameters): (&DelegateCode<'a>, &Parameters<'a>)) -> Self {
86        Self {
87            key: DelegateKey::from_params_and_code(parameters, data),
88            parameters: parameters.clone(),
89            data: data.clone(),
90        }
91    }
92}
93
94/// Executable delegate
95#[derive(Debug, Serialize, Deserialize, Clone)]
96#[serde_as]
97pub struct DelegateCode<'a> {
98    #[serde_as(as = "serde_with::Bytes")]
99    #[serde(borrow)]
100    pub(crate) data: Cow<'a, [u8]>,
101    // todo: skip serializing and instead compute it
102    pub(crate) code_hash: CodeHash,
103}
104
105impl DelegateCode<'static> {
106    /// Loads the contract raw wasm module, without any version.
107    pub fn load_raw(path: &Path) -> Result<Self, std::io::Error> {
108        let contract_data = Self::load_bytes(path)?;
109        Ok(DelegateCode::from(contract_data))
110    }
111
112    pub(crate) fn load_bytes(path: &Path) -> Result<Vec<u8>, std::io::Error> {
113        let mut contract_file = File::open(path)?;
114        let mut contract_data = if let Ok(md) = contract_file.metadata() {
115            Vec::with_capacity(md.len() as usize)
116        } else {
117            Vec::new()
118        };
119        contract_file.read_to_end(&mut contract_data)?;
120        Ok(contract_data)
121    }
122}
123
124impl DelegateCode<'_> {
125    /// Delegate code hash.
126    pub fn hash(&self) -> &CodeHash {
127        &self.code_hash
128    }
129
130    /// Returns the `Base58` string representation of the delegate key.
131    pub fn hash_str(&self) -> String {
132        Self::encode_hash(&self.code_hash.0)
133    }
134
135    /// Reference to delegate code.
136    pub fn data(&self) -> &[u8] {
137        &self.data
138    }
139
140    /// Returns the `Base58` string representation of a hash.
141    pub fn encode_hash(hash: &[u8; DELEGATE_HASH_LENGTH]) -> String {
142        bs58::encode(hash)
143            .with_alphabet(bs58::Alphabet::BITCOIN)
144            .into_string()
145    }
146
147    pub fn into_owned(self) -> DelegateCode<'static> {
148        DelegateCode {
149            code_hash: self.code_hash,
150            data: Cow::from(self.data.into_owned()),
151        }
152    }
153
154    pub fn size(&self) -> usize {
155        self.data.len()
156    }
157}
158
159impl PartialEq for DelegateCode<'_> {
160    fn eq(&self, other: &Self) -> bool {
161        self.code_hash == other.code_hash
162    }
163}
164
165impl Eq for DelegateCode<'_> {}
166
167impl AsRef<[u8]> for DelegateCode<'_> {
168    fn as_ref(&self) -> &[u8] {
169        self.data.borrow()
170    }
171}
172
173impl From<Vec<u8>> for DelegateCode<'static> {
174    fn from(data: Vec<u8>) -> Self {
175        let key = CodeHash::from_code(data.as_slice());
176        DelegateCode {
177            data: Cow::from(data),
178            code_hash: key,
179        }
180    }
181}
182
183impl<'a> From<&'a [u8]> for DelegateCode<'a> {
184    fn from(code: &'a [u8]) -> Self {
185        let key = CodeHash::from_code(code);
186        DelegateCode {
187            data: Cow::from(code),
188            code_hash: key,
189        }
190    }
191}
192
193#[serde_as]
194#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
195pub struct DelegateKey {
196    #[serde_as(as = "[_; DELEGATE_HASH_LENGTH]")]
197    key: [u8; DELEGATE_HASH_LENGTH],
198    code_hash: CodeHash,
199}
200
201impl From<DelegateKey> for SecretsId {
202    fn from(key: DelegateKey) -> SecretsId {
203        SecretsId {
204            hash: key.key,
205            key: vec![],
206        }
207    }
208}
209
210impl DelegateKey {
211    pub const fn new(key: [u8; DELEGATE_HASH_LENGTH], code_hash: CodeHash) -> Self {
212        Self { key, code_hash }
213    }
214
215    fn from_params_and_code<'a>(
216        params: impl Borrow<Parameters<'a>>,
217        wasm_code: impl Borrow<DelegateCode<'a>>,
218    ) -> Self {
219        let code = wasm_code.borrow();
220        let key = generate_id(params.borrow(), code);
221        Self {
222            key,
223            code_hash: *code.hash(),
224        }
225    }
226
227    pub fn encode(&self) -> String {
228        bs58::encode(self.key)
229            .with_alphabet(bs58::Alphabet::BITCOIN)
230            .into_string()
231    }
232
233    pub fn code_hash(&self) -> &CodeHash {
234        &self.code_hash
235    }
236
237    pub fn bytes(&self) -> &[u8] {
238        self.key.as_ref()
239    }
240
241    pub fn from_params(
242        code_hash: impl Into<String>,
243        parameters: &Parameters,
244    ) -> Result<Self, bs58::decode::Error> {
245        let mut code_key = [0; DELEGATE_HASH_LENGTH];
246        bs58::decode(code_hash.into())
247            .with_alphabet(bs58::Alphabet::BITCOIN)
248            .onto(&mut code_key)?;
249        let mut hasher = Blake3::new();
250        hasher.update(code_key.as_slice());
251        hasher.update(parameters.as_ref());
252        let full_key_arr = hasher.finalize();
253
254        debug_assert_eq!(full_key_arr[..].len(), DELEGATE_HASH_LENGTH);
255        let mut key = [0; DELEGATE_HASH_LENGTH];
256        key.copy_from_slice(&full_key_arr);
257
258        Ok(Self {
259            key,
260            code_hash: CodeHash(code_key),
261        })
262    }
263}
264
265impl Deref for DelegateKey {
266    type Target = [u8; DELEGATE_HASH_LENGTH];
267
268    fn deref(&self) -> &Self::Target {
269        &self.key
270    }
271}
272
273impl Display for DelegateKey {
274    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275        write!(f, "{}", self.encode())
276    }
277}
278
279impl<'a> TryFromFbs<&FbsDelegateKey<'a>> for DelegateKey {
280    fn try_decode_fbs(key: &FbsDelegateKey<'a>) -> Result<Self, WsApiError> {
281        let mut key_bytes = [0; DELEGATE_HASH_LENGTH];
282        key_bytes.copy_from_slice(key.key().bytes().iter().as_ref());
283        Ok(DelegateKey {
284            key: key_bytes,
285            code_hash: CodeHash::from_code(key.code_hash().bytes()),
286        })
287    }
288}
289
290/// Type of errors during interaction with a delegate.
291#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
292pub enum DelegateError {
293    #[error("de/serialization error: {0}")]
294    Deser(String),
295    #[error("{0}")]
296    Other(String),
297}
298
299fn generate_id<'a>(
300    parameters: &Parameters<'a>,
301    code_data: &DelegateCode<'a>,
302) -> [u8; DELEGATE_HASH_LENGTH] {
303    let contract_hash = code_data.hash();
304
305    let mut hasher = Blake3::new();
306    hasher.update(contract_hash.0.as_slice());
307    hasher.update(parameters.as_ref());
308    let full_key_arr = hasher.finalize();
309
310    debug_assert_eq!(full_key_arr[..].len(), DELEGATE_HASH_LENGTH);
311    let mut key = [0; DELEGATE_HASH_LENGTH];
312    key.copy_from_slice(&full_key_arr);
313    key
314}
315
316#[serde_as]
317#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
318pub struct SecretsId {
319    #[serde_as(as = "serde_with::Bytes")]
320    key: Vec<u8>,
321    #[serde_as(as = "[_; 32]")]
322    hash: [u8; 32],
323}
324
325impl SecretsId {
326    pub fn new(key: Vec<u8>) -> Self {
327        let mut hasher = Blake3::new();
328        hasher.update(&key);
329        let hashed = hasher.finalize();
330        let mut hash = [0; 32];
331        hash.copy_from_slice(&hashed);
332        Self { key, hash }
333    }
334
335    pub fn encode(&self) -> String {
336        bs58::encode(self.hash)
337            .with_alphabet(bs58::Alphabet::BITCOIN)
338            .into_string()
339    }
340
341    pub fn hash(&self) -> &[u8; 32] {
342        &self.hash
343    }
344    pub fn key(&self) -> &[u8] {
345        self.key.as_slice()
346    }
347}
348
349impl Display for SecretsId {
350    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
351        write!(f, "{}", self.encode())
352    }
353}
354
355impl<'a> TryFromFbs<&FbsSecretsId<'a>> for SecretsId {
356    fn try_decode_fbs(key: &FbsSecretsId<'a>) -> Result<Self, WsApiError> {
357        let mut key_hash = [0; 32];
358        key_hash.copy_from_slice(key.hash().bytes().iter().as_ref());
359        Ok(SecretsId {
360            key: key.key().bytes().to_vec(),
361            hash: key_hash,
362        })
363    }
364}
365
366/// A Delegate is a webassembly code designed to act as an agent for the user on
367/// Freenet. Delegates can:
368///
369///  * Store private data on behalf of the user
370///  * Create, read, and modify contracts
371///  * Create other delegates
372///  * Send and receive messages from other delegates and user interfaces
373///  * Ask the user questions and receive answers
374///
375/// Example use cases:
376///
377///  * A delegate stores a private key for the user, other components can ask
378///    the delegate to sign messages, it will ask the user for permission
379///  * A delegate monitors an inbox contract and downloads new messages when
380///    they arrive
381pub trait DelegateInterface {
382    /// Process inbound message, producing zero or more outbound messages in response.
383    /// All state for the delegate must be stored using the secret mechanism.
384    ///
385    /// # Arguments
386    /// - attested: an optional identifier for the client of this function. Usually will
387    ///   be a [`ContractInstanceId`].
388    fn process(
389        parameters: Parameters<'static>,
390        attested: Option<&'static [u8]>,
391        message: InboundDelegateMsg,
392    ) -> Result<Vec<OutboundDelegateMsg>, DelegateError>;
393}
394
395#[serde_as]
396#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
397pub struct DelegateContext(#[serde_as(as = "serde_with::Bytes")] Vec<u8>);
398
399impl DelegateContext {
400    pub const MAX_SIZE: usize = 4096 * 10 * 10;
401
402    pub fn new(bytes: Vec<u8>) -> Self {
403        assert!(bytes.len() < Self::MAX_SIZE);
404        Self(bytes)
405    }
406
407    pub fn append(&mut self, bytes: &mut Vec<u8>) {
408        assert!(self.0.len() + bytes.len() < Self::MAX_SIZE);
409        self.0.append(bytes)
410    }
411
412    pub fn replace(&mut self, bytes: Vec<u8>) {
413        assert!(bytes.len() < Self::MAX_SIZE);
414        let _ = std::mem::replace(&mut self.0, bytes);
415    }
416}
417
418impl AsRef<[u8]> for DelegateContext {
419    fn as_ref(&self) -> &[u8] {
420        &self.0
421    }
422}
423
424#[derive(Serialize, Deserialize, Debug, Clone)]
425pub enum InboundDelegateMsg<'a> {
426    ApplicationMessage(ApplicationMessage),
427    GetSecretResponse(GetSecretResponse),
428    UserResponse(#[serde(borrow)] UserInputResponse<'a>),
429    GetSecretRequest(GetSecretRequest),
430    GetContractResponse(GetContractResponse),
431}
432
433impl InboundDelegateMsg<'_> {
434    pub fn into_owned(self) -> InboundDelegateMsg<'static> {
435        match self {
436            InboundDelegateMsg::ApplicationMessage(r) => InboundDelegateMsg::ApplicationMessage(r),
437            InboundDelegateMsg::GetSecretResponse(r) => InboundDelegateMsg::GetSecretResponse(r),
438            InboundDelegateMsg::UserResponse(r) => InboundDelegateMsg::UserResponse(r.into_owned()),
439            InboundDelegateMsg::GetSecretRequest(r) => InboundDelegateMsg::GetSecretRequest(r),
440            InboundDelegateMsg::GetContractResponse(r) => {
441                InboundDelegateMsg::GetContractResponse(r)
442            }
443        }
444    }
445
446    pub fn get_context(&self) -> Option<&DelegateContext> {
447        match self {
448            InboundDelegateMsg::ApplicationMessage(ApplicationMessage { context, .. }) => {
449                Some(context)
450            }
451            InboundDelegateMsg::GetSecretResponse(GetSecretResponse { context, .. }) => {
452                Some(context)
453            }
454            InboundDelegateMsg::GetContractResponse(GetContractResponse { context, .. }) => {
455                Some(context)
456            }
457            _ => None,
458        }
459    }
460
461    pub fn get_mut_context(&mut self) -> Option<&mut DelegateContext> {
462        match self {
463            InboundDelegateMsg::ApplicationMessage(ApplicationMessage { context, .. }) => {
464                Some(context)
465            }
466            InboundDelegateMsg::GetSecretResponse(GetSecretResponse { context, .. }) => {
467                Some(context)
468            }
469            InboundDelegateMsg::GetContractResponse(GetContractResponse { context, .. }) => {
470                Some(context)
471            }
472            _ => None,
473        }
474    }
475}
476
477impl From<GetSecretRequest> for InboundDelegateMsg<'_> {
478    fn from(value: GetSecretRequest) -> Self {
479        Self::GetSecretRequest(value)
480    }
481}
482
483impl From<ApplicationMessage> for InboundDelegateMsg<'_> {
484    fn from(value: ApplicationMessage) -> Self {
485        Self::ApplicationMessage(value)
486    }
487}
488
489impl<'a> TryFromFbs<&FbsInboundDelegateMsg<'a>> for InboundDelegateMsg<'a> {
490    fn try_decode_fbs(msg: &FbsInboundDelegateMsg<'a>) -> Result<Self, WsApiError> {
491        match msg.inbound_type() {
492            InboundDelegateMsgType::common_ApplicationMessage => {
493                let app_msg = msg.inbound_as_common_application_message().unwrap();
494                let mut instance_key_bytes = [0; CONTRACT_KEY_SIZE];
495                instance_key_bytes
496                    .copy_from_slice(app_msg.app().data().bytes().to_vec().as_slice());
497                let app_msg = ApplicationMessage {
498                    app: ContractInstanceId::new(instance_key_bytes),
499                    payload: app_msg.payload().bytes().to_vec(),
500                    context: DelegateContext::new(app_msg.context().bytes().to_vec()),
501                    processed: app_msg.processed(),
502                };
503                Ok(InboundDelegateMsg::ApplicationMessage(app_msg))
504            }
505            InboundDelegateMsgType::common_GetSecretResponse => {
506                let get_secret = msg.inbound_as_common_get_secret_response().unwrap();
507                let get_secret = GetSecretResponse {
508                    key: SecretsId::try_decode_fbs(&get_secret.key())?,
509                    value: get_secret.value().map(|value| value.bytes().to_vec()),
510                    context: DelegateContext::new(get_secret.delegate_context().bytes().to_vec()),
511                };
512                Ok(InboundDelegateMsg::GetSecretResponse(get_secret))
513            }
514            InboundDelegateMsgType::UserInputResponse => {
515                let user_response = msg.inbound_as_user_input_response().unwrap();
516                let user_response = UserInputResponse {
517                    request_id: user_response.request_id(),
518                    response: ClientResponse::new(user_response.response().data().bytes().to_vec()),
519                    context: DelegateContext::new(
520                        user_response.delegate_context().bytes().to_vec(),
521                    ),
522                };
523                Ok(InboundDelegateMsg::UserResponse(user_response))
524            }
525            InboundDelegateMsgType::common_GetSecretRequest => {
526                let get_secret = msg.inbound_as_common_get_secret_request().unwrap();
527                let get_secret = GetSecretRequest {
528                    key: SecretsId::try_decode_fbs(&get_secret.key())?,
529                    context: DelegateContext::new(get_secret.delegate_context().bytes().to_vec()),
530                    processed: get_secret.processed(),
531                };
532                Ok(InboundDelegateMsg::GetSecretRequest(get_secret))
533            }
534            _ => unreachable!("invalid inbound delegate message type"),
535        }
536    }
537}
538
539#[derive(Serialize, Deserialize, Debug, Clone)]
540pub struct GetSecretResponse {
541    pub key: SecretsId,
542    pub value: Option<Secret>,
543    pub context: DelegateContext,
544}
545
546#[non_exhaustive]
547#[derive(Serialize, Deserialize, Debug, Clone)]
548pub struct ApplicationMessage {
549    pub app: ContractInstanceId,
550    pub payload: Vec<u8>,
551    pub context: DelegateContext,
552    pub processed: bool,
553}
554
555impl ApplicationMessage {
556    pub fn new(app: ContractInstanceId, payload: Vec<u8>) -> Self {
557        Self {
558            app,
559            payload,
560            context: DelegateContext::default(),
561            processed: false,
562        }
563    }
564
565    pub fn with_context(mut self, context: DelegateContext) -> Self {
566        self.context = context;
567        self
568    }
569
570    pub fn processed(mut self, p: bool) -> Self {
571        self.processed = p;
572        self
573    }
574}
575
576#[derive(Serialize, Deserialize, Debug, Clone)]
577pub struct UserInputResponse<'a> {
578    pub request_id: u32,
579    #[serde(borrow)]
580    pub response: ClientResponse<'a>,
581    pub context: DelegateContext,
582}
583
584impl UserInputResponse<'_> {
585    pub fn into_owned(self) -> UserInputResponse<'static> {
586        UserInputResponse {
587            request_id: self.request_id,
588            response: self.response.into_owned(),
589            context: self.context,
590        }
591    }
592}
593
594#[derive(Serialize, Deserialize, Debug, Clone)]
595pub enum OutboundDelegateMsg {
596    // for the apps
597    ApplicationMessage(ApplicationMessage),
598    RequestUserInput(
599        #[serde(deserialize_with = "OutboundDelegateMsg::deser_user_input_req")]
600        UserInputRequest<'static>,
601    ),
602    // todo: remove when context can be accessed from the delegate environment and we pass it as reference
603    ContextUpdated(DelegateContext),
604    // from the node
605    GetSecretRequest(GetSecretRequest),
606    SetSecretRequest(SetSecretRequest),
607    GetContractRequest(GetContractRequest),
608    GetSecretResponse(GetSecretResponse),
609}
610
611impl From<GetSecretRequest> for OutboundDelegateMsg {
612    fn from(req: GetSecretRequest) -> Self {
613        Self::GetSecretRequest(req)
614    }
615}
616
617impl From<ApplicationMessage> for OutboundDelegateMsg {
618    fn from(req: ApplicationMessage) -> Self {
619        Self::ApplicationMessage(req)
620    }
621}
622
623impl From<GetContractRequest> for OutboundDelegateMsg {
624    fn from(req: GetContractRequest) -> Self {
625        Self::GetContractRequest(req)
626    }
627}
628
629impl OutboundDelegateMsg {
630    fn deser_user_input_req<'de, D>(deser: D) -> Result<UserInputRequest<'static>, D::Error>
631    where
632        D: serde::Deserializer<'de>,
633    {
634        let value = <UserInputRequest<'de> as Deserialize>::deserialize(deser)?;
635        Ok(value.into_owned())
636    }
637
638    pub fn processed(&self) -> bool {
639        match self {
640            OutboundDelegateMsg::ApplicationMessage(msg) => msg.processed,
641            OutboundDelegateMsg::GetSecretRequest(msg) => msg.processed,
642            OutboundDelegateMsg::GetContractRequest(msg) => msg.processed,
643            OutboundDelegateMsg::SetSecretRequest(_) => false,
644            OutboundDelegateMsg::RequestUserInput(_) => true,
645            OutboundDelegateMsg::ContextUpdated(_) => true,
646            OutboundDelegateMsg::GetSecretResponse(_) => true,
647        }
648    }
649
650    pub fn get_context(&self) -> Option<&DelegateContext> {
651        match self {
652            OutboundDelegateMsg::ApplicationMessage(ApplicationMessage { context, .. }) => {
653                Some(context)
654            }
655            OutboundDelegateMsg::GetSecretRequest(GetSecretRequest { context, .. }) => {
656                Some(context)
657            }
658            OutboundDelegateMsg::GetContractRequest(GetContractRequest { context, .. }) => {
659                Some(context)
660            }
661            _ => None,
662        }
663    }
664
665    pub fn get_mut_context(&mut self) -> Option<&mut DelegateContext> {
666        match self {
667            OutboundDelegateMsg::ApplicationMessage(ApplicationMessage { context, .. }) => {
668                Some(context)
669            }
670            OutboundDelegateMsg::GetSecretRequest(GetSecretRequest { context, .. }) => {
671                Some(context)
672            }
673            OutboundDelegateMsg::GetContractRequest(GetContractRequest { context, .. }) => {
674                Some(context)
675            }
676            _ => None,
677        }
678    }
679}
680
681#[derive(Serialize, Deserialize, Debug, Clone)]
682pub struct GetSecretRequest {
683    pub key: SecretsId,
684    pub context: DelegateContext,
685    pub processed: bool,
686}
687
688impl GetSecretRequest {
689    pub fn new(key: SecretsId) -> Self {
690        Self {
691            key,
692            context: Default::default(),
693            processed: false,
694        }
695    }
696}
697
698#[derive(Serialize, Deserialize, Debug, Clone)]
699pub struct SetSecretRequest {
700    pub key: SecretsId,
701    /// Sets or unsets (if none) a value associated with the key.
702    pub value: Option<Secret>,
703}
704
705/// Request to get contract state from within a delegate.
706#[derive(Serialize, Deserialize, Debug, Clone)]
707pub struct GetContractRequest {
708    pub contract_id: ContractInstanceId,
709    pub context: DelegateContext,
710    pub processed: bool,
711}
712
713impl GetContractRequest {
714    pub fn new(contract_id: ContractInstanceId) -> Self {
715        Self {
716            contract_id,
717            context: Default::default(),
718            processed: false,
719        }
720    }
721}
722
723/// Response containing contract state for a delegate.
724#[derive(Serialize, Deserialize, Debug, Clone)]
725pub struct GetContractResponse {
726    pub contract_id: ContractInstanceId,
727    /// The contract state, or None if the contract was not found locally.
728    pub state: Option<WrappedState>,
729    pub context: DelegateContext,
730}
731
732#[serde_as]
733#[derive(Serialize, Deserialize, Debug, Clone)]
734pub struct NotificationMessage<'a>(
735    #[serde_as(as = "serde_with::Bytes")]
736    #[serde(borrow)]
737    Cow<'a, [u8]>,
738);
739
740impl TryFrom<&serde_json::Value> for NotificationMessage<'static> {
741    type Error = ();
742
743    fn try_from(json: &serde_json::Value) -> Result<NotificationMessage<'static>, ()> {
744        // todo: validate format when we have a better idea of what we want here
745        let bytes = serde_json::to_vec(json).unwrap();
746        Ok(Self(Cow::Owned(bytes)))
747    }
748}
749
750impl NotificationMessage<'_> {
751    pub fn into_owned(self) -> NotificationMessage<'static> {
752        NotificationMessage(self.0.into_owned().into())
753    }
754    pub fn bytes(&self) -> &[u8] {
755        self.0.as_ref()
756    }
757}
758
759#[serde_as]
760#[derive(Serialize, Deserialize, Debug, Clone)]
761pub struct ClientResponse<'a>(
762    #[serde_as(as = "serde_with::Bytes")]
763    #[serde(borrow)]
764    Cow<'a, [u8]>,
765);
766
767impl Deref for ClientResponse<'_> {
768    type Target = [u8];
769
770    fn deref(&self) -> &Self::Target {
771        &self.0
772    }
773}
774
775impl ClientResponse<'_> {
776    pub fn new(response: Vec<u8>) -> Self {
777        Self(response.into())
778    }
779    pub fn into_owned(self) -> ClientResponse<'static> {
780        ClientResponse(self.0.into_owned().into())
781    }
782    pub fn bytes(&self) -> &[u8] {
783        self.0.as_ref()
784    }
785}
786
787#[derive(Serialize, Deserialize, Debug, Clone)]
788pub struct UserInputRequest<'a> {
789    pub request_id: u32,
790    #[serde(borrow)]
791    /// An interpretable message by the notification system.
792    pub message: NotificationMessage<'a>,
793    /// If a response is required from the user they can be chosen from this list.
794    pub responses: Vec<ClientResponse<'a>>,
795}
796
797impl UserInputRequest<'_> {
798    pub fn into_owned(self) -> UserInputRequest<'static> {
799        UserInputRequest {
800            request_id: self.request_id,
801            message: self.message.into_owned(),
802            responses: self.responses.into_iter().map(|r| r.into_owned()).collect(),
803        }
804    }
805}
806
807#[doc(hidden)]
808pub(crate) mod wasm_interface {
809    //! Contains all the types to interface between the host environment and
810    //! the wasm module execution.
811    use super::*;
812    use crate::memory::WasmLinearMem;
813
814    #[repr(C)]
815    #[derive(Debug, Clone, Copy)]
816    pub struct DelegateInterfaceResult {
817        ptr: i64,
818        size: u32,
819    }
820
821    impl DelegateInterfaceResult {
822        pub unsafe fn from_raw(ptr: i64, mem: &WasmLinearMem) -> Self {
823            let result = Box::leak(Box::from_raw(crate::memory::buf::compute_ptr(
824                ptr as *mut Self,
825                mem,
826            )));
827            #[cfg(feature = "trace")]
828            {
829                tracing::trace!(
830                    "got FFI result @ {ptr} ({:p}) -> {result:?}",
831                    ptr as *mut Self
832                );
833            }
834            *result
835        }
836
837        #[cfg(feature = "contract")]
838        pub fn into_raw(self) -> i64 {
839            #[cfg(feature = "trace")]
840            {
841                tracing::trace!("returning FFI -> {self:?}");
842            }
843            let ptr = Box::into_raw(Box::new(self));
844            #[cfg(feature = "trace")]
845            {
846                tracing::trace!("FFI result ptr: {ptr:p} ({}i64)", ptr as i64);
847            }
848            ptr as _
849        }
850
851        pub unsafe fn unwrap(
852            self,
853            mem: WasmLinearMem,
854        ) -> Result<Vec<OutboundDelegateMsg>, DelegateError> {
855            let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
856            let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
857            let value: Result<Vec<OutboundDelegateMsg>, DelegateError> =
858                bincode::deserialize(serialized)
859                    .map_err(|e| DelegateError::Other(format!("{e}")))?;
860            #[cfg(feature = "trace")]
861            {
862                tracing::trace!(
863                    "got result through FFI; addr: {:p} ({}i64, mapped: {ptr:p})
864                     serialized: {serialized:?}
865                     value: {value:?}",
866                    self.ptr as *mut u8,
867                    self.ptr
868                );
869            }
870            value
871        }
872    }
873
874    impl From<Result<Vec<OutboundDelegateMsg>, DelegateError>> for DelegateInterfaceResult {
875        fn from(value: Result<Vec<OutboundDelegateMsg>, DelegateError>) -> Self {
876            let serialized = bincode::serialize(&value).unwrap();
877            let size = serialized.len() as _;
878            let ptr = serialized.as_ptr();
879            #[cfg(feature = "trace")]
880            {
881                tracing::trace!(
882                    "sending result through FFI; addr: {ptr:p} ({}),\n  serialized: {serialized:?}\n  value: {value:?}",
883                    ptr as i64
884                );
885            }
886            std::mem::forget(serialized);
887            Self {
888                ptr: ptr as i64,
889                size,
890            }
891        }
892    }
893}