Decentralised Art Server
High-performance C++ backend that exposes HTML interface and a secure REST API for managing Performative Transactions entities
 
Loading...
Searching...
No Matches
evm.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <string>
5#include <cstring>
6#include <filesystem>
7#include <vector>
8#include <expected>
9#include <fstream>
10#include <istream>
11
12// Undefine the conflicting macro
13#ifdef interface
14 #undef interface
15#endif
16
17#include <evmc/evmc.h>
18#include <evmc/evmc.hpp>
19#include <evmc/mocked_host.hpp>
20
21#include <evmc/hex.hpp>
22
23#include <evmone/evmone.h>
24
25#ifndef interface
26 #define interface __STRUCT__
27#endif
28
29#include "native.h"
30#include <asio.hpp>
31#include <spdlog/spdlog.h>
32#include <absl/container/flat_hash_map.h>
33
34#include "utils.hpp"
35#include "file.hpp"
36#include "keccak256.hpp"
37#include "pt.hpp"
38
39#include "evm_storage.hpp"
40#include "evm_formatter.hpp"
41
42namespace dcn::evm
43{
44 using Address = evmc::address;
45
60 {
85
86 evmc_bytes32 a{}; // first bytes32 (or zero)
87 uint32_t code{}; // for RegistryError
88 };
89
91 {
92 enum class Kind : std::uint8_t
93 {
94 UNKNOWN = 0,
96
98
99 evmc_bytes32 a{}; // first bytes32 (or zero)
100 };
101
102 class EVM
103 {
104 public:
105 EVM(asio::io_context & io_context, evmc_revision rev, std::filesystem::path solc_path);
106 ~EVM() = default;
107
108 EVM(const EVM&) = delete;
109 EVM& operator=(const EVM&) = delete;
110
111 EVM(EVM&&) = delete;
112 EVM& operator=(EVM&&) = delete;
113
114 asio::awaitable<bool> addAccount(Address address, std::uint64_t initial_gas) noexcept;
115 asio::awaitable<bool> setGas(Address address, std::uint64_t gas) noexcept;
116
117 asio::awaitable<bool> compile(std::filesystem::path code_path,
118 std::filesystem::path out_dir,
119 std::filesystem::path base_path = {},
120 std::filesystem::path includes = {}) const noexcept;
121
122 asio::awaitable<std::expected<Address, DeployError>> deploy(
123 std::istream & code_stream,
124 Address sender,
125 std::vector<std::uint8_t> constructor_args,
126 std::uint64_t gas_limit,
127 std::uint64_t value) noexcept;
128
129 asio::awaitable<std::expected<Address, DeployError>> deploy(
130 std::filesystem::path code_path,
131 Address sender,
132 std::vector<uint8_t> constructor_args,
133 std::uint64_t gas_limit,
134 std::uint64_t value) noexcept;
135
136 asio::awaitable<std::expected<std::vector<std::uint8_t>, ExecuteError>> execute(
137 Address sender,
138 Address recipient,
139 std::vector<std::uint8_t> input_bytes,
140 std::uint64_t gas_limit,
141 std::uint64_t value) noexcept;
142
145
146 protected:
147 asio::awaitable<bool> loadPT();
148
149 private:
150 asio::strand<asio::io_context::executor_type> _strand;
151
152 evmc::VM _vm;
153 evmc_revision _rev;
154
155 std::filesystem::path _solc_path;
156
157 EVMStorage _storage;
158
159 Address _genesis_address;
160 Address _console_log_address;
161
162 Address _registry_address;
163 Address _runner_address;
164 };
165 asio::awaitable<std::expected<std::vector<std::uint8_t>, ExecuteError>> fetchOwner(EVM & evm, const Address & address);
166
167 std::vector<std::uint8_t> constructSelector(std::string signature);
168
169 template<class T>
170 std::vector<std::uint8_t> encodeAsArg(const T & val);
171
172 template<>
173 std::vector<std::uint8_t> encodeAsArg<Address>(const Address & address);
174
175 template<>
176 std::vector<std::uint8_t> encodeAsArg<std::uint32_t>(const std::uint32_t & value);
177
178 template<>
179 std::vector<std::uint8_t> encodeAsArg<std::vector<std::uint32_t>>(const std::vector<std::uint32_t> & vec);
180
181 template<>
182 std::vector<std::uint8_t> encodeAsArg<std::vector<std::tuple<std::uint32_t, std::uint32_t>>>(const std::vector<std::tuple<std::uint32_t, std::uint32_t>>& vec);
183
184 template<>
185 std::vector<std::uint8_t> encodeAsArg<std::string>(const std::string& str);
186
187
188 template<class T>
189 T decodeReturnedValue(const std::vector<std::uint8_t> & bytes);
190
191
192 template<>
193 std::vector<std::vector<std::uint32_t>> decodeReturnedValue(const std::vector<std::uint8_t> & bytes);
194
195 template<>
196 Address decodeReturnedValue(const std::vector<std::uint8_t> & bytes);
197
198 template<>
199 std::vector<Samples> decodeReturnedValue(const std::vector<uint8_t> & bytes);
200}
201
202template <>
203struct std::formatter<dcn::evm::DeployError::Kind> : std::formatter<std::string> {
204 auto format(const dcn::evm::DeployError::Kind & err, format_context& ctx) const {
205 switch(err)
206 {
207 case dcn::evm::DeployError::Kind::INVALID_BYTECODE : return formatter<string>::format("Invalid bytecode", ctx);
208 case dcn::evm::DeployError::Kind::INVALID_ADDRESS : return formatter<string>::format("Invalid address", ctx);
209 case dcn::evm::DeployError::Kind::INVALID_DATA : return formatter<string>::format("Invalid data", ctx);
210 case dcn::evm::DeployError::Kind::COMPILATION_ERROR : return formatter<string>::format("Compilation error", ctx);
211
212 case dcn::evm::DeployError::Kind::FEATURE_ALREADY_REGISTERED : return formatter<string>::format("Feature already registered", ctx);
213 case dcn::evm::DeployError::Kind::FEATURE_MISSING : return formatter<string>::format("Feature missing", ctx);
214
215 case dcn::evm::DeployError::Kind::TRANSFORMATION_ALREADY_REGISTERED : return formatter<string>::format("Transformation already registered", ctx);
216 case dcn::evm::DeployError::Kind::TRANSFORMATION_ARGUMENTS_MISMATCH : return formatter<string>::format("Transformation arguments mismatch", ctx);
217 case dcn::evm::DeployError::Kind::TRANSFORMATION_MISSING : return formatter<string>::format("Transformation missing", ctx);
218
219 case dcn::evm::DeployError::Kind::CONDITION_ALREADY_REGISTERED : return formatter<string>::format("Condition already registered", ctx);
220 case dcn::evm::DeployError::Kind::CONDITION_ARGUMENTS_MISMATCH : return formatter<string>::format("Condition arguments mismatch", ctx);
221 case dcn::evm::DeployError::Kind::CONDITION_MISSING : return formatter<string>::format("Condition missing", ctx);
222
223 default: return formatter<string>::format("Unknown", ctx);
224 }
225 return formatter<string>::format("", ctx);
226 }
227};
228
229template <>
230struct std::formatter<dcn::evm::ExecuteError::Kind> : std::formatter<std::string> {
231 auto format(const dcn::evm::ExecuteError::Kind & err, format_context& ctx) const {
232 switch(err)
233 {
234 case dcn::evm::ExecuteError::Kind::CONDITION_NOT_MET : return formatter<string>::format("Condition not met", ctx);
235
236 default: return formatter<string>::format("Unknown", ctx);
237 }
238 return formatter<string>::format("", ctx);
239 }
240};
Definition evm.hpp:103
asio::awaitable< std::expected< std::vector< std::uint8_t >, ExecuteError > > execute(Address sender, Address recipient, std::vector< std::uint8_t > input_bytes, std::uint64_t gas_limit, std::uint64_t value) noexcept
Definition evm.cpp:564
Address getRunnerAddress() const
Definition evm.cpp:385
asio::awaitable< bool > loadPT()
Definition evm.cpp:619
EVM(EVM &&)=delete
~EVM()=default
EVM & operator=(EVM &&)=delete
asio::awaitable< bool > addAccount(Address address, std::uint64_t initial_gas) noexcept
Definition evm.cpp:390
asio::awaitable< std::expected< Address, DeployError > > deploy(std::istream &code_stream, Address sender, std::vector< std::uint8_t > constructor_args, std::uint64_t gas_limit, std::uint64_t value) noexcept
Definition evm.cpp:474
EVM(const EVM &)=delete
Address getRegistryAddress() const
Definition evm.cpp:380
asio::awaitable< bool > compile(std::filesystem::path code_path, std::filesystem::path out_dir, std::filesystem::path base_path={}, std::filesystem::path includes={}) const noexcept
Definition evm.cpp:426
asio::awaitable< bool > setGas(Address address, std::uint64_t gas) noexcept
Definition evm.cpp:412
EVM & operator=(const EVM &)=delete
Definition evm.hpp:43
std::vector< std::uint8_t > constructSelector(std::string signature)
Definition evm.cpp:5
T decodeReturnedValue(const std::vector< std::uint8_t > &bytes)
std::vector< std::uint8_t > encodeAsArg< std::string >(const std::string &str)
Definition evm.cpp:104
std::vector< std::uint8_t > encodeAsArg< Address >(const Address &address)
Definition evm.cpp:13
std::vector< std::uint8_t > encodeAsArg(const T &val)
std::vector< std::uint8_t > encodeAsArg< std::uint32_t >(const std::uint32_t &value)
Definition evm.cpp:21
evmc::address Address
Definition evm.hpp:44
asio::awaitable< std::expected< std::vector< std::uint8_t >, ExecuteError > > fetchOwner(EVM &evm, const Address &address)
Definition evm.cpp:339
Definition decentralised_art.hpp:29
Definition evm.hpp:60
enum dcn::evm::DeployError::Kind kind
Kind
Definition evm.hpp:62
uint32_t code
Definition evm.hpp:87
evmc_bytes32 a
Definition evm.hpp:86
Definition evm.hpp:91
Kind
Definition evm.hpp:93
evmc_bytes32 a
Definition evm.hpp:99
enum dcn::evm::ExecuteError::Kind kind
auto format(const dcn::evm::DeployError::Kind &err, format_context &ctx) const
Definition evm.hpp:204
auto format(const dcn::evm::ExecuteError::Kind &err, format_context &ctx) const
Definition evm.hpp:231