impls.rs 12.3 KB
Newer Older
1
// Copyright 2018-2020 Parity Technologies (UK) Ltd.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//
// 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.

use super::{
    ext,
    EnvInstance,
Hero Bird's avatar
Hero Bird committed
18
19
    Error as ExtError,
    ScopedBuffer,
20
21
22
};
use crate::env::{
    call::{
23
        utils::ReturnType,
24
        CallParams,
25
        CreateParams,
26
    },
27
28
29
    Blake2x128,
    Blake2x256,
    CryptoHash,
30
    Env,
Hero Bird's avatar
Hero Bird committed
31
    EnvError,
32
    EnvTypes,
33
34
    Keccak256,
    HashOutput,
35
    Result,
Hero Bird's avatar
Hero Bird committed
36
    ReturnFlags,
37
    Sha2x256,
38
39
40
41
42
    Topics,
    TypedEnv,
};
use ink_primitives::Key;

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
impl CryptoHash for Blake2x128 {
    fn hash(input: &[u8], output: &mut <Self as HashOutput>::Type) {
        type OutputType = [u8; 16];
        static_assertions::assert_type_eq_all!(<Blake2x128 as HashOutput>::Type, OutputType);
        let output: &mut OutputType = arrayref::array_mut_ref!(output, 0, 16);
        ext::hash_blake2_128(input, output);
    }
}

impl CryptoHash for Blake2x256 {
    fn hash(input: &[u8], output: &mut <Self as HashOutput>::Type) {
        type OutputType = [u8; 32];
        static_assertions::assert_type_eq_all!(<Blake2x256 as HashOutput>::Type, OutputType);
        let output: &mut OutputType = arrayref::array_mut_ref!(output, 0, 32);
        ext::hash_blake2_256(input, output);
    }
}

impl CryptoHash for Sha2x256 {
    fn hash(input: &[u8], output: &mut <Self as HashOutput>::Type) {
        type OutputType = [u8; 32];
        static_assertions::assert_type_eq_all!(<Sha2x256 as HashOutput>::Type, OutputType);
        let output: &mut OutputType = arrayref::array_mut_ref!(output, 0, 32);
        ext::hash_sha2_256(input, output);
    }
}

impl CryptoHash for Keccak256 {
    fn hash(input: &[u8], output: &mut <Self as HashOutput>::Type) {
        type OutputType = [u8; 32];
        static_assertions::assert_type_eq_all!(<Keccak256 as HashOutput>::Type, OutputType);
        let output: &mut OutputType = arrayref::array_mut_ref!(output, 0, 32);
        ext::hash_keccak_256(input, output);
    }
}

Hero Bird's avatar
Hero Bird committed
79
80
81
82
83
84
85
86
87
88
89
90
91
impl From<ext::Error> for EnvError {
    fn from(ext_error: ext::Error) -> Self {
        match ext_error {
            ext::Error::UnknownError => Self::UnknownError,
            ext::Error::CalleeTrapped => Self::CalleeTrapped,
            ext::Error::CalleeReverted => Self::CalleeReverted,
            ext::Error::KeyNotFound => Self::KeyNotFound,
            ext::Error::BelowSubsistenceThreshold => Self::BelowSubsistenceThreshold,
            ext::Error::TransferFailed => Self::TransferFailed,
            ext::Error::NewContractNotFunded => Self::NewContractNotFunded,
            ext::Error::CodeNotFound => Self::CodeNotFound,
            ext::Error::NotCallable => Self::NotCallable,
        }
92
    }
Hero Bird's avatar
Hero Bird committed
93
}
94

Hero Bird's avatar
Hero Bird committed
95
96
97
98
impl EnvInstance {
    /// Returns a new scoped buffer for the entire scope of the static 16kB buffer.
    fn scoped_buffer(&mut self) -> ScopedBuffer {
        ScopedBuffer::from(&mut self.buffer[..])
99
100
101
    }

