1 /* EVMC: Ethereum Client-VM Connector API.
2  * Copyright 2018-2020 The EVMC Authors.
3  * Licensed under the Apache License, Version 2.0.
4  */
5 #pragma once
6 
7 #include <evmc/evmc.h>
8 #include <evmc/helpers.h>
9 
10 #include <functional>
11 #include <initializer_list>
12 #include <utility>
13 
14 /// EVMC C++ API - wrappers and bindings for C++
15 /// @ingroup cpp
16 namespace evmc
17 {
18 /// The big-endian 160-bit hash suitable for keeping an Ethereum address.
19 ///
20 /// This type wraps C ::evmc_address to make sure objects of this type are always initialized.
21 struct address : evmc_address
22 {
23     /// Default and converting constructor.
24     ///
25     /// Initializes bytes to zeros if not other @p init value provided.
addressevmc::address26     constexpr address(evmc_address init = {}) noexcept : evmc_address{init} {}
27 
28     /// Converting constructor from unsigned integer value.
29     ///
30     /// This constructor assigns the @p v value to the last 8 bytes [12:19]
31     /// in big-endian order.
addressevmc::address32     constexpr explicit address(uint64_t v) noexcept
33       : evmc_address{{0,
34                       0,
35                       0,
36                       0,
37                       0,
38                       0,
39                       0,
40                       0,
41                       0,
42                       0,
43                       0,
44                       0,
45                       static_cast<uint8_t>(v >> 56),
46                       static_cast<uint8_t>(v >> 48),
47                       static_cast<uint8_t>(v >> 40),
48                       static_cast<uint8_t>(v >> 32),
49                       static_cast<uint8_t>(v >> 24),
50                       static_cast<uint8_t>(v >> 16),
51                       static_cast<uint8_t>(v >> 8),
52                       static_cast<uint8_t>(v >> 0)}}
53     {}
54 
55     /// Explicit operator converting to bool.
56     inline constexpr explicit operator bool() const noexcept;
57 };
58 
59 /// The fixed size array of 32 bytes for storing 256-bit EVM values.
60 ///
61 /// This type wraps C ::evmc_bytes32 to make sure objects of this type are always initialized.
62 struct bytes32 : evmc_bytes32
63 {
64     /// Default and converting constructor.
65     ///
66     /// Initializes bytes to zeros if not other @p init value provided.
bytes32evmc::bytes3267     constexpr bytes32(evmc_bytes32 init = {}) noexcept : evmc_bytes32{init} {}
68 
69     /// Converting constructor from unsigned integer value.
70     ///
71     /// This constructor assigns the @p v value to the last 8 bytes [24:31]
72     /// in big-endian order.
bytes32evmc::bytes3273     constexpr explicit bytes32(uint64_t v) noexcept
74       : evmc_bytes32{{0,
75                       0,
76                       0,
77                       0,
78                       0,
79                       0,
80                       0,
81                       0,
82                       0,
83                       0,
84                       0,
85                       0,
86                       0,
87                       0,
88                       0,
89                       0,
90                       0,
91                       0,
92                       0,
93                       0,
94                       0,
95                       0,
96                       0,
97                       0,
98                       static_cast<uint8_t>(v >> 56),
99                       static_cast<uint8_t>(v >> 48),
100                       static_cast<uint8_t>(v >> 40),
101                       static_cast<uint8_t>(v >> 32),
102                       static_cast<uint8_t>(v >> 24),
103                       static_cast<uint8_t>(v >> 16),
104                       static_cast<uint8_t>(v >> 8),
105                       static_cast<uint8_t>(v >> 0)}}
106     {}
107 
108     /// Explicit operator converting to bool.
109     constexpr inline explicit operator bool() const noexcept;
110 };
111 
112 /// The alias for evmc::bytes32 to represent a big-endian 256-bit integer.
113 using uint256be = bytes32;
114 
115 
116 /// Loads 64 bits / 8 bytes of data from the given @p data array in big-endian order.
load64be(const uint8_t * data)117 inline constexpr uint64_t load64be(const uint8_t* data) noexcept
118 {
119     return (uint64_t{data[0]} << 56) | (uint64_t{data[1]} << 48) | (uint64_t{data[2]} << 40) |
120            (uint64_t{data[3]} << 32) | (uint64_t{data[4]} << 24) | (uint64_t{data[5]} << 16) |
121            (uint64_t{data[6]} << 8) | uint64_t{data[7]};
122 }
123 
124 /// Loads 64 bits / 8 bytes of data from the given @p data array in little-endian order.
load64le(const uint8_t * data)125 inline constexpr uint64_t load64le(const uint8_t* data) noexcept
126 {
127     return uint64_t{data[0]} | (uint64_t{data[1]} << 8) | (uint64_t{data[2]} << 16) |
128            (uint64_t{data[3]} << 24) | (uint64_t{data[4]} << 32) | (uint64_t{data[5]} << 40) |
129            (uint64_t{data[6]} << 48) | (uint64_t{data[7]} << 56);
130 }
131 
132 /// Loads 32 bits / 4 bytes of data from the given @p data array in big-endian order.
load32be(const uint8_t * data)133 inline constexpr uint32_t load32be(const uint8_t* data) noexcept
134 {
135     return (uint32_t{data[0]} << 24) | (uint32_t{data[1]} << 16) | (uint32_t{data[2]} << 8) |
136            uint32_t{data[3]};
137 }
138 
139 /// Loads 32 bits / 4 bytes of data from the given @p data array in little-endian order.
load32le(const uint8_t * data)140 inline constexpr uint32_t load32le(const uint8_t* data) noexcept
141 {
142     return uint32_t{data[0]} | (uint32_t{data[1]} << 8) | (uint32_t{data[2]} << 16) |
143            (uint32_t{data[3]} << 24);
144 }
145 
146 namespace fnv
147 {
148 constexpr auto prime = 0x100000001b3;              ///< The 64-bit FNV prime number.
149 constexpr auto offset_basis = 0xcbf29ce484222325;  ///< The 64-bit FNV offset basis.
150 
151 /// The hashing transformation for 64-bit inputs based on the FNV-1a formula.
fnv1a_by64(uint64_t h,uint64_t x)152 inline constexpr uint64_t fnv1a_by64(uint64_t h, uint64_t x) noexcept
153 {
154     return (h ^ x) * prime;
155 }
156 }  // namespace fnv
157 
158 
159 /// The "equal to" comparison operator for the evmc::address type.
operator ==(const address & a,const address & b)160 inline constexpr bool operator==(const address& a, const address& b) noexcept
161 {
162     return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) &&
163            load64le(&a.bytes[8]) == load64le(&b.bytes[8]) &&
164            load32le(&a.bytes[16]) == load32le(&b.bytes[16]);
165 }
166 
167 /// The "not equal to" comparison operator for the evmc::address type.
operator !=(const address & a,const address & b)168 inline constexpr bool operator!=(const address& a, const address& b) noexcept
169 {
170     return !(a == b);
171 }
172 
173 /// The "less than" comparison operator for the evmc::address type.
operator <(const address & a,const address & b)174 inline constexpr bool operator<(const address& a, const address& b) noexcept
175 {
176     return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) ||
177            (load64be(&a.bytes[0]) == load64be(&b.bytes[0]) &&
178             (load64be(&a.bytes[8]) < load64be(&b.bytes[8]) ||
179              (load64be(&a.bytes[8]) == load64be(&b.bytes[8]) &&
180               load32be(&a.bytes[16]) < load32be(&b.bytes[16]))));
181 }
182 
183 /// The "greater than" comparison operator for the evmc::address type.
operator >(const address & a,const address & b)184 inline constexpr bool operator>(const address& a, const address& b) noexcept
185 {
186     return b < a;
187 }
188 
189 /// The "less than or equal to" comparison operator for the evmc::address type.
operator <=(const address & a,const address & b)190 inline constexpr bool operator<=(const address& a, const address& b) noexcept
191 {
192     return !(b < a);
193 }
194 
195 /// The "greater than or equal to" comparison operator for the evmc::address type.
operator >=(const address & a,const address & b)196 inline constexpr bool operator>=(const address& a, const address& b) noexcept
197 {
198     return !(a < b);
199 }
200 
201 /// The "equal to" comparison operator for the evmc::bytes32 type.
operator ==(const bytes32 & a,const bytes32 & b)202 inline constexpr bool operator==(const bytes32& a, const bytes32& b) noexcept
203 {
204     return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) &&
205            load64le(&a.bytes[8]) == load64le(&b.bytes[8]) &&
206            load64le(&a.bytes[16]) == load64le(&b.bytes[16]) &&
207            load64le(&a.bytes[24]) == load64le(&b.bytes[24]);
208 }
209 
210 /// The "not equal to" comparison operator for the evmc::bytes32 type.
operator !=(const bytes32 & a,const bytes32 & b)211 inline constexpr bool operator!=(const bytes32& a, const bytes32& b) noexcept
212 {
213     return !(a == b);
214 }
215 
216 /// The "less than" comparison operator for the evmc::bytes32 type.
operator <(const bytes32 & a,const bytes32 & b)217 inline constexpr bool operator<(const bytes32& a, const bytes32& b) noexcept
218 {
219     return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) ||
220            (load64be(&a.bytes[0]) == load64be(&b.bytes[0]) &&
221             (load64be(&a.bytes[8]) < load64be(&b.bytes[8]) ||
222              (load64be(&a.bytes[8]) == load64be(&b.bytes[8]) &&
223               (load64be(&a.bytes[16]) < load64be(&b.bytes[16]) ||
224                (load64be(&a.bytes[16]) == load64be(&b.bytes[16]) &&
225                 load64be(&a.bytes[24]) < load64be(&b.bytes[24]))))));
226 }
227 
228 /// The "greater than" comparison operator for the evmc::bytes32 type.
operator >(const bytes32 & a,const bytes32 & b)229 inline constexpr bool operator>(const bytes32& a, const bytes32& b) noexcept
230 {
231     return b < a;
232 }
233 
234 /// The "less than or equal to" comparison operator for the evmc::bytes32 type.
operator <=(const bytes32 & a,const bytes32 & b)235 inline constexpr bool operator<=(const bytes32& a, const bytes32& b) noexcept
236 {
237     return !(b < a);
238 }
239 
240 /// The "greater than or equal to" comparison operator for the evmc::bytes32 type.
operator >=(const bytes32 & a,const bytes32 & b)241 inline constexpr bool operator>=(const bytes32& a, const bytes32& b) noexcept
242 {
243     return !(a < b);
244 }
245 
246 /// Checks if the given address is the zero address.
is_zero(const address & a)247 inline constexpr bool is_zero(const address& a) noexcept
248 {
249     return a == address{};
250 }
251 
operator bool() const252 inline constexpr address::operator bool() const noexcept
253 {
254     return !is_zero(*this);
255 }
256 
257 /// Checks if the given bytes32 object has all zero bytes.
is_zero(const bytes32 & a)258 inline constexpr bool is_zero(const bytes32& a) noexcept
259 {
260     return a == bytes32{};
261 }
262 
operator bool() const263 inline constexpr bytes32::operator bool() const noexcept
264 {
265     return !is_zero(*this);
266 }
267 
268 namespace literals
269 {
270 namespace internal
271 {
from_hex(char c)272 constexpr int from_hex(char c) noexcept
273 {
274     return (c >= 'a' && c <= 'f') ? c - ('a' - 10) :
275                                     (c >= 'A' && c <= 'F') ? c - ('A' - 10) : c - '0';
276 }
277 
byte(const char * s,size_t i)278 constexpr uint8_t byte(const char* s, size_t i) noexcept
279 {
280     return static_cast<uint8_t>((from_hex(s[2 * i]) << 4) | from_hex(s[2 * i + 1]));
281 }
282 
283 template <typename T>
284 T from_hex(const char*) noexcept;
285 
286 template <>
from_hex(const char * s)287 constexpr bytes32 from_hex<bytes32>(const char* s) noexcept
288 {
289     return {
290         {{byte(s, 0),  byte(s, 1),  byte(s, 2),  byte(s, 3),  byte(s, 4),  byte(s, 5),  byte(s, 6),
291           byte(s, 7),  byte(s, 8),  byte(s, 9),  byte(s, 10), byte(s, 11), byte(s, 12), byte(s, 13),
292           byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19), byte(s, 20),
293           byte(s, 21), byte(s, 22), byte(s, 23), byte(s, 24), byte(s, 25), byte(s, 26), byte(s, 27),
294           byte(s, 28), byte(s, 29), byte(s, 30), byte(s, 31)}}};
295 }
296 
297 template <>
from_hex(const char * s)298 constexpr address from_hex<address>(const char* s) noexcept
299 {
300     return {
301         {{byte(s, 0),  byte(s, 1),  byte(s, 2),  byte(s, 3),  byte(s, 4),  byte(s, 5),  byte(s, 6),
302           byte(s, 7),  byte(s, 8),  byte(s, 9),  byte(s, 10), byte(s, 11), byte(s, 12), byte(s, 13),
303           byte(s, 14), byte(s, 15), byte(s, 16), byte(s, 17), byte(s, 18), byte(s, 19)}}};
304 }
305 
306 template <typename T, char... c>
from_literal()307 constexpr T from_literal() noexcept
308 {
309     constexpr auto size = sizeof...(c);
310     constexpr char literal[] = {c...};
311     constexpr bool is_simple_zero = size == 1 && literal[0] == '0';
312 
313     static_assert(is_simple_zero || (literal[0] == '0' && literal[1] == 'x'),
314                   "literal must be in hexadecimal notation");
315     static_assert(is_simple_zero || size == 2 * sizeof(T) + 2,
316                   "literal must match the result type size");
317 
318     return is_simple_zero ? T{} : from_hex<T>(&literal[2]);
319 }
320 }  // namespace internal
321 
322 /// Literal for evmc::address.
323 template <char... c>
operator ""_address()324 constexpr address operator""_address() noexcept
325 {
326     return internal::from_literal<address, c...>();
327 }
328 
329 /// Literal for evmc::bytes32.
330 template <char... c>
operator ""_bytes32()331 constexpr bytes32 operator""_bytes32() noexcept
332 {
333     return internal::from_literal<bytes32, c...>();
334 }
335 }  // namespace literals
336 
337 using namespace literals;
338 
339 /// Alias for evmc_make_result().
340 constexpr auto make_result = evmc_make_result;
341 
342 /// @copydoc evmc_result
343 ///
344 /// This is a RAII wrapper for evmc_result and objects of this type
345 /// automatically release attached resources.
346 class result : private evmc_result
347 {
348 public:
349     using evmc_result::create_address;
350     using evmc_result::gas_left;
351     using evmc_result::output_data;
352     using evmc_result::output_size;
353     using evmc_result::status_code;
354 
355     /// Creates the result from the provided arguments.
356     ///
357     /// The provided output is copied to memory allocated with malloc()
358     /// and the evmc_result::release function is set to one invoking free().
359     ///
360     /// @param _status_code  The status code.
361     /// @param _gas_left     The amount of gas left.
362     /// @param _output_data  The pointer to the output.
363     /// @param _output_size  The output size.
result(evmc_status_code _status_code,int64_t _gas_left,const uint8_t * _output_data,size_t _output_size)364     result(evmc_status_code _status_code,
365            int64_t _gas_left,
366            const uint8_t* _output_data,
367            size_t _output_size) noexcept
368       : evmc_result{make_result(_status_code, _gas_left, _output_data, _output_size)}
369     {}
370 
371     /// Converting constructor from raw evmc_result.
result(evmc_result const & res)372     explicit result(evmc_result const& res) noexcept : evmc_result{res} {}
373 
374     /// Destructor responsible for automatically releasing attached resources.
~result()375     ~result() noexcept
376     {
377         if (release != nullptr)
378             release(this);
379     }
380 
381     /// Move constructor.
result(result && other)382     result(result&& other) noexcept : evmc_result{other}
383     {
384         other.release = nullptr;  // Disable releasing of the rvalue object.
385     }
386 
387     /// Move assignment operator.
388     ///
389     /// The self-assigment MUST never happen.
390     ///
391     /// @param other The other result object.
392     /// @return      The reference to the left-hand side object.
operator =(result && other)393     result& operator=(result&& other) noexcept
394     {
395         this->~result();                           // Release this object.
396         static_cast<evmc_result&>(*this) = other;  // Copy data.
397         other.release = nullptr;                   // Disable releasing of the rvalue object.
398         return *this;
399     }
400 
401     /// Releases the ownership and returns the raw copy of evmc_result.
402     ///
403     /// This method drops the ownership of the result
404     /// (result's resources are not going to be released when this object is destructed).
405     /// It is the caller's responsibility having the returned copy of the result to release it.
406     /// This object MUST NOT be used after this method is invoked.
407     ///
408     /// @return  The copy of this object converted to raw evmc_result.
release_raw()409     evmc_result release_raw() noexcept
410     {
411         const auto out = evmc_result{*this};  // Copy data.
412         this->release = nullptr;              // Disable releasing of this object.
413         return out;
414     }
415 };
416 
417 
418 /// The EVMC Host interface
419 class HostInterface
420 {
421 public:
422     virtual ~HostInterface() noexcept = default;
423 
424     /// @copydoc evmc_host_interface::account_exists
425     virtual bool account_exists(const address& addr) const noexcept = 0;
426 
427     /// @copydoc evmc_host_interface::get_storage
428     virtual bytes32 get_storage(const address& addr, const bytes32& key) const noexcept = 0;
429 
430     /// @copydoc evmc_host_interface::set_storage
431     virtual evmc_storage_status set_storage(const address& addr,
432                                             const bytes32& key,
433                                             const bytes32& value) noexcept = 0;
434 
435     /// @copydoc evmc_host_interface::get_balance
436     virtual uint256be get_balance(const address& addr) const noexcept = 0;
437 
438     /// @copydoc evmc_host_interface::get_code_size
439     virtual size_t get_code_size(const address& addr) const noexcept = 0;
440 
441     /// @copydoc evmc_host_interface::get_code_hash
442     virtual bytes32 get_code_hash(const address& addr) const noexcept = 0;
443 
444     /// @copydoc evmc_host_interface::copy_code
445     virtual size_t copy_code(const address& addr,
446                              size_t code_offset,
447                              uint8_t* buffer_data,
448                              size_t buffer_size) const noexcept = 0;
449 
450     /// @copydoc evmc_host_interface::selfdestruct
451     virtual void selfdestruct(const address& addr, const address& beneficiary) noexcept = 0;
452 
453     /// @copydoc evmc_host_interface::call
454     virtual result call(const evmc_message& msg) noexcept = 0;
455 
456     /// @copydoc evmc_host_interface::get_tx_context
457     virtual evmc_tx_context get_tx_context() const noexcept = 0;
458 
459     /// @copydoc evmc_host_interface::get_block_hash
460     virtual bytes32 get_block_hash(int64_t block_number) const noexcept = 0;
461 
462     /// @copydoc evmc_host_interface::emit_log
463     virtual void emit_log(const address& addr,
464                           const uint8_t* data,
465                           size_t data_size,
466                           const bytes32 topics[],
467                           size_t num_topics) noexcept = 0;
468 
469     /// @copydoc evmc_host_interface::access_account
470     virtual evmc_access_status access_account(const address& addr) noexcept = 0;
471 
472     /// @copydoc evmc_host_interface::access_storage
473     virtual evmc_access_status access_storage(const address& addr, const bytes32& key) noexcept = 0;
474 };
475 
476 
477 /// Wrapper around EVMC host context / host interface.
478 ///
479 /// To be used by VM implementations as better alternative to using ::evmc_host_context directly.
480 class HostContext : public HostInterface
481 {
482     const evmc_host_interface* host = nullptr;
483     evmc_host_context* context = nullptr;
484     mutable evmc_tx_context tx_context = {};
485 
486 public:
487     /// Default constructor for null Host context.
488     HostContext() = default;
489 
490     /// Constructor from the EVMC Host primitives.
491     /// @param interface  The reference to the Host interface.
492     /// @param ctx        The pointer to the Host context object. This parameter MAY be null.
HostContext(const evmc_host_interface & interface,evmc_host_context * ctx)493     HostContext(const evmc_host_interface& interface, evmc_host_context* ctx) noexcept
494       : host{&interface}, context{ctx}
495     {}
496 
account_exists(const address & address) const497     bool account_exists(const address& address) const noexcept final
498     {
499         return host->account_exists(context, &address);
500     }
501 
get_storage(const address & address,const bytes32 & key) const502     bytes32 get_storage(const address& address, const bytes32& key) const noexcept final
503     {
504         return host->get_storage(context, &address, &key);
505     }
506 
set_storage(const address & address,const bytes32 & key,const bytes32 & value)507     evmc_storage_status set_storage(const address& address,
508                                     const bytes32& key,
509                                     const bytes32& value) noexcept final
510     {
511         return host->set_storage(context, &address, &key, &value);
512     }
513 
get_balance(const address & address) const514     uint256be get_balance(const address& address) const noexcept final
515     {
516         return host->get_balance(context, &address);
517     }
518 
get_code_size(const address & address) const519     size_t get_code_size(const address& address) const noexcept final
520     {
521         return host->get_code_size(context, &address);
522     }
523 
get_code_hash(const address & address) const524     bytes32 get_code_hash(const address& address) const noexcept final
525     {
526         return host->get_code_hash(context, &address);
527     }
528 
copy_code(const address & address,size_t code_offset,uint8_t * buffer_data,size_t buffer_size) const529     size_t copy_code(const address& address,
530                      size_t code_offset,
531                      uint8_t* buffer_data,
532                      size_t buffer_size) const noexcept final
533     {
534         return host->copy_code(context, &address, code_offset, buffer_data, buffer_size);
535     }
536 
selfdestruct(const address & addr,const address & beneficiary)537     void selfdestruct(const address& addr, const address& beneficiary) noexcept final
538     {
539         host->selfdestruct(context, &addr, &beneficiary);
540     }
541 
call(const evmc_message & message)542     result call(const evmc_message& message) noexcept final
543     {
544         return result{host->call(context, &message)};
545     }
546 
547     /// @copydoc HostInterface::get_tx_context()
548     ///
549     /// The implementation caches the received transaction context
550     /// by assuming that the block timestamp should never be zero.
551     ///
552     /// @return The cached transaction context.
get_tx_context() const553     evmc_tx_context get_tx_context() const noexcept final
554     {
555         if (tx_context.block_timestamp == 0)
556             tx_context = host->get_tx_context(context);
557         return tx_context;
558     }
559 
get_block_hash(int64_t number) const560     bytes32 get_block_hash(int64_t number) const noexcept final
561     {
562         return host->get_block_hash(context, number);
563     }
564 
emit_log(const address & addr,const uint8_t * data,size_t data_size,const bytes32 topics[],size_t topics_count)565     void emit_log(const address& addr,
566                   const uint8_t* data,
567                   size_t data_size,
568                   const bytes32 topics[],
569                   size_t topics_count) noexcept final
570     {
571         host->emit_log(context, &addr, data, data_size, topics, topics_count);
572     }
573 
access_account(const address & address)574     evmc_access_status access_account(const address& address) noexcept final
575     {
576         return host->access_account(context, &address);
577     }
578 
access_storage(const address & address,const bytes32 & key)579     evmc_access_status access_storage(const address& address, const bytes32& key) noexcept final
580     {
581         return host->access_storage(context, &address, &key);
582     }
583 };
584 
585 
586 /// Abstract class to be used by Host implementations.
587 ///
588 /// When implementing EVMC Host, you can directly inherit from the evmc::Host class.
589 /// This way your implementation will be simpler by avoiding manual handling
590 /// of the ::evmc_host_context and the ::evmc_host_interface.
591 class Host : public HostInterface
592 {
593 public:
594     /// Provides access to the global host interface.
595     /// @returns  Reference to the host interface object.
596     static const evmc_host_interface& get_interface() noexcept;
597 
598     /// Converts the Host object to the opaque host context pointer.
599     /// @returns  Pointer to evmc_host_context.
to_context()600     evmc_host_context* to_context() noexcept { return reinterpret_cast<evmc_host_context*>(this); }
601 
602     /// Converts the opaque host context pointer back to the original Host object.
603     /// @tparam DerivedClass  The class derived from the Host class.
604     /// @param context        The opaque host context pointer.
605     /// @returns              The pointer to DerivedClass.
606     template <typename DerivedClass = Host>
from_context(evmc_host_context * context)607     static DerivedClass* from_context(evmc_host_context* context) noexcept
608     {
609         // Get pointer of the Host base class.
610         auto* h = reinterpret_cast<Host*>(context);
611 
612         // Additional downcast, only possible if DerivedClass inherits from Host.
613         return static_cast<DerivedClass*>(h);
614     }
615 };
616 
617 
618 /// @copybrief evmc_vm
619 ///
620 /// This is a RAII wrapper for evmc_vm, and object of this type
621 /// automatically destroys the VM instance.
622 class VM
623 {
624 public:
625     VM() noexcept = default;
626 
627     /// Converting constructor from evmc_vm.
VM(evmc_vm * vm)628     explicit VM(evmc_vm* vm) noexcept : m_instance{vm} {}
629 
630     /// Destructor responsible for automatically destroying the VM instance.
~VM()631     ~VM() noexcept
632     {
633         if (m_instance != nullptr)
634             m_instance->destroy(m_instance);
635     }
636 
637     VM(const VM&) = delete;
638     VM& operator=(const VM&) = delete;
639 
640     /// Move constructor.
VM(VM && other)641     VM(VM&& other) noexcept : m_instance{other.m_instance} { other.m_instance = nullptr; }
642 
643     /// Move assignment operator.
operator =(VM && other)644     VM& operator=(VM&& other) noexcept
645     {
646         this->~VM();
647         m_instance = other.m_instance;
648         other.m_instance = nullptr;
649         return *this;
650     }
651 
652     /// The constructor that captures a VM instance and configures the instance
653     /// with the provided list of options.
654     inline VM(evmc_vm* vm,
655               std::initializer_list<std::pair<const char*, const char*>> options) noexcept;
656 
657     /// Checks if contains a valid pointer to the VM instance.
operator bool() const658     explicit operator bool() const noexcept { return m_instance != nullptr; }
659 
660     /// Checks whenever the VM instance is ABI compatible with the current EVMC API.
is_abi_compatible() const661     bool is_abi_compatible() const noexcept { return m_instance->abi_version == EVMC_ABI_VERSION; }
662 
663     /// @copydoc evmc_vm::name
name() const664     char const* name() const noexcept { return m_instance->name; }
665 
666     /// @copydoc evmc_vm::version
version() const667     char const* version() const noexcept { return m_instance->version; }
668 
669     /// Checks if the VM has the given capability.
has_capability(evmc_capabilities capability) const670     bool has_capability(evmc_capabilities capability) const noexcept
671     {
672         return (get_capabilities() & static_cast<evmc_capabilities_flagset>(capability)) != 0;
673     }
674 
675     /// @copydoc evmc_vm::get_capabilities
get_capabilities() const676     evmc_capabilities_flagset get_capabilities() const noexcept
677     {
678         return m_instance->get_capabilities(m_instance);
679     }
680 
681     /// @copydoc evmc_set_option()
set_option(const char name[],const char value[])682     evmc_set_option_result set_option(const char name[], const char value[]) noexcept
683     {
684         return evmc_set_option(m_instance, name, value);
685     }
686 
687     /// @copydoc evmc_execute()
execute(const evmc_host_interface & host,evmc_host_context * ctx,evmc_revision rev,const evmc_message & msg,const uint8_t * code,size_t code_size)688     result execute(const evmc_host_interface& host,
689                    evmc_host_context* ctx,
690                    evmc_revision rev,
691                    const evmc_message& msg,
692                    const uint8_t* code,
693                    size_t code_size) noexcept
694     {
695         return result{m_instance->execute(m_instance, &host, ctx, rev, &msg, code, code_size)};
696     }
697 
698     /// Convenient variant of the VM::execute() that takes reference to evmc::Host class.
execute(Host & host,evmc_revision rev,const evmc_message & msg,const uint8_t * code,size_t code_size)699     result execute(Host& host,
700                    evmc_revision rev,
701                    const evmc_message& msg,
702                    const uint8_t* code,
703                    size_t code_size) noexcept
704     {
705         return execute(Host::get_interface(), host.to_context(), rev, msg, code, code_size);
706     }
707 
708     /// Executes code without the Host context.
709     ///
710     /// The same as
711     /// execute(const evmc_host_interface&, evmc_host_context*, evmc_revision,
712     ///         const evmc_message&, const uint8_t*, size_t),
713     /// but without providing the Host context and interface.
714     /// This method is for experimental precompiles support where execution is
715     /// guaranteed not to require any Host access.
execute(evmc_revision rev,const evmc_message & msg,const uint8_t * code,size_t code_size)716     result execute(evmc_revision rev,
717                    const evmc_message& msg,
718                    const uint8_t* code,
719                    size_t code_size) noexcept
720     {
721         return result{
722             m_instance->execute(m_instance, nullptr, nullptr, rev, &msg, code, code_size)};
723     }
724 
725     /// Returns the pointer to C EVMC struct representing the VM.
726     ///
727     /// Gives access to the C EVMC VM struct to allow advanced interaction with the VM not supported
728     /// by the C++ interface. Use as the last resort.
729     /// This object still owns the VM after returning the pointer. The returned pointer MAY be null.
get_raw_pointer() const730     evmc_vm* get_raw_pointer() const noexcept { return m_instance; }
731 
732 private:
733     evmc_vm* m_instance = nullptr;
734 };
735 
VM(evmc_vm * vm,std::initializer_list<std::pair<const char *,const char * >> options)736 inline VM::VM(evmc_vm* vm,
737               std::initializer_list<std::pair<const char*, const char*>> options) noexcept
738   : m_instance{vm}
739 {
740     // This constructor is implemented outside of the class definition to workaround a doxygen bug.
741     for (const auto& option : options)
742         set_option(option.first, option.second);
743 }
744 
745 
746 namespace internal
747 {
account_exists(evmc_host_context * h,const evmc_address * addr)748 inline bool account_exists(evmc_host_context* h, const evmc_address* addr) noexcept
749 {
750     return Host::from_context(h)->account_exists(*addr);
751 }
752 
get_storage(evmc_host_context * h,const evmc_address * addr,const evmc_bytes32 * key)753 inline evmc_bytes32 get_storage(evmc_host_context* h,
754                                 const evmc_address* addr,
755                                 const evmc_bytes32* key) noexcept
756 {
757     return Host::from_context(h)->get_storage(*addr, *key);
758 }
759 
set_storage(evmc_host_context * h,const evmc_address * addr,const evmc_bytes32 * key,const evmc_bytes32 * value)760 inline evmc_storage_status set_storage(evmc_host_context* h,
761                                        const evmc_address* addr,
762                                        const evmc_bytes32* key,
763                                        const evmc_bytes32* value) noexcept
764 {
765     return Host::from_context(h)->set_storage(*addr, *key, *value);
766 }
767 
get_balance(evmc_host_context * h,const evmc_address * addr)768 inline evmc_uint256be get_balance(evmc_host_context* h, const evmc_address* addr) noexcept
769 {
770     return Host::from_context(h)->get_balance(*addr);
771 }
772 
get_code_size(evmc_host_context * h,const evmc_address * addr)773 inline size_t get_code_size(evmc_host_context* h, const evmc_address* addr) noexcept
774 {
775     return Host::from_context(h)->get_code_size(*addr);
776 }
777 
get_code_hash(evmc_host_context * h,const evmc_address * addr)778 inline evmc_bytes32 get_code_hash(evmc_host_context* h, const evmc_address* addr) noexcept
779 {
780     return Host::from_context(h)->get_code_hash(*addr);
781 }
782 
copy_code(evmc_host_context * h,const evmc_address * addr,size_t code_offset,uint8_t * buffer_data,size_t buffer_size)783 inline size_t copy_code(evmc_host_context* h,
784                         const evmc_address* addr,
785                         size_t code_offset,
786                         uint8_t* buffer_data,
787                         size_t buffer_size) noexcept
788 {
789     return Host::from_context(h)->copy_code(*addr, code_offset, buffer_data, buffer_size);
790 }
791 
selfdestruct(evmc_host_context * h,const evmc_address * addr,const evmc_address * beneficiary)792 inline void selfdestruct(evmc_host_context* h,
793                          const evmc_address* addr,
794                          const evmc_address* beneficiary) noexcept
795 {
796     Host::from_context(h)->selfdestruct(*addr, *beneficiary);
797 }
798 
call(evmc_host_context * h,const evmc_message * msg)799 inline evmc_result call(evmc_host_context* h, const evmc_message* msg) noexcept
800 {
801     return Host::from_context(h)->call(*msg).release_raw();
802 }
803 
get_tx_context(evmc_host_context * h)804 inline evmc_tx_context get_tx_context(evmc_host_context* h) noexcept
805 {
806     return Host::from_context(h)->get_tx_context();
807 }
808 
get_block_hash(evmc_host_context * h,int64_t block_number)809 inline evmc_bytes32 get_block_hash(evmc_host_context* h, int64_t block_number) noexcept
810 {
811     return Host::from_context(h)->get_block_hash(block_number);
812 }
813 
emit_log(evmc_host_context * h,const evmc_address * addr,const uint8_t * data,size_t data_size,const evmc_bytes32 topics[],size_t num_topics)814 inline void emit_log(evmc_host_context* h,
815                      const evmc_address* addr,
816                      const uint8_t* data,
817                      size_t data_size,
818                      const evmc_bytes32 topics[],
819                      size_t num_topics) noexcept
820 {
821     Host::from_context(h)->emit_log(*addr, data, data_size, static_cast<const bytes32*>(topics),
822                                     num_topics);
823 }
824 
access_account(evmc_host_context * h,const evmc_address * addr)825 inline evmc_access_status access_account(evmc_host_context* h, const evmc_address* addr) noexcept
826 {
827     return Host::from_context(h)->access_account(*addr);
828 }
829 
access_storage(evmc_host_context * h,const evmc_address * addr,const evmc_bytes32 * key)830 inline evmc_access_status access_storage(evmc_host_context* h,
831                                          const evmc_address* addr,
832                                          const evmc_bytes32* key) noexcept
833 {
834     return Host::from_context(h)->access_storage(*addr, *key);
835 }
836 }  // namespace internal
837 
get_interface()838 inline const evmc_host_interface& Host::get_interface() noexcept
839 {
840     static constexpr evmc_host_interface interface{
841         ::evmc::internal::account_exists, ::evmc::internal::get_storage,
842         ::evmc::internal::set_storage,    ::evmc::internal::get_balance,
843         ::evmc::internal::get_code_size,  ::evmc::internal::get_code_hash,
844         ::evmc::internal::copy_code,      ::evmc::internal::selfdestruct,
845         ::evmc::internal::call,           ::evmc::internal::get_tx_context,
846         ::evmc::internal::get_block_hash, ::evmc::internal::emit_log,
847         ::evmc::internal::access_account, ::evmc::internal::access_storage,
848     };
849     return interface;
850 }
851 }  // namespace evmc
852 
853 
854 namespace std
855 {
856 /// Hash operator template specialization for evmc::address. Needed for unordered containers.
857 template <>
858 struct hash<evmc::address>
859 {
860     /// Hash operator using FNV1a-based folding.
operator ()std::hash861     constexpr size_t operator()(const evmc::address& s) const noexcept
862     {
863         using namespace evmc;
864         using namespace fnv;
865         return static_cast<size_t>(fnv1a_by64(
866             fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])), load64le(&s.bytes[8])),
867             load32le(&s.bytes[16])));
868     }
869 };
870 
871 /// Hash operator template specialization for evmc::bytes32. Needed for unordered containers.
872 template <>
873 struct hash<evmc::bytes32>
874 {
875     /// Hash operator using FNV1a-based folding.
operator ()std::hash876     constexpr size_t operator()(const evmc::bytes32& s) const noexcept
877     {
878         using namespace evmc;
879         using namespace fnv;
880         return static_cast<size_t>(
881             fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])),
882                                              load64le(&s.bytes[8])),
883                                   load64le(&s.bytes[16])),
884                        load64le(&s.bytes[24])));
885     }
886 };
887 }  // namespace std
888