exec_env.rs 4.84 KB
Newer Older
Hero Bird's avatar
Hero Bird committed
1
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
2
// This file is part of ink!.
Hero Bird's avatar
Hero Bird committed
3
//
4
// ink! is free software: you can redistribute it and/or modify
Hero Bird's avatar
Hero Bird committed
5
6
7
8
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
9
// ink! is distributed in the hope that it will be useful,
Hero Bird's avatar
Hero Bird committed
10
11
12
13
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
15
// along with ink!.  If not, see <http://www.gnu.org/licenses/>.
Hero Bird's avatar
Hero Bird committed
16

Andrew Jones's avatar
Andrew Jones committed
17
use core::marker::PhantomData;
18
use crate::ContractState;
19
use ink_core::{
Andrew Jones's avatar
Andrew Jones committed
20
21
22
23
    env::{
        self,
        Env
    },
24
25
26
27
28
29
    storage::alloc::{
        Allocate,
        AllocateUsing,
        CellChunkAlloc,
        Initialize,
    },
30
};
31

32
/// Provides a safe interface to an environment given a contract state.
Andrew Jones's avatar
Andrew Jones committed
33
pub struct ExecutionEnv<State, Env> {
34
    /// The environment handler.
Andrew Jones's avatar
Andrew Jones committed
35
    env_handler: EnvHandler<Env>,
36
37
    /// The contract state.
    pub state: State,
38
39
}

Andrew Jones's avatar
Andrew Jones committed
40
impl<State, Env> AllocateUsing for ExecutionEnv<State, Env>
41
42
43
44
45
46
47
48
49
50
51
52
53
where
    State: ContractState,
{
    unsafe fn allocate_using<A>(alloc: &mut A) -> Self
    where
        A: Allocate,
    {
        let env_handler = AllocateUsing::allocate_using(alloc);
        let state = AllocateUsing::allocate_using(alloc);
        Self { env_handler, state }
    }
}

Andrew Jones's avatar
Andrew Jones committed
54
impl<State, Env> Initialize for ExecutionEnv<State, Env>
55
where
Robin Freyler's avatar
Robin Freyler committed
56
    State: ContractState,
57
{
58
59
60
    type Args = ();

    fn initialize(&mut self, _: Self::Args) {
61
62
        self.env_handler.initialize(());
        self.state.try_default_initialize();
63
64
65
    }
}

Andrew Jones's avatar
Andrew Jones committed
66
67
impl<State, Env> core::ops::Deref for ExecutionEnv<State, Env> {
    type Target = EnvHandler<Env>;
68
69
70
71
72
73

    fn deref(&self) -> &Self::Target {
        &self.env_handler
    }
}

Andrew Jones's avatar
Andrew Jones committed
74
impl<State, Env> core::ops::DerefMut for ExecutionEnv<State, Env> {
75
76
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.env_handler
77
    }
78
79
}

Andrew Jones's avatar
Andrew Jones committed
80
impl<State, Env> ExecutionEnv<State, Env> {
Robin Freyler's avatar
Robin Freyler committed
81
82
83
84
85
86
87
    /// Splits the execution environment into shared references
    /// to the environment handler and the state.
    ///
    /// # Note
    ///
    /// This can be useful if you want to implement a message as
    /// a method of the state to make it callable from other messages.
Andrew Jones's avatar
Andrew Jones committed
88
    pub fn split(&self) -> (&EnvHandler<Env>, &State) {
89
90
91
        (&self.env_handler, &self.state)
    }

Robin Freyler's avatar
Robin Freyler committed
92
93
94
95
96
97
98
    /// Splits the execution environment into mutable references
    /// to the environment handler and the state.
    ///
    /// # Note
    ///
    /// This can be useful if you want to implement a message as
    /// a method of the state to make it callable from other messages.
Andrew Jones's avatar
Andrew Jones committed
99
    pub fn split_mut(&mut self) -> (&mut EnvHandler<Env>, &mut State) {
100
101
102
103
104
105
        (&mut self.env_handler, &mut self.state)
    }
}

/// The actual handler for the environment and for dynamic
/// allocations and deallocations.
Andrew Jones's avatar
Andrew Jones committed
106
pub struct EnvHandler<T> {
107
108
    /// The dynamic allocator.
    pub dyn_alloc: CellChunkAlloc,
Andrew Jones's avatar
Andrew Jones committed
109
    env_marker: PhantomData<T>,
110
111
}

Andrew Jones's avatar
Andrew Jones committed
112
impl<T> AllocateUsing for EnvHandler<T> {
113
114
115
116
117
118
    unsafe fn allocate_using<A>(alloc: &mut A) -> Self
    where
        A: Allocate,
    {
        Self {
            dyn_alloc: AllocateUsing::allocate_using(alloc),
Andrew Jones's avatar
Andrew Jones committed
119
            env_marker: PhantomData,
120
121
122
123
        }
    }
}

Andrew Jones's avatar
Andrew Jones committed
124
impl<T> Initialize for EnvHandler<T> {
125
126
127
128
129
130
131
    type Args = ();

    fn initialize(&mut self, _: Self::Args) {
        self.dyn_alloc.initialize(())
    }
}

Andrew Jones's avatar
Andrew Jones committed
132
impl<T: Env> EnvHandler<T> {
133
    /// Returns the address of the current smart contract.
Andrew Jones's avatar
Andrew Jones committed
134
135
    pub fn address(&self) -> T::AccountId {
        T::address()
136
137
138
    }

    /// Returns the balance of the current smart contract.
Andrew Jones's avatar
Andrew Jones committed
139
140
    pub fn balance(&self) -> T::Balance {
        T::balance()
141
142
    }

143
    /// Returns the caller address of the current smart contract execution.
Andrew Jones's avatar
Andrew Jones committed
144
145
    pub fn caller(&self) -> T::AccountId {
        T::caller()
146
    }
147

148
    /// Returns from the current smart contract execution with the given value.
Andrew Jones's avatar
Andrew Jones committed
149
    pub unsafe fn r#return<V>(&self, val: V) -> !
150
    where
Andrew Jones's avatar
Andrew Jones committed
151
        V: parity_codec::Encode
152
    {
Andrew Jones's avatar
Andrew Jones committed
153
        env::r#return::<V, T>(val)
154
    }
155
156
157
158
159
160
161

    /// Prints the given content.
    ///
    /// # Note
    ///
    /// Only usable in development (`--dev`) chains.
    pub fn println(&self, content: &str) {
Andrew Jones's avatar
Andrew Jones committed
162
        T::println(content)
163
    }
164

165
    /// Deposits raw event data through the Contracts module.
Andrew Jones's avatar
Andrew Jones committed
166
167
    pub fn deposit_raw_event(&self, topics: &[T::Hash], event: &[u8]) {
        T::deposit_raw_event(topics, event)
168
169
    }

170
    /// Returns the random seed from the latest block.
Andrew Jones's avatar
Andrew Jones committed
171
172
    pub fn random_seed(&self) -> T::Hash {
        T::random_seed()
173
    }
174
175

    /// Returns the timestamp of the latest block.
Andrew Jones's avatar
Andrew Jones committed
176
177
    pub fn now(&self) -> T::Moment {
        T::now()
178
    }
179
180
181
182

    pub fn current_block(&self) -> T::BlockNumber {
        T::current_block()
    }
183
}