    /// Returns the contract property value.
Hero Bird's avatar
Hero Bird committed
102
    fn get_property<T>(&mut self, ext_fn: fn(output: &mut &mut [u8])) -> Result<T>
103
104
105
    where
        T: scale::Decode,
    {
Hero Bird's avatar
Hero Bird committed
106
107
108
        let full_scope = &mut self.scoped_buffer().take_rest();
        ext_fn(full_scope);
        scale::Decode::decode(&mut &full_scope[..]).map_err(Into::into)
109
110
111
    }

    /// Reusable implementation for invoking another contract message.
Hero Bird's avatar
Hero Bird committed
112
    fn invoke_contract_impl<T, Args, RetType, R>(
113
        &mut self,
Hero Bird's avatar
Hero Bird committed
114
115
        params: &CallParams<T, Args, RetType>,
    ) -> Result<R>
116
117
    where
        T: EnvTypes,
118
        Args: scale::Encode,
Hero Bird's avatar
Hero Bird committed
119
        R: scale::Decode,
120
    {
Hero Bird's avatar
Hero Bird committed
121
122
123
124
        let mut scope = self.scoped_buffer();
        let gas_limit = params.gas_limit();
        let enc_callee = scope.take_encoded(params.callee());
        let enc_transferred_value = scope.take_encoded(params.transferred_value());
125
        let enc_input = scope.take_encoded(params.exec_input());
Hero Bird's avatar
Hero Bird committed
126
        let output = &mut scope.take_rest();
127
        ext::call(
Hero Bird's avatar
Hero Bird committed
128
129
130
131
132
133
134
135
            enc_callee,
            gas_limit,
            enc_transferred_value,
            enc_input,
            output,
        )?;
        let decoded = scale::Decode::decode(&mut &output[..])?;
        Ok(decoded)
136
137
138
139
    }
}

impl Env for EnvInstance {
140
    fn set_contract_storage<V>(&mut self, key: &Key, value: &V)
141
142
143
    where
        V: scale::Encode,
    {
Hero Bird's avatar
Hero Bird committed
144
145
        let buffer = self.scoped_buffer().take_encoded(value);
        ext::set_storage(key.as_bytes(), &buffer[..]);
146
147
    }

Hero Bird's avatar
Hero Bird committed
148
    fn get_contract_storage<R>(&mut self, key: &Key) -> Result<Option<R>>
149
150
151
    where
        R: scale::Decode,
    {
Hero Bird's avatar
Hero Bird committed
152
153
154
155
156
        let output = &mut self.scoped_buffer().take_rest();
        match ext::get_storage(key.as_bytes(), output) {
            Ok(_) => (),
            Err(ExtError::KeyNotFound) => return Ok(None),
            Err(_) => panic!("encountered unexpected error"),
157
        }
Hero Bird's avatar
Hero Bird committed
158
159
        let decoded = scale::Decode::decode(&mut &output[..])?;
        Ok(Some(decoded))
160
161
    }

162
    fn clear_contract_storage(&mut self, key: &Key) {
163
164
165
        ext::clear_storage(key.as_bytes())
    }

166
167
168
169
    fn decode_input<T>(&mut self) -> Result<T>
    where
        T: scale::Decode,
    {
Hero Bird's avatar
Hero Bird committed
170
        self.get_property::<T>(ext::input)
171
172
    }

Hero Bird's avatar
Hero Bird committed
173
    fn return_value<R>(&mut self, flags: ReturnFlags, return_value: &R) -> !
174
175
176
    where
        R: scale::Encode,
    {
Hero Bird's avatar
Hero Bird committed
177
178
179
        let mut scope = self.scoped_buffer();
        let enc_return_value = scope.take_encoded(return_value);
        ext::return_value(flags, enc_return_value);
180
181
182
183
184
    }

    fn println(&mut self, content: &str) {
        ext::println(content)
    }
185

186
187
188
189
190
    fn hash_bytes<H>(&mut self, input: &[u8], output: &mut <H as HashOutput>::Type)
    where
        H: CryptoHash,
    {
        <H as CryptoHash>::hash(input, output)
191
192
    }

193
194
195
196
197
198
199
200
    fn hash_encoded<H, T>(&mut self, input: &T, output: &mut <H as HashOutput>::Type)
    where
        H: CryptoHash,
        T: scale::Encode,
    {
        let mut scope = self.scoped_buffer();
        let enc_input = scope.take_encoded(input);
        <H as CryptoHash>::hash(enc_input, output)
201
    }
Hero Bird's avatar
Hero Bird committed
202
203

