ext.rs 20.9 KB
Newer Older
1
// Copyright 2018-2021 Parity Technologies (UK) Ltd.
2
//
3
4
5
// 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
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
10
11
12
13
// 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.
14
15
16

//! External C API to communicate with substrate contracts runtime module.
//!
17
//! Refer to substrate FRAME contract module for more documentation.
18

19
use crate::ReturnFlags;
Hero Bird's avatar
Hero Bird committed
20
use core::marker::PhantomData;
21
22
use ink_primitives::Key;

Hero Bird's avatar
Hero Bird committed
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
macro_rules! define_error_codes {
    (
        $(
            $( #[$attr:meta] )*
            $name:ident = $discr:literal,
        )*
    ) => {
        /// Every error that can be returned to a contract when it calls any of the host functions.
        #[repr(u32)]
        pub enum Error {
            $(
                $( #[$attr] )*
                $name = $discr,
            )*
            /// Returns if an unknown error was received from the host module.
            UnknownError,
        }

        impl From<ReturnCode> for Result {
            #[inline]
            fn from(return_code: ReturnCode) -> Self {
                match return_code.0 {
                    0 => Ok(()),
                    $(
                        $discr => Err(Error::$name),
                    )*
                    _ => Err(Error::UnknownError),
                }
            }
        }
    };
}
define_error_codes! {
    /// The called function trapped and has its state changes reverted.
    /// In this case no output buffer is returned.
    /// Can only be returned from `seal_call` and `seal_instantiate`.
    CalleeTrapped = 1,
    /// The called function ran to completion but decided to revert its state.
    /// An output buffer is returned when one was supplied.
    /// Can only be returned from `seal_call` and `seal_instantiate`.
    CalleeReverted = 2,
    /// The passed key does not exist in storage.
    KeyNotFound = 3,
    /// Transfer failed because it would have brought the sender's total balance
67
    /// below the subsistence threshold.
Hero Bird's avatar
Hero Bird committed
68
69
70
71
72
73
74
75
76
77
78
    BelowSubsistenceThreshold = 4,
    /// Transfer failed for other not further specified reason. Most probably
    /// reserved or locked balance of the sender that was preventing the transfer.
    TransferFailed = 5,
    /// The newly created contract is below the subsistence threshold after executing
    /// its constructor so no usable contract instance will be created.
    NewContractNotFunded = 6,
    /// No code could be found at the supplied code hash.
    CodeNotFound = 7,
    /// The account that was called is either no contract (e.g. user account) or is a tombstone.
    NotCallable = 8,
79
80
81
     /// The call to `seal_debug_message` had no effect because debug message
    /// recording was disabled.
    LoggingDisabled = 9,
Hero Bird's avatar
Hero Bird committed
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
}

/// Thin-wrapper around a `u32` representing a pointer for Wasm32.
///
/// Only for shared references.
///
/// # Note
///
/// Can only be constructed from shared reference types and encapsulates the
/// conversion from reference to raw `u32`.
/// Does not allow accessing the internal `u32` value.
#[derive(Debug)]
#[repr(transparent)]
pub struct Ptr32<'a, T>
where
    T: ?Sized,
{
    /// The internal Wasm32 raw pointer value.
    ///
    /// Must not be readable or directly usable by any safe Rust code.
    value: u32,
    /// We handle types like these as if the associated lifetime was exclusive.
    marker: PhantomData<fn() -> &'a T>,
}

impl<'a, T> Ptr32<'a, T>
where
    T: ?Sized,
{
    /// Creates a new Wasm32 pointer for the given raw pointer value.
    fn new(value: u32) -> Self {
        Self {
            value,
            marker: Default::default(),
        }
    }
}

impl<'a, T> Ptr32<'a, [T]> {
    /// Creates a new Wasm32 pointer from the given shared slice.
    pub fn from_slice(slice: &'a [T]) -> Self {
        Self::new(slice.as_ptr() as u32)
    }
}

/// Thin-wrapper around a `u32` representing a pointer for Wasm32.
///
/// Only for exclusive references.
///
/// # Note
///
/// Can only be constructed from exclusive reference types and encapsulates the
/// conversion from reference to raw `u32`.
/// Does not allow accessing the internal `u32` value.
#[derive(Debug)]
#[repr(transparent)]
pub struct Ptr32Mut<'a, T>
where
    T: ?Sized,
{
    /// The internal Wasm32 raw pointer value.
    ///
    /// Must not be readable or directly usable by any safe Rust code.
    value: u32,
    /// We handle types like these as if the associated lifetime was exclusive.
    marker: PhantomData<fn() -> &'a mut T>,
}

impl<'a, T> Ptr32Mut<'a, T>
where
    T: ?Sized,
{
    /// Creates a new Wasm32 pointer for the given raw pointer value.
    fn new(value: u32) -> Self {
        Self {
            value,
            marker: Default::default(),
        }
    }
}

impl<'a, T> Ptr32Mut<'a, [T]> {
    /// Creates a new Wasm32 pointer from the given exclusive slice.
    pub fn from_slice(slice: &'a mut [T]) -> Self {
        Self::new(slice.as_ptr() as u32)
    }
}

impl<'a, T> Ptr32Mut<'a, T>
where
    T: Sized,
{
    /// Creates a new Wasm32 pointer from the given exclusive reference.
    pub fn from_ref(a_ref: &'a mut T) -> Self {
        let a_ptr: *mut T = a_ref;
        Self::new(a_ptr as u32)
    }
}

/// The raw return code returned by the host side.
#[repr(transparent)]
pub struct ReturnCode(u32);

185
186
187
188
189
190
191
impl ReturnCode {
    /// Returns the raw underlying `u32` representation.
    pub fn into_u32(self) -> u32 {
        self.0
    }
}

Hero Bird's avatar
Hero Bird committed
192
type Result = core::result::Result<(), Error>;
193
194

mod sys {
Hero Bird's avatar
Hero Bird committed
195
196
197
198
199
200
201
202
    use super::{
        Key,
        Ptr32,
        Ptr32Mut,
        ReturnCode,
    };

    #[link(wasm_import_module = "seal0")]
203
    extern "C" {
Hero Bird's avatar
Hero Bird committed
204
205
        pub fn seal_instantiate(
            init_code_ptr: Ptr32<[u8]>,
206
207
            init_code_len: u32,
            gas: u64,
Hero Bird's avatar
Hero Bird committed
208
209
210
211
212
213
214
215
            endowment_ptr: Ptr32<[u8]>,
            endowment_len: u32,
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            address_ptr: Ptr32Mut<[u8]>,
            address_len_ptr: Ptr32Mut<u32>,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
216
217
            salt_ptr: Ptr32<[u8]>,
            salt_len: u32,
Hero Bird's avatar
Hero Bird committed
218
219
220
221
        ) -> ReturnCode;

        pub fn seal_call(
            callee_ptr: Ptr32<[u8]>,
222
223
            callee_len: u32,
            gas: u64,
Hero Bird's avatar
Hero Bird committed
224
225
226
227
228
229
230
231
232
233
            transferred_value_ptr: Ptr32<[u8]>,
            transferred_value_len: u32,
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        ) -> ReturnCode;

        pub fn seal_transfer(
            account_id_ptr: Ptr32<[u8]>,
234
            account_id_len: u32,
Hero Bird's avatar
Hero Bird committed
235
236
237
            transferred_value_ptr: Ptr32<[u8]>,
            transferred_value_len: u32,
        ) -> ReturnCode;
238

Hero Bird's avatar
Hero Bird committed
239
240
        pub fn seal_deposit_event(
            topics_ptr: Ptr32<[u8]>,
241
            topics_len: u32,
Hero Bird's avatar
Hero Bird committed
242
            data_ptr: Ptr32<[u8]>,
243
244
245
            data_len: u32,
        );

246
247
248
249
250
        pub fn seal_set_storage(
            key_ptr: Ptr32<[u8]>,
            value_ptr: Ptr32<[u8]>,
            value_len: u32,
        );
Hero Bird's avatar
Hero Bird committed
251
252
253
254
255
256
        pub fn seal_get_storage(
            key_ptr: Ptr32<[u8]>,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        ) -> ReturnCode;
        pub fn seal_clear_storage(key_ptr: Ptr32<[u8]>);
257

Hero Bird's avatar
Hero Bird committed
258
259
        pub fn seal_restore_to(
            dest_ptr: Ptr32<[u8]>,
260
            dest_len: u32,
Hero Bird's avatar
Hero Bird committed
261
            code_hash_ptr: Ptr32<[u8]>,
262
            code_hash_len: u32,
Hero Bird's avatar
Hero Bird committed
263
            rent_allowance_ptr: Ptr32<[u8]>,
264
            rent_allowance_len: u32,
Hero Bird's avatar
Hero Bird committed
265
            delta_ptr: Ptr32<[Key]>,
266
267
            delta_count: u32,
        );
Hero Bird's avatar
Hero Bird committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
        pub fn seal_terminate(beneficiary_ptr: Ptr32<[u8]>, beneficiary_len: u32) -> !;

        pub fn seal_call_chain_extension(
            func_id: u32,
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        ) -> ReturnCode;

        pub fn seal_input(buf_ptr: Ptr32Mut<[u8]>, buf_len_ptr: Ptr32Mut<u32>);
        pub fn seal_return(flags: u32, data_ptr: Ptr32<[u8]>, data_len: u32) -> !;

        pub fn seal_caller(output_ptr: Ptr32Mut<[u8]>, output_len_ptr: Ptr32Mut<u32>);
        pub fn seal_block_number(
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
        pub fn seal_address(output_ptr: Ptr32Mut<[u8]>, output_len_ptr: Ptr32Mut<u32>);
        pub fn seal_balance(output_ptr: Ptr32Mut<[u8]>, output_len_ptr: Ptr32Mut<u32>);
        pub fn seal_weight_to_fee(
            gas: u64,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
        pub fn seal_gas_left(output_ptr: Ptr32Mut<[u8]>, output_len_ptr: Ptr32Mut<u32>);
        pub fn seal_value_transferred(
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
        pub fn seal_now(output_ptr: Ptr32Mut<[u8]>, output_len_ptr: Ptr32Mut<u32>);
        pub fn seal_rent_allowance(
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
        pub fn seal_minimum_balance(
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
        pub fn seal_tombstone_deposit(
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );

        pub fn seal_set_rent_allowance(value_ptr: Ptr32<[u8]>, value_len: u32);

        pub fn seal_hash_keccak_256(
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
        );
        pub fn seal_hash_blake2_256(
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
        );
        pub fn seal_hash_blake2_128(
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
        );
        pub fn seal_hash_sha2_256(
            input_ptr: Ptr32<[u8]>,
            input_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
        );
334
    }
335
336
337
338
339
340
341
342
343
344

    #[link(wasm_import_module = "seal1")]
    extern "C" {
        pub fn seal_random(
            subject_ptr: Ptr32<[u8]>,
            subject_len: u32,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
    }
345
346
347

    #[link(wasm_import_module = "__unstable__")]
    extern "C" {
348
349
350
        #[cfg(feature = "ink-debug")]
        pub fn seal_debug_message(str_ptr: Ptr32<[u8]>, str_len: u32) -> ReturnCode;

351
352
353
354
        pub fn seal_rent_params(
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
355
356
357
358
359
360

        pub fn seal_rent_status(
            at_refcount: u32,
            output_ptr: Ptr32Mut<[u8]>,
            output_len_ptr: Ptr32Mut<u32>,
        );
361
    }
362
}
363

Hero Bird's avatar
Hero Bird committed
364
365
366
367
368
369
370
fn extract_from_slice(output: &mut &mut [u8], new_len: usize) {
    debug_assert!(new_len <= output.len());
    let tmp = core::mem::take(output);
    *output = &mut tmp[..new_len];
}

pub fn instantiate(
371
372
    code_hash: &[u8],
    gas_limit: u64,
Hero Bird's avatar
Hero Bird committed
373
374
375
376
    endowment: &[u8],
    input: &[u8],
    out_address: &mut &mut [u8],
    out_return_value: &mut &mut [u8],
377
    salt: &[u8],
Hero Bird's avatar
Hero Bird committed
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
) -> Result {
    let mut address_len = out_address.len() as u32;
    let mut return_value_len = out_return_value.len() as u32;
    let ret_code = {
        unsafe {
            sys::seal_instantiate(
                Ptr32::from_slice(code_hash),
                code_hash.len() as u32,
                gas_limit,
                Ptr32::from_slice(endowment),
                endowment.len() as u32,
                Ptr32::from_slice(input),
                input.len() as u32,
                Ptr32Mut::from_slice(out_address),
                Ptr32Mut::from_ref(&mut address_len),
                Ptr32Mut::from_slice(out_return_value),
                Ptr32Mut::from_ref(&mut return_value_len),
395
396
                Ptr32::from_slice(salt),
                salt.len() as u32,
Hero Bird's avatar
Hero Bird committed
397
398
            )
        }
399
    };
Hero Bird's avatar
Hero Bird committed
400
401
402
    extract_from_slice(out_address, address_len as usize);
    extract_from_slice(out_return_value, return_value_len as usize);
    ret_code.into()
403
404
}

Hero Bird's avatar
Hero Bird committed
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
pub fn call(
    callee: &[u8],
    gas_limit: u64,
    value: &[u8],
    input: &[u8],
    output: &mut &mut [u8],
) -> Result {
    let mut output_len = output.len() as u32;
    let ret_code = {
        unsafe {
            sys::seal_call(
                Ptr32::from_slice(callee),
                callee.len() as u32,
                gas_limit,
                Ptr32::from_slice(value),
                value.len() as u32,
                Ptr32::from_slice(input),
                input.len() as u32,
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        }
427
    };
Hero Bird's avatar
Hero Bird committed
428
429
    extract_from_slice(output, output_len as usize);
    ret_code.into()
430
431
}

Hero Bird's avatar
Hero Bird committed
432
pub fn transfer(account_id: &[u8], value: &[u8]) -> Result {
433
    let ret_code = unsafe {
Hero Bird's avatar
Hero Bird committed
434
435
        sys::seal_transfer(
            Ptr32::from_slice(account_id),
436
            account_id.len() as u32,
Hero Bird's avatar
Hero Bird committed
437
            Ptr32::from_slice(value),
438
439
440
            value.len() as u32,
        )
    };
Hero Bird's avatar
Hero Bird committed
441
    ret_code.into()
442
443
}

444
445
pub fn deposit_event(topics: &[u8], data: &[u8]) {
    unsafe {
Hero Bird's avatar
Hero Bird committed
446
447
        sys::seal_deposit_event(
            Ptr32::from_slice(topics),
448
            topics.len() as u32,
Hero Bird's avatar
Hero Bird committed
449
            Ptr32::from_slice(data),
450
451
452
453
454
            data.len() as u32,
        )
    }
}

455
456
pub fn set_storage(key: &[u8], encoded_value: &[u8]) {
    unsafe {
Hero Bird's avatar
Hero Bird committed
457
458
459
        sys::seal_set_storage(
            Ptr32::from_slice(key),
            Ptr32::from_slice(encoded_value),
460
461
            encoded_value.len() as u32,
        )
462
463
464
    }
}

465
pub fn clear_storage(key: &[u8]) {
Hero Bird's avatar
Hero Bird committed
466
    unsafe { sys::seal_clear_storage(Ptr32::from_slice(key)) }
467
468
}

Hero Bird's avatar
Hero Bird committed
469
470
471
472
473
474
475
476
477
478
pub fn get_storage(key: &[u8], output: &mut &mut [u8]) -> Result {
    let mut output_len = output.len() as u32;
    let ret_code = {
        unsafe {
            sys::seal_get_storage(
                Ptr32::from_slice(key),
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        }
479
    };
Hero Bird's avatar
Hero Bird committed
480
481
    extract_from_slice(output, output_len as usize);
    ret_code.into()
482
483
}

484
485
486
487
488
489
490
491
492
493
494
/// Restores a tombstone to the original smart contract.
///
/// # Params
///
/// - `account_id`: Encoded bytes of the `AccountId` of the to-be-restored contract.
/// - `code_hash`: Encoded code hash of the to-be-restored contract.
/// - `rent_allowance`: The encoded rent allowance of the restored contract
///                     upon successful restoration.
/// - `filtered_keys`: Storage keys that will be ignored for the tombstone hash
///                    match calculation that decide whether the original contract
///                    storage and the storage of the restorer contract is equal.
495
pub fn restore_to(
496
    account_id: &[u8],
497
498
499
500
501
    code_hash: &[u8],
    rent_allowance: &[u8],
    filtered_keys: &[Key],
) {
    unsafe {
Hero Bird's avatar
Hero Bird committed
502
503
        sys::seal_restore_to(
            Ptr32::from_slice(account_id),
504
            account_id.len() as u32,
Hero Bird's avatar
Hero Bird committed
505
            Ptr32::from_slice(code_hash),
506
            code_hash.len() as u32,
Hero Bird's avatar
Hero Bird committed
507
            Ptr32::from_slice(rent_allowance),
508
            rent_allowance.len() as u32,
Hero Bird's avatar
Hero Bird committed
509
            Ptr32::from_slice(filtered_keys),
510
511
512
513
514
            filtered_keys.len() as u32,
        )
    }
}

515
pub fn terminate(beneficiary: &[u8]) -> ! {
Hero Bird's avatar
Hero Bird committed
516
517
518
    unsafe {
        sys::seal_terminate(Ptr32::from_slice(beneficiary), beneficiary.len() as u32)
    }
519
520
}

521
pub fn call_chain_extension(func_id: u32, input: &[u8], output: &mut &mut [u8]) -> u32 {
Hero Bird's avatar
Hero Bird committed
522
523
524
525
526
527
528
529
530
531
532
533
534
    let mut output_len = output.len() as u32;
    let ret_code = {
        unsafe {
            sys::seal_call_chain_extension(
                func_id,
                Ptr32::from_slice(input),
                input.len() as u32,
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        }
    };
    extract_from_slice(output, output_len as usize);
535
    ret_code.into_u32()
536
537
}

Hero Bird's avatar
Hero Bird committed
538
539
540
541
542
543
544
545
546
547
548
pub fn input(output: &mut &mut [u8]) {
    let mut output_len = output.len() as u32;
    {
        unsafe {
            sys::seal_input(
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        };
    }
    extract_from_slice(output, output_len as usize);
549
550
}

Hero Bird's avatar
Hero Bird committed
551
552
553
554
555
556
557
558
pub fn return_value(flags: ReturnFlags, return_value: &[u8]) -> ! {
    unsafe {
        sys::seal_return(
            flags.into_u32(),
            Ptr32::from_slice(return_value),
            return_value.len() as u32,
        )
    }
559
560
}

Hero Bird's avatar
Hero Bird committed
561
562
macro_rules! impl_seal_wrapper_for {
    ( $( ($name:ident => $seal_name:ident), )* ) => {
563
        $(
Hero Bird's avatar
Hero Bird committed
564
565
566
567
568
569
570
571
572
            pub fn $name(output: &mut &mut [u8]) {
                let mut output_len = output.len() as u32;
                {
                    unsafe {
                        sys::$seal_name(
                            Ptr32Mut::from_slice(output),
                            Ptr32Mut::from_ref(&mut output_len),
                        )
                    };
573
                }
Hero Bird's avatar
Hero Bird committed
574
                extract_from_slice(output, output_len as usize);
575
576
577
578
            }
        )*
    }
}
Hero Bird's avatar
Hero Bird committed
579
580
581
582
583
584
585
586
587
588
589
impl_seal_wrapper_for! {
    (caller => seal_caller),
    (block_number => seal_block_number),
    (address => seal_address),
    (balance => seal_balance),
    (gas_left => seal_gas_left),
    (value_transferred => seal_value_transferred),
    (now => seal_now),
    (rent_allowance => seal_rent_allowance),
    (minimum_balance => seal_minimum_balance),
    (tombstone_deposit => seal_tombstone_deposit),
590
591
}

Hero Bird's avatar
Hero Bird committed
592
593
594
595
596
597
598
599
600
601
602
603
pub fn weight_to_fee(gas: u64, output: &mut &mut [u8]) {
    let mut output_len = output.len() as u32;
    {
        unsafe {
            sys::seal_weight_to_fee(
                gas,
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        };
    }
    extract_from_slice(output, output_len as usize);
604
605
}

606
pub fn set_rent_allowance(value: &[u8]) {
Hero Bird's avatar
Hero Bird committed
607
    unsafe { sys::seal_set_rent_allowance(Ptr32::from_slice(value), value.len() as u32) }
608
609
}

610
611
612
613
614
615
616
617
618
619
620
621
622
pub fn rent_params(output: &mut &mut [u8]) {
    let mut output_len = output.len() as u32;
    {
        unsafe {
            sys::seal_rent_params(
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        };
    }
    extract_from_slice(output, output_len as usize);
}

623
624
625
626
627
628
629
630
631
632
633
634
635
636
pub fn rent_status(at_refcount: Option<core::num::NonZeroU32>, output: &mut &mut [u8]) {
    let mut output_len = output.len() as u32;
    {
        unsafe {
            sys::seal_rent_status(
                at_refcount.map_or(0, |rc| rc.get()),
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        };
    }
    extract_from_slice(output, output_len as usize);
}

Hero Bird's avatar
Hero Bird committed
637
638
639
640
641
642
643
644
645
646
647
648
649
pub fn random(subject: &[u8], output: &mut &mut [u8]) {
    let mut output_len = output.len() as u32;
    {
        unsafe {
            sys::seal_random(
                Ptr32::from_slice(subject),
                subject.len() as u32,
                Ptr32Mut::from_slice(output),
                Ptr32Mut::from_ref(&mut output_len),
            )
        };
    }
    extract_from_slice(output, output_len as usize);
650
651
}

652
653
654
#[cfg(feature = "ink-debug")]
/// Call `seal_debug_message` with the supplied UTF-8 encoded message.
///
655
656
657
/// If debug message recording is disabled in the contracts pallet, the first call will
/// return a `LoggingDisabled` error, and further calls will be a no-op to avoid the cost
/// of calling into the supervisor.
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
///
/// # Note
///
/// This depends on the the `seal_debug_message` interface which requires the
/// `"pallet-contracts/unstable-interface"` feature to be enabled in the target runtime.
pub fn debug_message(message: &str) {
    static mut DEBUG_ENABLED: bool = true;

    // SAFETY: safe because executing in a single threaded context
    if unsafe { DEBUG_ENABLED } {
        let bytes = message.as_bytes();
        let ret_code = unsafe {
            sys::seal_debug_message(Ptr32::from_slice(bytes), bytes.len() as u32)
        };
        if let Err(Error::LoggingDisabled) = ret_code.into() {
            // SAFETY: safe because executing in a single threaded context
            unsafe { DEBUG_ENABLED = false }
        }
    }
677
}
678

679
680
681
682
#[cfg(not(feature = "ink-debug"))]
/// A no-op. Enable the `ink-debug` feature for debug messages.
pub fn debug_message(_message: &str) {}

683
684
685
686
687
macro_rules! impl_hash_fn {
    ( $name:ident, $bytes_result:literal ) => {
        paste::item! {
            pub fn [<hash_ $name>](input: &[u8], output: &mut [u8; $bytes_result]) {
                unsafe {
Hero Bird's avatar
Hero Bird committed
688
689
                    sys::[<seal_hash_ $name>](
                        Ptr32::from_slice(input),
690
                        input.len() as u32,
Hero Bird's avatar
Hero Bird committed
691
                        Ptr32Mut::from_slice(output),
692
693
694
695
696
697
698
699
700
701
                    )
                }
            }
        }
    };
}
impl_hash_fn!(sha2_256, 32);
impl_hash_fn!(keccak_256, 32);
impl_hash_fn!(blake2_256, 32);
impl_hash_fn!(blake2_128, 16);