1
2
3
4
5
6
7
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
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
/*
 * Copyright 2020 Fluence Labs Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#[cfg(all(feature = "marine-abi", target_arch = "wasm32"))]
use marine_macro::marine;

use serde::Serialize;
use serde::Deserialize;

/// Describes an origin that set corresponding value.
#[cfg_attr(all(target_arch = "wasm32", feature = "marine-abi"), marine)]
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[cfg_attr(
    feature = "rkyv",
    derive(::rkyv::Archive, ::rkyv::Serialize, ::rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv", archive(check_bytes))]
pub struct SecurityTetraplet {
    /// Id of a peer where corresponding value was set.
    pub peer_pk: String,

    /// Id of a service that set corresponding value.
    pub service_id: String,

    /// Name of a function that returned corresponding value.
    pub function_name: String,

    /// Value was produced by applying this `lens` to the output from `call_service`.
    pub lens: String,
}

impl SecurityTetraplet {
    pub fn new(
        peer_pk: impl Into<String>,
        service_id: impl Into<String>,
        function_name: impl Into<String>,
        lens: impl Into<String>,
    ) -> Self {
        Self {
            peer_pk: peer_pk.into(),
            service_id: service_id.into(),
            function_name: function_name.into(),
            lens: lens.into(),
        }
    }

    /// Create a tetraplet for string literals defined in the script
    /// such as variable here `(call ("" "") "" ["variable_1"])`.
    pub fn literal_tetraplet(init_peer_id: impl Into<String>) -> Self {
        Self {
            // these variables represent the initiator peer
            peer_pk: init_peer_id.into(),
            service_id: String::new(),
            function_name: String::new(),
            // lens can't be applied to the string literals
            lens: String::new(),
        }
    }

    pub fn add_lens(&mut self, lens: &str) {
        self.lens.push_str(lens)
    }
}

/// This struct contains parameters that would be accessible by Wasm modules.
#[cfg_attr(all(target_arch = "wasm32", feature = "marine-abi"), marine)]
#[derive(Clone, PartialEq, Default, Eq, Debug, Serialize, Deserialize)]
#[cfg_attr(
    feature = "rkyv",
    derive(::rkyv::Archive, ::rkyv::Serialize, ::rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv", archive(check_bytes))]
pub struct CallParameters {
    /// Parameters of the particle that caused this call.
    pub particle: ParticleParameters,

    /// Id of the current service.
    pub service_id: String,

    /// Id of the service creator.
    pub service_creator_peer_id: String,

    /// PeerId of the peer who hosts worker with this service.
    pub host_id: String,

    /// PeerId of the worker who hosts this service.
    pub worker_id: String,

    /// Security tetraplets which described origin of the arguments.
    pub tetraplets: Vec<Vec<SecurityTetraplet>>,
}

#[cfg_attr(all(target_arch = "wasm32", feature = "marine-abi"), marine)]
#[derive(Clone, PartialEq, Default, Eq, Debug, Serialize, Deserialize)]
#[cfg_attr(
    feature = "rkyv",
    derive(::rkyv::Archive, ::rkyv::Serialize, ::rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv", archive(check_bytes))]
pub struct ParticleParameters {
    /// Id of the particle which execution resulted a call this service.
    pub id: String,

    /// Peer id of the AIR script initiator.
    pub init_peer_id: String,

    /// Unix timestamp of the particle start time.
    pub timestamp: u64,

    /// Time to live for this particle in milliseconds.
    pub ttl: u32,

    /// AIR script in this particle.
    pub script: String,

    /// Signature made by particle initiator -- init_peer_id.
    pub signature: Vec<u8>,

    /// particle.signature signed by host_id -- used for FS access.
    pub token: String,
}

use std::fmt;
impl fmt::Display for SecurityTetraplet {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "peer_pk: {}, service_id: {}, function_name: {}, lens: {}",
            self.peer_pk, self.service_id, self.function_name, self.lens
        )
    }
}

/// This functions takes from host current call parameters.
/// Beware that this implies import function call which takes some time.
#[cfg(all(feature = "marine-abi", target_arch = "wasm32"))]
pub fn get_call_parameters() -> CallParameters {
    // it's safe until it is executed on standard Fluence node with appropriate import function
    unsafe {
        get_call_raw_parameters();
        let raw_call_parameters = crate::internal::get_result_ptr();
        CallParameters::__m_generated_deserialize(raw_call_parameters as _)
    }
}

#[cfg(not(all(target_arch = "wasm32", feature = "marine-abi")))]
pub fn get_call_parameters() -> CallParameters {
    unimplemented!()
}

#[cfg(all(feature = "marine-abi", target_arch = "wasm32"))]
#[link(wasm_import_module = "__marine_host_api_v3")]
#[allow(improper_ctypes)]
extern "C" {
    // returns serialized current call parameters
    #[link_name = "get_call_parameters"]
    fn get_call_raw_parameters();
}

#[cfg(all(feature = "marine-abi", target_arch = "wasm32"))]
#[allow(unused_extern_crates)]
extern crate self as marine_rs_sdk;

#[cfg(all(feature = "marine-abi", target_arch = "wasm32"))]
#[allow(unused_imports)]
mod internal {
    pub(crate) use marine_rs_sdk_main::add_object_to_release;
    pub(crate) use marine_rs_sdk_main::get_result_ptr;
    pub(crate) use marine_rs_sdk_main::get_result_size;
    pub(crate) use marine_rs_sdk_main::set_result_ptr;
    pub(crate) use marine_rs_sdk_main::set_result_size;
}