    #[cfg(feature = "ink-unstable-chain-extensions")]
204
    fn call_chain_extension<I, O>(&mut self, func_id: u32, input: &I) -> Result<O>
Hero Bird's avatar
Hero Bird committed
205
206
207
208
209
210
211
212
213
214
    where
        I: scale::Encode,
        O: scale::Decode,
    {
        let mut scope = self.scoped_buffer();
        let enc_input = scope.take_encoded(input);
        let output = &mut scope.take_rest();
        ext::call_chain_extension(func_id, enc_input, output)?;
        scale::Decode::decode(&mut &output[..]).map_err(Into::into)
    }
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
}

impl TypedEnv for EnvInstance {
    fn caller<T: EnvTypes>(&mut self) -> Result<T::AccountId> {
        self.get_property::<T::AccountId>(ext::caller)
    }

    fn transferred_balance<T: EnvTypes>(&mut self) -> Result<T::Balance> {
        self.get_property::<T::Balance>(ext::value_transferred)
    }

    fn gas_left<T: EnvTypes>(&mut self) -> Result<T::Balance> {
        self.get_property::<T::Balance>(ext::gas_left)
    }

    fn block_timestamp<T: EnvTypes>(&mut self) -> Result<T::Timestamp> {
        self.get_property::<T::Timestamp>(ext::now)
    }

    fn account_id<T: EnvTypes>(&mut self) -> Result<T::AccountId> {
        self.get_property::<T::AccountId>(ext::address)
    }

    fn balance<T: EnvTypes>(&mut self) -> Result<T::Balance> {
        self.get_property::<T::Balance>(ext::balance)
    }

    fn rent_allowance<T: EnvTypes>(&mut self) -> Result<T::Balance> {
        self.get_property::<T::Balance>(ext::rent_allowance)
    }

    fn block_number<T: EnvTypes>(&mut self) -> Result<T::BlockNumber> {
        self.get_property::<T::BlockNumber>(ext::block_number)
    }

    fn minimum_balance<T: EnvTypes>(&mut self) -> Result<T::Balance> {
        self.get_property::<T::Balance>(ext::minimum_balance)
    }

    fn tombstone_deposit<T: EnvTypes>(&mut self) -> Result<T::Balance> {
        self.get_property::<T::Balance>(ext::tombstone_deposit)
    }

    fn emit_event<T, Event>(&mut self, event: Event)
    where
        T: EnvTypes,
        Event: Topics<T> + scale::Encode,
    {
Hero Bird's avatar
Hero Bird committed
263
264
265
266
        let mut scope = self.scoped_buffer();
        let enc_topics = scope.take_encoded(&event.topics());
        let enc_data = scope.take_encoded(&event);
        ext::deposit_event(enc_topics, enc_data);
267
268
269
270
271
272
    }

    fn set_rent_allowance<T>(&mut self, new_value: T::Balance)
    where
        T: EnvTypes,
    {
Hero Bird's avatar
Hero Bird committed
273
274
        let buffer = self.scoped_buffer().take_encoded(&new_value);
        ext::set_rent_allowance(&buffer[..])
275
276
    }

277
278
279
280
    fn invoke_contract<T, Args>(
        &mut self,
        call_params: &CallParams<T, Args, ()>,
    ) -> Result<()>
281
282
    where
        T: EnvTypes,
283
        Args: scale::Encode,
284
285
286
287
    {
        self.invoke_contract_impl(call_params)
    }

288
    fn eval_contract<T, Args, R>(
289
        &mut self,
290
        call_params: &CallParams<T, Args, ReturnType<R>>,
291
292
293
    ) -> Result<R>
    where
        T: EnvTypes,
294
        Args: scale::Encode,
295
296
        R: scale::Decode,
    {
Hero Bird's avatar
Hero Bird committed
297
        self.invoke_contract_impl(call_params)
298
299
    }

300
    fn instantiate_contract<T, Args, C>(
301
        &mut self,
302
        params: &CreateParams<T, Args, C>,
303
304
305
    ) -> Result<T::AccountId>
    where
        T: EnvTypes,
306
        Args: scale::Encode,
307
    {
Hero Bird's avatar
Hero Bird committed
308
309
310
311
        let mut scoped = self.scoped_buffer();
        let gas_limit = params.gas_limit();
        let enc_code_hash = scoped.take_encoded(params.code_hash());
        let enc_endowment = scoped.take_encoded(params.endowment());
312
        let enc_input = scoped.take_encoded(params.exec_input());
Hero Bird's avatar
Hero Bird committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
        // We support `AccountId` types with an encoding that requires up to
        // 1024 bytes. Beyond that limit ink! contracts will trap for now.
        // In the default configuration encoded `AccountId` require 32 bytes.
        let out_address = &mut scoped.take(1024);
        let out_return_value = &mut scoped.take_rest();
        // We currently do nothing with the `out_return_value` buffer.
        // This should change in the future but for that we need to add support
        // for constructors that may return values.
        // This is useful to support fallible constructors for example.
        ext::instantiate(
            enc_code_hash,
            gas_limit,
            enc_endowment,
            enc_input,
            out_address,
            out_return_value,
        )?;
        let account_id = scale::Decode::decode(&mut &out_address[..])?;
        Ok(account_id)
332
333
334
335
336
337
338
339
340
341
342
    }

    fn restore_contract<T>(
        &mut self,
        account_id: T::AccountId,
        code_hash: T::Hash,
        rent_allowance: T::Balance,
        filtered_keys: &[Key],
    ) where
        T: EnvTypes,
    {
Hero Bird's avatar
Hero Bird committed
343
344
345
346
347
348
349
350
351
352
        let mut scope = self.scoped_buffer();
        let enc_account_id = scope.take_encoded(&account_id);
        let enc_code_hash = scope.take_encoded(&code_hash);
        let enc_rent_allowance = scope.take_encoded(&rent_allowance);
        ext::restore_to(
            enc_account_id,
            enc_code_hash,
            enc_rent_allowance,
            filtered_keys,
        );
353
354
    }

355
356
357
358
    fn terminate_contract<T>(&mut self, beneficiary: T::AccountId) -> !
    where
        T: EnvTypes,
    {
Hero Bird's avatar
Hero Bird committed
359
360
        let buffer = self.scoped_buffer().take_encoded(&beneficiary);
        ext::terminate(&buffer[..]);
361
362
    }

363
364
365
366
    fn transfer<T>(&mut self, destination: T::AccountId, value: T::Balance) -> Result<()>
    where
        T: EnvTypes,
    {
Hero Bird's avatar
Hero Bird committed
367
368
369
370
        let mut scope = self.scoped_buffer();
        let enc_destination = scope.take_encoded(&destination);
        let enc_value = scope.take_encoded(&value);
        ext::transfer(enc_destination, enc_value).map_err(Into::into)
371
372
    }

Hero Bird's avatar
Hero Bird committed
373
374
375
376
    fn weight_to_fee<T: EnvTypes>(&mut self, gas: u64) -> Result<T::Balance> {
        let output = &mut self.scoped_buffer().take_rest();
        ext::weight_to_fee(gas, output);
        scale::Decode::decode(&mut &output[..]).map_err(Into::into)
377
378
    }

379
380
381
382
    fn random<T>(&mut self, subject: &[u8]) -> Result<T::Hash>
    where
        T: EnvTypes,
    {
Hero Bird's avatar
Hero Bird committed
383
384
385
386
387
        let mut scope = self.scoped_buffer();
        let enc_subject = scope.take_bytes(subject);
        let output = &mut scope.take_rest();
        ext::random(enc_subject, output);
        scale::Decode::decode(&mut &output[..]).map_err(Into::into)
388
389
    }
}